semillero-special-hotel/src/app/api/auth/login/route.ts

100 lines
2.4 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { getPrisma } from '@/lib/db';
import { comparePassword, signJwt } from '@/lib/auth';
export async function POST(req: NextRequest) {
try {
const { username, password } = await req.json();
if (!username || !password) {
return NextResponse.json(
{ error: 'Username and password are required' },
{ status: 400 }
);
}
// Run lookup as ADMIN to bypass RLS since the user is not authenticated yet
const prismaAdmin = getPrisma({
userId: 0,
username: 'login_system',
email: 'system@estelar.com',
role: 'ADMIN',
hotelId: 0,
regionId: 0
});
const user = await prismaAdmin.user.findUnique({
where: { username },
include: { hotel: true }
});
if (!user || user.status !== 'ACTIVE') {
return NextResponse.json(
{ error: 'Invalid credentials or inactive user' },
{ status: 401 }
);
}
const passwordMatch = await comparePassword(password, user.passwordHash);
if (!passwordMatch) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
);
}
// Create session payload
const sessionPayload = {
userId: user.id,
username: user.username,
email: user.email,
role: user.role,
hotelId: user.hotelId,
regionId: user.hotel.regionId
};
// Sign JWT
const token = signJwt(sessionPayload);
// Set cookie
const response = NextResponse.json({
user: {
id: user.id,
username: user.username,
email: user.email,
role: user.role,
hotelId: user.hotelId,
area: user.area
}
});
response.cookies.set({
name: 'session',
value: token,
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
path: '/',
maxAge: 86400 // 1 day
});
// Record login audit log
await prismaAdmin.auditLog.create({
data: {
userId: user.id,
action: 'LOGIN',
targetTable: 'users',
targetId: user.id,
ipAddress: req.headers.get('x-forwarded-for') || '127.0.0.1'
}
});
return response;
} catch (err) {
console.error('Login error:', err);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}