feat: admin controls
This commit is contained in:
@@ -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;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user