summaryrefslogtreecommitdiff
path: root/player-server/internal/repository
AgeCommit message (Collapse)Author
2026-05-22Add migration for missing playback_progress.finished column (5f)Paul Buetow
Existing databases created before the finished column was added to the base schema still satisfied CREATE TABLE IF NOT EXISTS and never got the column, causing GET /api/v1/media/{id} to fail with "SQL logic error: no such column: finished" and break media detail view. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20Merge j9+i9: LIKE wildcard escaping and CreateUser password validationPaul Buetow
- escapeLike() helper in repository/media.go for LIKE search safety - ErrWeakPassword sentinel in service.go (min 8 chars, HTTP 400) - CreateUser rejects empty/short passwords in service/user.go - ErrWeakPassword auto-dispatched via HTTPStatuser (no switch needed) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20Embed CoreStore in service store interfaces (ca)Paul Buetow
Several per-service Store interfaces declared the same four-repo block (UserRepo + SetRepo + SetPermissionRepo + MediaRepo) verbatim. Extract that into a CoreStore interface and have MediaServiceStore, AdminServiceStore, AccessHelperStore, BrowseServiceStore, and WriteServiceStore embed it. Repository structurally still satisfies every interface; tests unaffected. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19Fix four defects flagged by S19/S20/S24; tighten scenariosPaul Buetow
1. tagService.AssignTag and RemoveTag now use verifyModifyAccess (owner role required) instead of verifyAccess. Tags are global state visible to every user with access to a media item, so a viewer must not be able to add or remove them. Favorites and notes stay on verifyAccess because they're per-user data (favorites.user_id, media_notes.user_id) and don't affect anyone else. Verified via curl: viewer POST /media/{id}/tags now 403, admin still 200. 2. serveFileResult now emits a strong ETag header ("<size>-<mtime-nanos>") before calling http.ServeContent. Go's ServeContent honours If-None-Match when ETag is set, so iOS audio clients and podcast apps can revalidate cached downloads with conditional GETs. Verified via curl: ETag present on /stream; If-None-Match matching the ETag returns 304. 3. MediaFilter gains IncludeDeleted flag; ListMedia skips the implicit `deleted_at IS NULL` predicate when it is set. FSScanner.loadExistingMedia now passes IncludeDeleted=true so the dedup map includes soft-deleted rows. Previously a re-scan of a soft-deleted file tried to CreateMedia and hit the UNIQUE(set_id, rel_path) constraint, failing the whole scan and setting progress.last_error. Now the rescan skips the row cleanly; soft-delete sticks. 4. FSScanner.reconcileOrphans soft-deletes media rows whose underlying file disappeared between scans. The scanner used to only walk files that exist and never compare against the DB, leaving phantom rows in GET /api/v1/media that 404'd on stream. Verified via curl: rm /testdata/.../orphan.mp3, rescan, row now has deleted_at != NULL. Scenarios updated to lock in the fixed behaviour: S19 step 15 — viewer tag-add now asserts 403, not 200. S20 step 14 — asserts ETag is present and If-None-Match → 304. S24 step 13 — asserts clean rescan (no last_error from UNIQUE). S24 step 20 — asserts orphan rows are soft-deleted by rescan. Verified: full Go unit suite passes; 25/25 LLM e2e scenarios; 22/22 Playwright e2e-web. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17Add bulk progress sync endpoint for offline mobile clientsPaul Buetow
2026-05-17Add Bearer token authentication alongside session cookiesPaul Buetow
2026-05-17Add api_tokens table, model, and repositoryPaul Buetow
2026-05-17Restructure repo: move Go server into player-server/Paul Buetow