Merge pull request (#7): comprobar el rol de la sesion en todas las rutas
Deploy / deploy (push) Successful in 3m5s

This commit was merged in pull request #7.
This commit is contained in:
2026-08-05 17:02:50 -03:00
18 changed files with 37 additions and 35 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
import { verificarSesion } from "@/lib/auth-admin"; import { verificarSesion } from "@/lib/auth-admin";
export async function GET(req: NextRequest) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { searchParams } = new URL(req.url); const { searchParams } = new URL(req.url);
+2 -2
View File
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
import { verificarSesion } from "@/lib/auth-admin"; import { verificarSesion } from "@/lib/auth-admin";
export async function GET(req: NextRequest) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { searchParams } = new URL(req.url); const { searchParams } = new URL(req.url);
@@ -20,7 +20,7 @@ export async function GET(req: NextRequest) {
} }
export async function POST(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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { autoId, tipoServicioId, descripcion, observaciones, fechaRealizado } = await req.json(); const { autoId, tipoServicioId, descripcion, observaciones, fechaRealizado } = await req.json();
+1 -1
View File
@@ -4,7 +4,7 @@ import { verificarSesion } from "@/lib/auth-admin";
import bcrypt from "bcryptjs"; import bcrypt from "bcryptjs";
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { id } = await params; const { id } = await params;
+2 -2
View File
@@ -4,7 +4,7 @@ import { verificarSesion } from "@/lib/auth-admin";
import bcrypt from "bcryptjs"; import bcrypt from "bcryptjs";
export async function GET() { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const jefes = await prisma.jefeMecanico.findMany({ const jefes = await prisma.jefeMecanico.findMany({
@@ -15,7 +15,7 @@ export async function GET() {
} }
export async function POST(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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { nombre, email, password, slotsParalelos } = await req.json(); const { nombre, email, password, slotsParalelos } = await req.json();
+1 -1
View File
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
import { verificarSesion } from "@/lib/auth-admin"; import { verificarSesion } from "@/lib/auth-admin";
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { id } = await params; const { id } = await params;
+2 -2
View File
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
import { verificarSesion } from "@/lib/auth-admin"; import { verificarSesion } from "@/lib/auth-admin";
export async function GET() { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const servicios = await prisma.tipoServicio.findMany({ orderBy: { nombre: "asc" } }); const servicios = await prisma.tipoServicio.findMany({ orderBy: { nombre: "asc" } });
@@ -11,7 +11,7 @@ export async function GET() {
} }
export async function POST(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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { nombre, duracionHoras } = await req.json(); const { nombre, duracionHoras } = await req.json();
+1 -1
View File
@@ -4,7 +4,7 @@ import { verificarSesion } from "@/lib/auth-admin";
import { agregarFilaSheet } from "@/lib/google-sheets"; import { agregarFilaSheet } from "@/lib/google-sheets";
export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { id } = await params; const { id } = await params;
+1 -1
View File
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
import { verificarSesion } from "@/lib/auth-admin"; import { verificarSesion } from "@/lib/auth-admin";
export async function GET(req: NextRequest) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { searchParams } = new URL(req.url); const { searchParams } = new URL(req.url);
+2 -2
View File
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
import { verificarSesion } from "@/lib/auth-admin"; import { verificarSesion } from "@/lib/auth-admin";
export async function GET() { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const autos = await prisma.auto.findMany({ const autos = await prisma.auto.findMany({
@@ -15,7 +15,7 @@ export async function GET() {
} }
export async function POST(req: NextRequest) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { patente, marca, modelo, anio, nroChasis } = await req.json(); const { patente, marca, modelo, anio, nroChasis } = await req.json();
+1 -1
View File
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
import { verificarSesion } from "@/lib/auth-admin"; import { verificarSesion } from "@/lib/auth-admin";
export async function GET(req: NextRequest) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { searchParams } = new URL(req.url); const { searchParams } = new URL(req.url);
+1 -1
View File
@@ -3,7 +3,7 @@ import { prisma } from "@/lib/prisma";
import { verificarSesion } from "@/lib/auth-admin"; import { verificarSesion } from "@/lib/auth-admin";
export async function GET() { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const jefes = await prisma.jefeMecanico.findMany({ const jefes = await prisma.jefeMecanico.findMany({
+1 -1
View File
@@ -6,7 +6,7 @@ import { whereTrabajosDeJefe } from "@/lib/servicios";
// Trabajos que ofrece un jefe mecánico: los suyos + los globales del taller. // 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. // El flujo del cliente es jefe → trabajo, así que el jefe es obligatorio.
export async function GET(req: NextRequest) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const jefeMecanicoId = req.nextUrl.searchParams.get("jefeMecanicoId"); const jefeMecanicoId = req.nextUrl.searchParams.get("jefeMecanicoId");
+1 -1
View File
@@ -5,7 +5,7 @@ import { obtenerSlotsDisponibles } from "@/lib/scheduling";
import { trabajoEsDeJefe } from "@/lib/servicios"; import { trabajoEsDeJefe } from "@/lib/servicios";
export async function GET(req: NextRequest) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { searchParams } = new URL(req.url); const { searchParams } = new URL(req.url);
+2 -2
View File
@@ -4,7 +4,7 @@ import { verificarSesion } from "@/lib/auth-admin";
import { crearTurno } from "@/lib/turnos"; import { crearTurno } from "@/lib/turnos";
export async function GET() { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const turnos = await prisma.turno.findMany({ const turnos = await prisma.turno.findMany({
@@ -17,7 +17,7 @@ export async function GET() {
} }
export async function POST(req: NextRequest) { 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 }); if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { autoId, tipoServicioId, jefeMecanicoId, fechaInicio, kilometros } = await req.json(); const { autoId, tipoServicioId, jefeMecanicoId, fechaInicio, kilometros } = await req.json();
+4 -4
View File
@@ -4,8 +4,8 @@ import { verificarSesion } from "@/lib/auth-admin";
// Edita un trabajo propio del jefe (nombre, duración, activo). Solo si le pertenece. // 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 }> }) { export async function PATCH(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
const sesion = await verificarSesion("jefe_session"); const sesion = await verificarSesion("jefe_session", "jefe");
if (!sesion || sesion.role !== "jefe") if (!sesion)
return NextResponse.json({ error: "No autorizado" }, { status: 401 }); return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { id } = await params; 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 // 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). // (para no romper la integridad referencial de los turnos históricos).
export async function DELETE(_req: NextRequest, { params }: { params: Promise<{ id: string }> }) { export async function DELETE(_req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
const sesion = await verificarSesion("jefe_session"); const sesion = await verificarSesion("jefe_session", "jefe");
if (!sesion || sesion.role !== "jefe") if (!sesion)
return NextResponse.json({ error: "No autorizado" }, { status: 401 }); return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { id } = await params; const { id } = await params;
+4 -4
View File
@@ -4,8 +4,8 @@ import { verificarSesion } from "@/lib/auth-admin";
// Lista los trabajos cargados por el jefe logueado (los suyos, no los globales). // Lista los trabajos cargados por el jefe logueado (los suyos, no los globales).
export async function GET() { export async function GET() {
const sesion = await verificarSesion("jefe_session"); const sesion = await verificarSesion("jefe_session", "jefe");
if (!sesion || sesion.role !== "jefe") if (!sesion)
return NextResponse.json({ error: "No autorizado" }, { status: 401 }); return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const servicios = await prisma.tipoServicio.findMany({ 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). // Crea un trabajo propio del jefe (nombre + duración en horas).
export async function POST(req: NextRequest) { export async function POST(req: NextRequest) {
const sesion = await verificarSesion("jefe_session"); const sesion = await verificarSesion("jefe_session", "jefe");
if (!sesion || sesion.role !== "jefe") if (!sesion)
return NextResponse.json({ error: "No autorizado" }, { status: 401 }); return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { nombre, duracionHoras } = await req.json(); const { nombre, duracionHoras } = await req.json();
+2 -2
View File
@@ -3,8 +3,8 @@ import { prisma } from "@/lib/prisma";
import { verificarSesion } from "@/lib/auth-admin"; import { verificarSesion } from "@/lib/auth-admin";
export async function GET(req: NextRequest) { export async function GET(req: NextRequest) {
const sesion = await verificarSesion("jefe_session"); const sesion = await verificarSesion("jefe_session", "jefe");
if (!sesion || sesion.role !== "jefe") if (!sesion)
return NextResponse.json({ error: "No autorizado" }, { status: 401 }); return NextResponse.json({ error: "No autorizado" }, { status: 401 });
const { searchParams } = new URL(req.url); const { searchParams } = new URL(req.url);
+8 -6
View File
@@ -3,12 +3,14 @@ import { jwtVerify } from "jose";
const SECRET = new TextEncoder().encode(process.env.NEXTAUTH_SECRET || "dev-secret"); 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; const token = req.cookies.get(cookieName)?.value;
if (!token) return false; if (!token) return false;
try { try {
await jwtVerify(token, SECRET); const { payload } = await jwtVerify(token, SECRET);
return true; return (payload as { role?: string }).role === rol;
} catch { } catch {
return false; return false;
} }
@@ -21,7 +23,7 @@ export async function middleware(req: NextRequest) {
pathname.startsWith("/cliente/historial") || pathname.startsWith("/cliente/historial") ||
pathname.startsWith("/cliente/perfil") || pathname.startsWith("/cliente/perfil") ||
pathname.startsWith("/cliente/turnos")) { 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)); 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/servicios") ||
pathname.startsWith("/admin/jefes") || pathname.startsWith("/admin/jefes") ||
pathname.startsWith("/admin/clientes")) { 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 (!ok) return NextResponse.redirect(new URL("/admin", req.url));
} }
if (pathname.startsWith("/jefe/dashboard")) { 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)); if (!ok) return NextResponse.redirect(new URL("/jefe", req.url));
} }