47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
import { auth } from "~~/lib/auth";
|
|
import { lockAdministration } from "~~/server/lib/account-security";
|
|
import { authTransaction } from "~~/server/lib/auth-transaction";
|
|
|
|
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;
|
|
}
|
|
});
|