4cf35f9280
Páginas cliente: login magic link, registro, validación de token, dashboard de autos, historial por auto y reserva de turnos con selector de servicio + slots disponibles. Páginas admin: login, dashboard de turnos del día con cambio de estado, historial de autos (buscar cliente → auto → ver/cargar registros), gestión de tipos de servicio y vista de clientes. Middleware JWT para proteger rutas /cliente/* y /admin/*. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
42 lines
1.3 KiB
TypeScript
42 lines
1.3 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { jwtVerify } from "jose";
|
|
|
|
const SECRET = new TextEncoder().encode(process.env.NEXTAUTH_SECRET || "dev-secret");
|
|
|
|
async function verifyCookie(req: NextRequest, cookieName: string) {
|
|
const token = req.cookies.get(cookieName)?.value;
|
|
if (!token) return false;
|
|
try {
|
|
await jwtVerify(token, SECRET);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export async function middleware(req: NextRequest) {
|
|
const { pathname } = req.nextUrl;
|
|
|
|
if (pathname.startsWith("/cliente/dashboard") ||
|
|
pathname.startsWith("/cliente/historial") ||
|
|
pathname.startsWith("/cliente/turnos")) {
|
|
const ok = await verifyCookie(req, "cliente_session");
|
|
if (!ok) return NextResponse.redirect(new URL("/cliente", req.url));
|
|
}
|
|
|
|
if (pathname.startsWith("/admin/dashboard") ||
|
|
pathname.startsWith("/admin/turnos") ||
|
|
pathname.startsWith("/admin/historial") ||
|
|
pathname.startsWith("/admin/servicios") ||
|
|
pathname.startsWith("/admin/clientes")) {
|
|
const ok = await verifyCookie(req, "admin_session");
|
|
if (!ok) return NextResponse.redirect(new URL("/admin", req.url));
|
|
}
|
|
|
|
return NextResponse.next();
|
|
}
|
|
|
|
export const config = {
|
|
matcher: ["/cliente/:path*", "/admin/:path*"],
|
|
};
|