Add self-hosted auth, admin API, and owner web dashboard
- 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
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
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;
|
||||
};
|
||||
Reference in New Issue
Block a user