fix(auth): comprobar el rol de la sesion en todas las rutas
Revisión con IA / ai-review (pull_request) Successful in 1m24s
Revisión con IA / ai-review (pull_request) Successful in 1m24s
Las tres sesiones (admin, cliente, jefe) se firman con el mismo secreto, asi que verificar solo la firma alcanzaba para que un token de un rol pasara por la cookie de otro. Verificado antes del cambio: un token de admin en cliente_session daba 200 en /api/cliente/autos, y uno de jefe cargaba /cliente/dashboard. Despues: 401 y 307. - Las 26 llamadas a verificarSesion pasan el rol esperado. - El middleware, que hacia su propio jwtVerify sin mirar el rol, ahora tambien lo comprueba. - Se sacan las comprobaciones sueltas de rol en las rutas de jefe, que quedaron redundantes. Matriz probada contra la app: los tres roles siguen entrando en su area (200) y ninguno entra en la de los otros, ni por API (401) ni por pagina (307). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url);
|
||||
@@ -20,7 +20,7 @@ export async function GET(req: NextRequest) {
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { autoId, tipoServicioId, descripcion, observaciones, fechaRealizado } = await req.json();
|
||||
|
||||
@@ -4,7 +4,7 @@ import { verificarSesion } from "@/lib/auth-admin";
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { verificarSesion } from "@/lib/auth-admin";
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
export async function GET() {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const jefes = await prisma.jefeMecanico.findMany({
|
||||
@@ -15,7 +15,7 @@ export async function GET() {
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { nombre, email, password, slotsParalelos } = await req.json();
|
||||
|
||||
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
export async function GET() {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const servicios = await prisma.tipoServicio.findMany({ orderBy: { nombre: "asc" } });
|
||||
@@ -11,7 +11,7 @@ export async function GET() {
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { nombre, duracionHoras } = await req.json();
|
||||
|
||||
@@ -4,7 +4,7 @@ import { verificarSesion } from "@/lib/auth-admin";
|
||||
import { agregarFilaSheet } from "@/lib/google-sheets";
|
||||
|
||||
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const sesion = await verificarSesion("admin_session");
|
||||
const sesion = await verificarSesion("admin_session", "admin");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
export async function GET() {
|
||||
const sesion = await verificarSesion("cliente_session");
|
||||
const sesion = await verificarSesion("cliente_session", "cliente");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const autos = await prisma.auto.findMany({
|
||||
@@ -15,7 +15,7 @@ export async function GET() {
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const sesion = await verificarSesion("cliente_session");
|
||||
const sesion = await verificarSesion("cliente_session", "cliente");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { patente, marca, modelo, anio, nroChasis } = await req.json();
|
||||
|
||||
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const sesion = await verificarSesion("cliente_session");
|
||||
const sesion = await verificarSesion("cliente_session", "cliente");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
export async function GET() {
|
||||
const sesion = await verificarSesion("cliente_session");
|
||||
const sesion = await verificarSesion("cliente_session", "cliente");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const jefes = await prisma.jefeMecanico.findMany({
|
||||
|
||||
@@ -6,7 +6,7 @@ import { whereTrabajosDeJefe } from "@/lib/servicios";
|
||||
// Trabajos que ofrece un jefe mecánico: los suyos + los globales del taller.
|
||||
// El flujo del cliente es jefe → trabajo, así que el jefe es obligatorio.
|
||||
export async function GET(req: NextRequest) {
|
||||
const sesion = await verificarSesion("cliente_session");
|
||||
const sesion = await verificarSesion("cliente_session", "cliente");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const jefeMecanicoId = req.nextUrl.searchParams.get("jefeMecanicoId");
|
||||
|
||||
@@ -5,7 +5,7 @@ import { obtenerSlotsDisponibles } from "@/lib/scheduling";
|
||||
import { trabajoEsDeJefe } from "@/lib/servicios";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const sesion = await verificarSesion("cliente_session");
|
||||
const sesion = await verificarSesion("cliente_session", "cliente");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { verificarSesion } from "@/lib/auth-admin";
|
||||
import { crearTurno } from "@/lib/turnos";
|
||||
|
||||
export async function GET() {
|
||||
const sesion = await verificarSesion("cliente_session");
|
||||
const sesion = await verificarSesion("cliente_session", "cliente");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const turnos = await prisma.turno.findMany({
|
||||
@@ -17,7 +17,7 @@ export async function GET() {
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const sesion = await verificarSesion("cliente_session");
|
||||
const sesion = await verificarSesion("cliente_session", "cliente");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { autoId, tipoServicioId, jefeMecanicoId, fechaInicio, kilometros } = await req.json();
|
||||
|
||||
@@ -4,8 +4,8 @@ import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
// Edita un trabajo propio del jefe (nombre, duración, activo). Solo si le pertenece.
|
||||
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const sesion = await verificarSesion("jefe_session");
|
||||
if (!sesion || sesion.role !== "jefe")
|
||||
const sesion = await verificarSesion("jefe_session", "jefe");
|
||||
if (!sesion)
|
||||
return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { id } = await params;
|
||||
@@ -42,8 +42,8 @@ export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id
|
||||
// Elimina un trabajo propio. Si ya tiene turnos asociados, lo desactiva en vez de borrarlo
|
||||
// (para no romper la integridad referencial de los turnos históricos).
|
||||
export async function DELETE(_req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
||||
const sesion = await verificarSesion("jefe_session");
|
||||
if (!sesion || sesion.role !== "jefe")
|
||||
const sesion = await verificarSesion("jefe_session", "jefe");
|
||||
if (!sesion)
|
||||
return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
@@ -4,8 +4,8 @@ import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
// Lista los trabajos cargados por el jefe logueado (los suyos, no los globales).
|
||||
export async function GET() {
|
||||
const sesion = await verificarSesion("jefe_session");
|
||||
if (!sesion || sesion.role !== "jefe")
|
||||
const sesion = await verificarSesion("jefe_session", "jefe");
|
||||
if (!sesion)
|
||||
return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const servicios = await prisma.tipoServicio.findMany({
|
||||
@@ -18,8 +18,8 @@ export async function GET() {
|
||||
|
||||
// Crea un trabajo propio del jefe (nombre + duración en horas).
|
||||
export async function POST(req: NextRequest) {
|
||||
const sesion = await verificarSesion("jefe_session");
|
||||
if (!sesion || sesion.role !== "jefe")
|
||||
const sesion = await verificarSesion("jefe_session", "jefe");
|
||||
if (!sesion)
|
||||
return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { nombre, duracionHoras } = await req.json();
|
||||
|
||||
@@ -3,8 +3,8 @@ import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
|
||||
export async function GET(req: NextRequest) {
|
||||
const sesion = await verificarSesion("jefe_session");
|
||||
if (!sesion || sesion.role !== "jefe")
|
||||
const sesion = await verificarSesion("jefe_session", "jefe");
|
||||
if (!sesion)
|
||||
return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { searchParams } = new URL(req.url);
|
||||
|
||||
+8
-6
@@ -3,12 +3,14 @@ import { jwtVerify } from "jose";
|
||||
|
||||
const SECRET = new TextEncoder().encode(process.env.NEXTAUTH_SECRET || "dev-secret");
|
||||
|
||||
async function verifyCookie(req: NextRequest, cookieName: string) {
|
||||
// Las tres sesiones se firman con el mismo secreto, así que además de la firma hay
|
||||
// que mirar el rol: si no, un token de jefe en la cookie del cliente pasa.
|
||||
async function verifyCookie(req: NextRequest, cookieName: string, rol: "admin" | "cliente" | "jefe") {
|
||||
const token = req.cookies.get(cookieName)?.value;
|
||||
if (!token) return false;
|
||||
try {
|
||||
await jwtVerify(token, SECRET);
|
||||
return true;
|
||||
const { payload } = await jwtVerify(token, SECRET);
|
||||
return (payload as { role?: string }).role === rol;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
@@ -21,7 +23,7 @@ export async function middleware(req: NextRequest) {
|
||||
pathname.startsWith("/cliente/historial") ||
|
||||
pathname.startsWith("/cliente/perfil") ||
|
||||
pathname.startsWith("/cliente/turnos")) {
|
||||
const ok = await verifyCookie(req, "cliente_session");
|
||||
const ok = await verifyCookie(req, "cliente_session", "cliente");
|
||||
if (!ok) return NextResponse.redirect(new URL("/cliente", req.url));
|
||||
}
|
||||
|
||||
@@ -31,12 +33,12 @@ export async function middleware(req: NextRequest) {
|
||||
pathname.startsWith("/admin/servicios") ||
|
||||
pathname.startsWith("/admin/jefes") ||
|
||||
pathname.startsWith("/admin/clientes")) {
|
||||
const ok = await verifyCookie(req, "admin_session");
|
||||
const ok = await verifyCookie(req, "admin_session", "admin");
|
||||
if (!ok) return NextResponse.redirect(new URL("/admin", req.url));
|
||||
}
|
||||
|
||||
if (pathname.startsWith("/jefe/dashboard")) {
|
||||
const ok = await verifyCookie(req, "jefe_session");
|
||||
const ok = await verifyCookie(req, "jefe_session", "jefe");
|
||||
if (!ok) return NextResponse.redirect(new URL("/jefe", req.url));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user