- Replace Clerk with self-hosted JWT auth (register/login/verify, bcrypt passwords, Gmail OTP with console fallback) - Add lib/db.ts pg pool + transaction helpers; seed script migrates legacy Clerk-era schema (drop clerk_id, enforce UUID ids and unique email) - Add owner-gated admin API: stats, users, drivers CRUD, rides - Add dashboard/ Vite React owner dashboard (login, overview, users, fleet, rides) with dev-server proxy to avoid Expo CORS middleware - Add scripts/set-owner.mjs for role management
38 lines
1.1 KiB
TypeScript
38 lines
1.1 KiB
TypeScript
import { sql } from "@/lib/db";
|
|
import { requireAuth } from "@/lib/jwt";
|
|
|
|
export const corsHeaders: Record<string, string> = {
|
|
"Access-Control-Allow-Origin": process.env.ADMIN_CORS_ORIGIN ?? "*",
|
|
"Access-Control-Allow-Methods": "GET, POST, PATCH, DELETE, OPTIONS",
|
|
"Access-Control-Allow-Headers": "Content-Type, Authorization",
|
|
};
|
|
|
|
export const withCors = (response: Response): Response => {
|
|
for (const [key, value] of Object.entries(corsHeaders)) {
|
|
response.headers.set(key, value);
|
|
}
|
|
return response;
|
|
};
|
|
|
|
export const preflight = (): Response => withCors(new Response(null, { status: 204 }));
|
|
|
|
// Returns the authenticated owner or a ready-to-return error Response.
|
|
export const requireOwner = async (
|
|
req: Request,
|
|
): Promise<{ userId: string; email: string } | { error: Response }> => {
|
|
const auth = requireAuth(req);
|
|
if ("error" in auth) return auth;
|
|
|
|
const rows = await sql<{ role: string | null }>`
|
|
SELECT role FROM users WHERE id = ${auth.userId}
|
|
`;
|
|
|
|
if (rows[0]?.role !== "owner") {
|
|
return {
|
|
error: Response.json({ error: "Forbidden." }, { status: 403 }),
|
|
};
|
|
}
|
|
|
|
return auth;
|
|
};
|