Merge fix/security-review-batch-2: cross-event authz + upload OOM backstop
Brings the batch-2 security hardening into main (forked from the same base as the UX batch; auto-merged cleanly — verified both sides' edits to social.rs / main.rs coexist): - Cross-event authorization: toggle_like / list_comments / add_comment now event-scope the upload via Upload::find_by_id_and_event (404 on cross-event access); delete_comment uses Comment::soft_delete_in_event. Closes the gap where a guest could like/comment/list across events by upload UUID. - Upload OOM backstop: the /upload route gets DefaultBodyLimit::max(576 MiB) instead of disable(), so a multi-GB body can't be buffered before the handler's per-class size checks run. - upload.rs per-class size-limit refactor, XSS allowlist, deploy hardening (Caddyfile, Dockerfiles, docker-compose, .env.example), and a data-mode doc-comment clarifying the original-media route is capability-(UUID-)gated. The event-scope checks sit before, and batch-3's best-effort count broadcasts after, the like/comment mutations — both preserved. Verified: cargo build clean, svelte-check 0 errors.
This commit is contained in:
@@ -18,6 +18,10 @@ mod state;
|
||||
use config::AppConfig;
|
||||
use state::AppState;
|
||||
|
||||
/// Hard HTTP body cap for the upload endpoint (576 MiB). Backstop against
|
||||
/// memory-exhaustion; precise per-class size limits are enforced in the handler.
|
||||
const MAX_UPLOAD_BYTES: usize = 576 * 1024 * 1024;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
dotenvy::dotenv().ok();
|
||||
@@ -57,9 +61,13 @@ async fn main() -> Result<()> {
|
||||
.route("/api/v1/recover", post(auth::handlers::recover))
|
||||
.route("/api/v1/admin/login", post(auth::handlers::admin_login))
|
||||
.route("/api/v1/session", delete(auth::handlers::logout))
|
||||
// Upload — body limit disabled; size validation is done inside the handler
|
||||
// Upload — HTTP-level body cap as an OOM backstop. The handler still enforces
|
||||
// the precise per-class limits from DB config (max_image/video_size_mb); this
|
||||
// layer just stops a multi-GB body from being buffered into memory before that
|
||||
// check runs. Sized generously above the default 500 MB video limit + multipart
|
||||
// overhead — if an admin raises max_video_size_mb above this, bump MAX_UPLOAD_BYTES.
|
||||
.route("/api/v1/upload", post(handlers::upload::upload)
|
||||
.route_layer(DefaultBodyLimit::disable()))
|
||||
.route_layer(DefaultBodyLimit::max(MAX_UPLOAD_BYTES)))
|
||||
.route(
|
||||
"/api/v1/upload/{id}",
|
||||
patch(handlers::upload::edit_upload).delete(handlers::upload::delete_upload),
|
||||
|
||||
Reference in New Issue
Block a user