fix(audit): restore broken upload pipeline + role-based E2E audit fixes
A comprehensive role-based E2E audit (guest/host/admin, across browser sessions) surfaced one critical and several smaller issues; this addresses them and hardens the tests that missed them. Critical - The client upload pipeline was fully broken: the IndexedDB v1->v2 upgrade opened a *new* transaction inside the upgrade callback, which throws during a version-change transaction and aborted the whole upgrade, leaving the queue object store uncreated -- so no UI upload ever fired. Reuse the version-change transaction the callback provides, and bump the DB to v3 with a contains() guard so installs already corrupted by the shipped bug self-heal on next load. Re-enabled the previously-fixme'd UI upload E2E test. High / Medium - Event lock is uploads-only again: likes, comments and browsing stay open while the event is locked (USER_JOURNEYS 9.3 / FEATURES) -- it was wrongly freezing social interaction. Updated the event-lock spec accordingly. - get_original now excludes soft-deleted and ban-hidden uploads, and direct /media/originals/** serving is blocked, so a hidden user's originals can no longer be pulled by UUID (all originals go through the checked alias). - The upload handler reads the file field with an early-abort size cap chosen from the declared content-type, instead of buffering the entire body before the size check. Low - unban_user mirrors the ban role guard (a host can no longer unban a host/admin banned by an admin). - reset_user_pin's UPDATE is event-scoped. - Admin login returns and stores a real identity (user_id + display name) instead of a blank session. - The host user list no longer renders target-actions (ban/promote/demote/PIN) on the caller's own row, where the backend always rejected them. - /diashow gains a client-side auth guard like the other protected routes. - The join page shows the event name via a new public GET /api/v1/event. Verified: backend cargo build clean, frontend svelte-check 0 errors, full Playwright E2E suite 144 passed / 1 skipped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -12,18 +12,6 @@ use crate::models::hashtag::{self, Hashtag};
|
||||
use crate::models::upload::Upload;
|
||||
use crate::state::AppState;
|
||||
|
||||
/// Reject the request when the event's uploads (and, by extension, social
|
||||
/// interaction) are locked. Mirrors the guard in the upload handler.
|
||||
async fn require_event_open(state: &AppState) -> Result<(), AppError> {
|
||||
let event = crate::models::event::Event::find_by_slug(&state.pool, &state.config.event_slug)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound("Event nicht gefunden.".into()))?;
|
||||
if event.uploads_locked_at.is_some() {
|
||||
return Err(AppError::Forbidden("Das Event ist geschlossen.".into()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn toggle_like(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthUser,
|
||||
@@ -43,8 +31,9 @@ pub async fn toggle_like(
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound("Upload nicht gefunden.".into()))?;
|
||||
|
||||
// A closed event freezes social interaction too, matching the upload handler.
|
||||
require_event_open(&state).await?;
|
||||
// NOTE: liking is intentionally allowed while the event is locked. Locking
|
||||
// ("Event schließen") freezes *new uploads* only — likes, comments and
|
||||
// browsing stay open (USER_JOURNEYS §9.3, FEATURES capability matrix).
|
||||
|
||||
// Try to insert; if conflict, delete (toggle)
|
||||
let result = sqlx::query(
|
||||
@@ -135,8 +124,9 @@ pub async fn add_comment(
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound("Upload nicht gefunden.".into()))?;
|
||||
|
||||
// A closed event freezes social interaction too, matching the upload handler.
|
||||
require_event_open(&state).await?;
|
||||
// NOTE: commenting is intentionally allowed while the event is locked. Locking
|
||||
// freezes *new uploads* only — likes, comments and browsing stay open
|
||||
// (USER_JOURNEYS §9.3, FEATURES capability matrix).
|
||||
|
||||
let text = body.body.trim();
|
||||
let text_chars = text.chars().count();
|
||||
|
||||
Reference in New Issue
Block a user