import { NextResponse } from 'next/server'; import pool from '@/lib/db'; import bcrypt from 'bcryptjs'; import { SignJWT } from 'jose'; import { RowDataPacket } from 'mysql2'; interface User extends RowDataPacket { id_user: number; nim: string; username: string; password: string; role: string; } export async function POST(request: Request) { let connection; try { console.log('Login request received'); // Test database connection first try { connection = await pool.getConnection(); console.log('Database connection successful'); } catch (dbError) { console.error('Database connection error:', dbError); return NextResponse.json( { error: 'Tidak dapat terhubung ke database' }, { status: 500 } ); } const body = await request.json(); console.log('Request body:', body); const { nim, password } = body; console.log('Extracted credentials:', { nim, password: '***' }); // Validate input if (!nim || !password) { console.log('Missing credentials:', { nim: !!nim, password: !!password }); return NextResponse.json( { error: 'NIM dan password harus diisi' }, { status: 400 } ); } // Get user by NIM console.log('Querying user with NIM:', nim); let users: User[]; try { const [rows] = await connection.execute( 'SELECT * FROM user WHERE nim = ?', [nim] ); users = rows; console.log('Query result:', users.length > 0 ? 'User found' : 'User not found'); } catch (queryError) { console.error('Database query error:', queryError); return NextResponse.json( { error: 'Terjadi kesalahan saat memeriksa data pengguna' }, { status: 500 } ); } if (users.length === 0) { console.log('No user found with NIM:', nim); connection.release(); return NextResponse.json( { error: 'NIM atau password salah' }, { status: 401 } ); } const user = users[0]; console.log('User found:', { id: user.id_user, nim: user.nim, username: user.username, role: user.role }); // Verify password console.log('Verifying password...'); let isPasswordValid; try { isPasswordValid = await bcrypt.compare(password, user.password); console.log('Password verification result:', isPasswordValid ? 'Valid' : 'Invalid'); } catch (bcryptError) { console.error('Password verification error:', bcryptError); return NextResponse.json( { error: 'Terjadi kesalahan saat memverifikasi password' }, { status: 500 } ); } if (!isPasswordValid) { console.log('Invalid password for user:', nim); connection.release(); return NextResponse.json( { error: 'NIM atau password salah' }, { status: 401 } ); } // Create JWT token console.log('Creating JWT token...'); let token; try { token = await new SignJWT({ id: user.id_user, nim: user.nim, role: user.role }) .setProtectedHeader({ alg: 'HS256' }) .setExpirationTime('24h') .sign(new TextEncoder().encode(process.env.JWT_SECRET || 'your-secret-key')); console.log('JWT token created'); } catch (jwtError) { console.error('JWT creation error:', jwtError); return NextResponse.json( { error: 'Terjadi kesalahan saat membuat token' }, { status: 500 } ); } // Set cookie console.log('Setting response...'); const response = NextResponse.json({ user: { id: user.id_user, nim: user.nim, username: user.username, role: user.role } }); response.cookies.set('token', token, { httpOnly: true, secure: false, sameSite: 'lax', maxAge: 60 * 60 * 24 // 24 hours }); console.log('Cookie set'); connection.release(); console.log('Login process completed successfully'); return response; } catch (error) { if (connection) { connection.release(); } console.error('Login error details:', error); if (error instanceof Error) { console.error('Error message:', error.message); console.error('Error stack:', error.stack); } return NextResponse.json( { error: 'Terjadi kesalahan saat login' }, { status: 500 } ); } } // Handle OPTIONS request for CORS export async function OPTIONS() { return NextResponse.json({}, { headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', } }); }