Add PDF upload, download and voice filter #5

Merged
mcp-bot merged 1 commit from feature/score-files into develop 2026-11-01 20:21:21 +01:00
Member

Why

Members need their parts before rehearsal, so the archive has to hold the actual PDFs. Sheet music must stay inside its group, and a homelab disk must not fill up from one oversized request. Everyone may reach every part of their group, but a member usually wants only their own.

What

  • ScoreFile with role, instrument, part number, sha256, size and page count
  • Files live under DATA_DIR/<group_id>/<score_set_id>/<file_id>.pdf; names are generated by the server
  • Download name follows <Archivnr>_<Titel>_<Instrument>.pdf and is built on delivery, so metadata changes rename nothing on disk
  • Upload checks: size, %PDF- header, opens in pypdf, not encrypted, at least one page, no duplicate within the score set. Written to a partial file and renamed atomically
  • BodySizeLimitMiddleware stops a request while it is being received, also without Content-Length
  • Voice filter: members see their own parts by default and can show all; editors and admins see all by default and can filter. Without a part number in the profile, all parts of the instrument match
  • Deleting a file or score set removes it from disk

Form fields that were parsed by hand are now typed, so manipulated values give a clean 422 instead of a 500. This also fixes the invitation and profile forms from the groups PR.

Verification

  • make lint and pytest pass (274 tests), including no-PDF, damaged, encrypted, oversized with and without Content-Length, duplicates and path traversal in the filename
  • The isolation sweep covers all new routes
  • Only synthetic PDFs are used in tests
## Why Members need their parts before rehearsal, so the archive has to hold the actual PDFs. Sheet music must stay inside its group, and a homelab disk must not fill up from one oversized request. Everyone may reach every part of their group, but a member usually wants only their own. ## What - `ScoreFile` with role, instrument, part number, sha256, size and page count - Files live under `DATA_DIR/<group_id>/<score_set_id>/<file_id>.pdf`; names are generated by the server - Download name follows `<Archivnr>_<Titel>_<Instrument>.pdf` and is built on delivery, so metadata changes rename nothing on disk - Upload checks: size, `%PDF-` header, opens in pypdf, not encrypted, at least one page, no duplicate within the score set. Written to a partial file and renamed atomically - `BodySizeLimitMiddleware` stops a request while it is being received, also without `Content-Length` - Voice filter: members see their own parts by default and can show all; editors and admins see all by default and can filter. Without a part number in the profile, all parts of the instrument match - Deleting a file or score set removes it from disk Form fields that were parsed by hand are now typed, so manipulated values give a clean 422 instead of a 500. This also fixes the invitation and profile forms from the groups PR. ## Verification - `make lint` and `pytest` pass (274 tests), including no-PDF, damaged, encrypted, oversized with and without `Content-Length`, duplicates and path traversal in the filename - The isolation sweep covers all new routes - Only synthetic PDFs are used in tests
Add PDF upload, download and voice filter
All checks were successful
test / test (pull_request) Successful in 6m12s
c2ddfc5530
mcp-bot merged commit 608d29f571 into develop 2026-11-01 20:21:21 +01:00
mcp-bot deleted branch feature/score-files 2026-11-01 20:21:22 +01:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
makeitsystems/Notenwart!5
No description provided.