feat(auth): make upload review a separate grant instead of an admin privilege
Reviewing the upload queue is now a per-user flag (reviews_uploads), not part of the admin role: several people can hold it, a moderator can have it, and an admin may not. Only admins grant or revoke it; existing admins keep it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
066ba24834
commit
74da457362
27 files changed
+503
-319
No files matched your search
@@ -56,6 +56,7 @@ export function makeUser(username: string, role: Role, extra: Partial<FakeUser>
|
||||
is_blocked: false,
|
||||
must_change_password: false,
|
||||
must_change_credentials: false,
|
||||
reviews_uploads: false,
|
||||
created_at: '2026-01-01T00:00:00Z',
|
||||
last_login_at: null,
|
||||
password: `${username}-password`,
|
||||
@@ -80,6 +81,7 @@ export function fakeApi(initial: FakeUser[]) {
|
||||
username: u.username,
|
||||
display_name: u.display_name,
|
||||
role: u.role,
|
||||
reviews_uploads: u.reviews_uploads,
|
||||
locale: u.locale,
|
||||
ui_prefs: prefs.get(u.id) ?? {},
|
||||
must_change_password: u.must_change_password,
|
||||
@@ -179,6 +181,7 @@ export function fakeApi(initial: FakeUser[]) {
|
||||
display_name: (body?.display_name as string) ?? null,
|
||||
must_change_password: true,
|
||||
password: 'Temp-Pass-123',
|
||||
reviews_uploads: body?.reviews_uploads === true && user.role === 'admin',
|
||||
});
|
||||
users.set(u.id, u);
|
||||
return json({ user: admin(u), temporary_password: u.password }, 201);
|
||||
@@ -235,6 +238,20 @@ export function fakeApi(initial: FakeUser[]) {
|
||||
}
|
||||
if (req.method === 'POST' && /^\/api\/v1\/admin\/users\/[^/]+\/reset-recommendations$/.test(path))
|
||||
return new Response(null, { status: 204 });
|
||||
const userPath = /^\/api\/v1\/admin\/users\/([^/]+)$/.exec(path);
|
||||
if (userPath && req.method === 'PATCH') {
|
||||
if (!user || user.role === 'user') return problem(403, 'auth.forbidden');
|
||||
const target = users.get(userPath[1]!);
|
||||
if (!target) return problem(404, 'common.not_found');
|
||||
if (typeof body?.reviews_uploads === 'boolean') {
|
||||
if (user.role !== 'admin') return problem(403, 'auth.forbidden');
|
||||
target.reviews_uploads = body.reviews_uploads;
|
||||
}
|
||||
if (typeof body?.role === 'string' && user.role === 'admin') target.role = body.role as Role;
|
||||
if (typeof body?.is_blocked === 'boolean') target.is_blocked = body.is_blocked;
|
||||
users.set(target.id, target);
|
||||
return json(admin(target));
|
||||
}
|
||||
const reactionPath = /^\/api\/v1\/me\/reactions\/tracks\/([^/]+)$/.exec(path);
|
||||
if (reactionPath) {
|
||||
if (req.method === 'PUT') reactions.set(reactionPath[1]!, body?.reaction as 'like' | 'dislike');
|
||||
|
||||
Reference in new issue
Block a user