Add a read-only role per app for calendar, feedback and tickets

A grant can now be `read` instead of `access`: requireAppAccess lets it
through for GET/HEAD/OPTIONS and answers 403 to every other method, so
new write routes are covered without being marked. `read` and `access`
on the same app are rejected together; user management has no read role.
/tickets/admin/me and /feedback/admin/me report `readOnly`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
PaddyandClaude Opus 5.5 committed 2026-10-29 23:24:28 +01:00
1 parent bc865813cb
commit bfb8f2ff9c
9 files changed
+377 -10

No files matched your search

+10 -1
View File
@@ -3,6 +3,7 @@
*/
import express, {Request, Response} from 'express';
import {requireAdminAuth} from '../feedback.auth.js';
import {isReadOnly} from '../../admin/admin.schema.js';
import {sendServerError} from '../feedback.errors.js';
import {eventsAdminRouter} from './events.admin.router.js';
import {songsAdminRouter} from './songs.admin.router.js';
@@ -40,13 +41,21 @@ adminRouter.use(requireAdminAuth);
* type: string
* fullName:
* type: string
* readOnly:
* type: boolean
* description: Holds only the read role for feedback - every write answers 403.
* 401:
* description: Unauthorized
* 403:
* description: Signed in without the permission for this app, or account disabled
*/
adminRouter.get('/me', (req: Request, res: Response) => {
res.status(200).send({email: res.locals.admin.email, fullName: res.locals.admin.displayName});
res.status(200).send({
email: res.locals.admin.email,
fullName: res.locals.admin.displayName,
// Lets the frontend hide what the API would refuse anyway.
readOnly: isReadOnly(res.locals.admin.permissions, 'feedback')
});
});
/**