Repository navigation
feat(server): make smart list visibility an admin capability - #152
Conversation
A regular user's smart lists are always PRIVATE: non-admins cannot set visibility or share targets on create or PATCH, and GET share-targets now requires admin — matching komga's admin-only /api/v2/users, since exposing every user's email to all authenticated users is not acceptable. Admins can still publish PUBLIC lists and share SHARED lists; everyone authenticated can read those, but only the owner or an admin can modify or delete them (require_owner_or_admin gate on PATCH/DELETE, closing the sharee-write hole). The visibility test is rewritten around the admin-only model.
everpcpc
left a comment
There was a problem hiding this comment.
Reviewed; fmt/clippy/nextest (1095 tests) are green. The model is coherent and closes both holes from the previous round: visibility as an admin capability matches the kmweb wizard's gating, and admin-only share-targets resolves the email-directory exposure the same way komga's /api/v2/users does. The rewritten test pins the new contract well — the old version exercised these exact paths with 200s, so the 400/403 assertions are real regression coverage.
One gap and two nits:
1. openapi.json wasn't updated for the semantics change. The document still describes share-targets as a plain "minimal user directory" with no admin note, and the create/PATCH descriptions don't say visibility/sharing is admin-only. Since #150 established that kmrs extensions are documented there, this behavior change should land in the document too — otherwise the spec contradicts the server.
2. Create/PATCH asymmetry on explicit PRIVATE. Create accepts a non-admin body with visibility: "PRIVATE" (it equals the default), but PATCH rejects any non-admin body where visibility is merely present (is_some()). A client that always serializes the field works on create and 400s on PATCH. Either allow the explicit PRIVATE no-op on PATCH too, or reject it on create for symmetry.
3. 400 vs 403. "only admins may set visibility" is an authorization failure, and the codebase's require_admin answers those with 403 (ApiError::forbidden). 400 reads as "your request is malformed", which it isn't. Minor, but the tests now pin the less precise code.
Cross-repo follow-ups (not this PR's scope, flagging so they don't get lost):
- kmworks/kmweb#123:
SmartListDialogqueriesshareTargets()unconditionally — with this change, every non-admin opening the wizard gets a background 403 (retry noise in the console). The query should beenabled: admin. - The website's
server/enhancements/smart-listspage describes visibility as owner-writable andshare-targetsas open; I'll send a small docs PR once this merges.
…nt the admin rule - create now rejects the mere presence of visibility/sharedWithUserIds from non-admins, same as PATCH (an explicit PRIVATE no longer slips through), and both gates answer 403 instead of 400 - openapi.json: share-targets and the visibility/share fields carry the admin-only note
|
Taking over the PR to land the review fixes directly — pushed
fmt / clippy / nextest (1095 tests) all green locally. The two cross-repo items remain: kmworks/kmweb#123 should gate the |
|
Holistic design review of the whole smart-lists feature — #150 (merged) plus this PR — as it now stands. CI: lint/test/ubuntu/docker green, macos/windows builds still running. Design verdictThe final shape is coherent. The core decisions all hold up:
Strangers always get 404, so existence never leaks. For regular users the feature is "saved searches"; the curated PUBLIC/SHARED lists are necessarily admin-owned, which matches how komga gates user-visible administration everywhere else. Design consequences worth stating for the record (accepted, not blockers)
Open items across the feature (outside this PR)
|
Surface the kmrs smart-list API (kmworks/kmrs#150, kmworks/kmrs#152): user-owned search filters created and edited through a two-step wizard (details, then filters inline), evaluated live by the server. - smartListsApi + SmartList DTOs; SSE wiring for the smart-list events, including read-progress invalidation so items and the continue target stay fresh - new 'entities' filter group kind (libraries / read lists / collections) with multi-select and is/is-not membership; referential options in the wizard follow the selected scope - /smart-lists browse page and /smart-lists/:id detail pages for both targets, reusing the browse grid/filter bar; page-side filters post as an overlay body; owner-scoped edit/delete (new isOwner permission idiom), covers owner-only (admins no longer get a dead Manage posters entry on others' lists); adminOnly filter groups hidden from non-admins; read/peek entry points on book lists - two-step create/edit wizard reusing the filter building blocks inline (no drawer overlay), with a debounced live match-count preview, admin-only visibility and share-target picking, and a lossy warning when a stored document contains conditions the editor cannot represent - stored-filter round-tripping verified lossless across the builder vocabulary: group mode tracked through the same condition→group mapping as values, single-group documents recognized (whole-condition same-key anyOf/allOf and year-pair runs), year-pair bounds arithmetic fixed, and unrepresentable constructs (mixed is/isNot per group, repeated bare keys) flagged instead of silently rewritten - PosterManager gains the 'smartlist' kind (upload/select/delete covers, generated mosaic listed alongside uploads) - smart-list cards use the generated/selected cover with cache busting - i18n: smartlists namespace in all 10 locales plus nav/filter/poster keys - bump version to 0.11.8
Aligns the smart-lists enhancement page with kmworks/kmrs#152: visibility and sharing are admin capabilities (a regular user's lists are always private), share-targets is admin-only like komga's /api/v2/users, and writes split into owner-or-admin (rename/filter/scope/delete) vs owner-only (covers).
A regular user's smart lists are always PRIVATE: non-admins cannot set visibility or share targets on create or PATCH, and GET share-targets now requires admin — matching komga's admin-only /api/v2/users, since exposing every user's email to all authenticated users is not acceptable. Admins can still publish PUBLIC lists and share SHARED lists; everyone authenticated can read those, but only the owner or an admin can modify or delete them (require_owner_or_admin gate on PATCH/DELETE, closing the sharee-write hole). The visibility test is rewritten around the admin-only model.