feat: admin controls

This commit is contained in:
Zoe
2026-10-15 10:07:41 -05:00
parent b6f4d85ed7
commit ff7797d3f8
41 changed files with 612 additions and 427 deletions
+44 -3
View File
@@ -1,5 +1,46 @@
import { auth } from '~~/lib/auth';
import { auth } from "~~/lib/auth";
import { lockAdministration } from "~~/server/lib/account-security";
import { authTransaction } from "~~/server/lib/auth-transaction";
export default defineEventHandler((event) => {
return auth.handler(toWebRequest(event));
const SIGN_UP = "/api/auth/sign-up/email";
// Requests that have to be undone as a whole when they fail. The hooks in
// lib/auth.ts refuse to run these without a transaction, so a URL that slips
// past this list is rejected there instead of going through unguarded.
const ADMIN_MUTATIONS = new Set([
"/api/auth/admin/set-role",
"/api/auth/admin/ban-user",
"/api/auth/admin/unban-user",
"/api/auth/admin/update-user",
]);
export default defineEventHandler(async (event) => {
const request = toWebRequest(event);
const path = new URL(request.url).pathname.replace(/\/+$/, "");
const adminMutation = ADMIN_MUTATIONS.has(path);
if (request.method !== "POST" || (!adminMutation && path !== SIGN_UP)) {
return auth.handler(request);
}
try {
return await authTransaction(async (tx) => {
if (adminMutation) {
// Deletion, banning and demotion all wait for each other here.
await lockAdministration(tx);
}
const response = await auth.handler(request);
if (!response.ok) {
// The auth handler returns errors as responses; roll back any writes.
throw response;
}
return response;
});
} catch (error) {
if (error instanceof Response) {
return error;
}
throw error;
}
});