/** * GET /_emdash/api/auth/signup/verify * * Validate a signup verification token (called when user clicks email link). * Returns the email and role for the UI to display. */ import type { APIRoute } from "astro"; export const prerender = false; import { validateSignupToken, SignupError, roleFromLevel } from "@premium-cms/auth"; import { createKyselyAdapter } from "@premium-cms/auth/adapters/kysely"; import { apiError, apiSuccess, handleError } from "#api/error.js"; import { AuthzRepository } from "#db/repositories/authz.js"; export const GET: APIRoute = async ({ url, locals }) => { const { emdash } = locals; if (!emdash?.db) { return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500); } const token = url.searchParams.get("token"); if (!token) { return apiError("MISSING_PARAM", "Token is required", 400); } try { const adapter = createKyselyAdapter(emdash.db); const result = await validateSignupToken(adapter, token); return apiSuccess({ success: true, email: result.email, role: result.role, roleId: result.roleId, roleName: await roleDisplayName(emdash.db, result.roleId, result.role), }); } catch (error) { if (error instanceof SignupError) { const statusMap: Record = { invalid_token: 404, token_expired: 410, user_exists: 409, domain_not_allowed: 403, }; return apiError(error.code.toUpperCase(), error.message, statusMap[error.code] ?? 400); } return handleError(error, "Failed to validate signup token", "SIGNUP_VERIFY_ERROR"); } }; /** Human name for a role, preferring the roles table over the legacy level. */ async function roleDisplayName( db: import("kysely").Kysely, roleId: string | null, level: number, ): Promise { if (roleId) { const summary = await new AuthzRepository(db).roleSummary(roleId); if (summary) return summary.name; } return roleFromLevel(level as 10 | 20 | 30 | 40 | 50) ?? "Unknown"; }