Files
Krikorios a0b297285a 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
2026-08-23 16:38:41 +03:00

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;
};