Restore the community photo after reload and reject empty, oversized, SVG, and spoofed uploads. #80

Merged
an.di merged 1 commits from adilallo/fix/CR-195-photo-upload into main 2026-09-10 21:57:52 +00:00
Owner

Overview

A photo picked before sign-in was saved in the browser, but after reload the preview was empty and there was no way to remove it. The picker also accepted empty files, huge files, SVGs, and text renamed as .png.

This restores the staged photo so it can be previewed and removed, and checks size, real file type, and whether the image can be read — on the device and on the server.

Changes

  • Community photo step rehydrates the staged file on mount and keeps the remove control
  • Remove clears the preview, the draft URL, and the staged file so sign-in cannot bring it back
  • Shared client/server validation: empty files, 5 MB photo / 10 MB attachment caps, magic-byte type (not the filename), image decode, and explicit SVG rejection
  • Clear errors for those cases; custom-method uploads use the same checker and error copy
  • Tests for restore/remove and for empty, oversized, SVG, and spoofed files

Screenshots

How to Test

  1. npm run devhttp://localhost:3000/create/community-upload (stay signed out).
  2. Restore / remove: add a photo, reload. The preview should return with Remove uploaded photo. Remove it; the Upload control should come back. Reload again — the photo should stay gone.
  3. Rejects: try a 0-byte file, a 17 MB file, an .svg, and a text file renamed .png. Each should show a specific error and should not stage or upload.
  4. Signed-in (optional): sign in, add a real JPEG/PNG/WebP/GIF under 5 MB. It should upload and persist. Invalid files should still be rejected before the request.
  5. Optional: npx tsc --noEmit and npx vitest run.

Notes

  • Anonymous picks still wait for sign-in to upload; validation runs before staging so a bad file never sits in IndexedDB.
  • Knip still reports unused seedDataRoot; that is unrelated.
## Overview A photo picked before sign-in was saved in the browser, but after reload the preview was empty and there was no way to remove it. The picker also accepted empty files, huge files, SVGs, and text renamed as `.png`. This restores the staged photo so it can be previewed and removed, and checks size, real file type, and whether the image can be read — on the device and on the server. ## Changes - Community photo step rehydrates the staged file on mount and keeps the remove control - Remove clears the preview, the draft URL, and the staged file so sign-in cannot bring it back - Shared client/server validation: empty files, 5 MB photo / 10 MB attachment caps, magic-byte type (not the filename), image decode, and explicit SVG rejection - Clear errors for those cases; custom-method uploads use the same checker and error copy - Tests for restore/remove and for empty, oversized, SVG, and spoofed files ## Screenshots ## How to Test 1. `npm run dev` → [http://localhost:3000/create/community-upload](http://localhost:3000/create/community-upload) (stay signed out). 2. **Restore / remove:** add a photo, reload. The preview should return with **Remove uploaded photo**. Remove it; the Upload control should come back. Reload again — the photo should stay gone. 3. **Rejects:** try a 0-byte file, a 17 MB file, an `.svg`, and a text file renamed `.png`. Each should show a specific error and should not stage or upload. 4. **Signed-in (optional):** sign in, add a real JPEG/PNG/WebP/GIF under 5 MB. It should upload and persist. Invalid files should still be rejected before the request. 5. Optional: `npx tsc --noEmit` and `npx vitest run`. ## Notes - Anonymous picks still wait for sign-in to upload; validation runs before staging so a bad file never sits in IndexedDB. - Knip still reports unused `seedDataRoot`; that is unrelated.
an.di added 1 commit 2026-09-10 21:57:27 +00:00
an.di self-assigned this 2026-09-10 21:57:47 +00:00
an.di merged commit 98945ceb7e into main 2026-09-10 21:57:52 +00:00
an.di deleted branch adilallo/fix/CR-195-photo-upload 2026-09-10 21:57:52 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: CommunityRule/community-rule#80