mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 08:21:39 -06:00
fix(auth): split Book Dock access from Book Dock administration
Book Dock was a single permission that the standard preset handed to every user, so an ordinary account could pause processing, trigger a rescan, and finalize straight into the library. Keep book_dock_access for personal upload and review, and move global control behind a new manage_book_dock permission in the administration group. Finalization now also requires library_upload, since it writes into a library. Per-file reads and mutations are scoped to the uploader unless the caller can manage the dock, which closes the gap that let any Book Dock user read, edit, or discard another user's entry by id. The summary websocket now announces a change instead of broadcasting global counts, so each client refetches its own scoped totals. Closes #961
This commit is contained in:
@@ -774,14 +774,18 @@ describe('Book Dock ingest + finalize (e2e)', () => {
|
||||
|
||||
it('enforces Book Dock permission and library access for finalize', async () => {
|
||||
const noPermissionUser = await createUserAndLogin(context);
|
||||
const withPermissionUser = await createUserAndLogin(context, {
|
||||
const accessOnlyUser = await createUserAndLogin(context, {
|
||||
permissions: [Permission.BookDockAccess],
|
||||
});
|
||||
const withPermissionUser = await createUserAndLogin(context, {
|
||||
permissions: [Permission.BookDockAccess, Permission.LibraryUpload],
|
||||
});
|
||||
const destination = await createLibraryWithFolder(context);
|
||||
const bookDockRow = await createBookDockRow(context, {
|
||||
fileName: 'permission-check.fb2',
|
||||
selectedMetadata: { title: 'Permission Check' },
|
||||
status: 'ready',
|
||||
uploadedBy: withPermissionUser.userId,
|
||||
});
|
||||
|
||||
const forbiddenSummary = await context.app.inject({
|
||||
@@ -798,6 +802,19 @@ describe('Book Dock ingest + finalize (e2e)', () => {
|
||||
});
|
||||
expect(allowedSummary.statusCode).toBe(200);
|
||||
|
||||
const missingUploadPermission = await context.app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/v1/book-dock/finalize',
|
||||
headers: authHeader(accessOnlyUser.accessToken),
|
||||
payload: {
|
||||
fileIds: [bookDockRow.id],
|
||||
defaultLibraryId: destination.libraryId,
|
||||
defaultFolderId: destination.libraryFolderId,
|
||||
},
|
||||
});
|
||||
expect(missingUploadPermission.statusCode).toBe(403);
|
||||
expect(missingUploadPermission.json()).toMatchObject({ message: `Missing permission: ${Permission.LibraryUpload}` });
|
||||
|
||||
const noAccessFinalize = await context.app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/v1/book-dock/finalize',
|
||||
|
||||
Reference in New Issue
Block a user