import { NextResponse } from 'next/server'; import supabase from '@/lib/db'; import bcrypt from 'bcryptjs'; import { SignJWT } from 'jose'; interface User { id_user: number; username?: string; nip?: string; password: string; role_user: string; } export async function POST(request: Request) { try { // Test database connection first try { const { data: testData, error: testError } = await supabase .from('user_app') .select('count') .limit(1); if (testError) { return NextResponse.json( { error: 'Tidak dapat terhubung ke database' }, { status: 500 } ); } } catch (dbError) { return NextResponse.json( { error: 'Tidak dapat terhubung ke database' }, { status: 500 } ); } const body = await request.json(); const { username, nip, password, role } = body; // Validate input based on role if (role === 'admin') { if (!username || !password) { return NextResponse.json( { error: 'Username dan password harus diisi' }, { status: 400 } ); } } else if (role === 'dosen' || role === 'kajur') { if (!nip || !password) { return NextResponse.json( { error: 'NIP dan password harus diisi' }, { status: 400 } ); } } else { return NextResponse.json( { error: 'Role tidak valid' }, { status: 400 } ); } // Get user by username (admin) or NIP (dosen/kajur) let users: User[]; try { let query = supabase.from('user_app').select('*'); if (role === 'admin') { query = query.eq('username', username); } else { query = query.eq('nip', nip); } const { data, error } = await query; if (error) { return NextResponse.json( { error: 'Terjadi kesalahan saat memeriksa data pengguna' }, { status: 500 } ); } users = data || []; } catch (queryError) { return NextResponse.json( { error: 'Terjadi kesalahan saat memeriksa data pengguna' }, { status: 500 } ); } if (users.length === 0) { return NextResponse.json( { error: role === 'admin' ? 'Username atau password salah' : 'NIP atau password salah' }, { status: 401 } ); } const user = users[0]; // Check if user role matches if (user.role_user !== role) { return NextResponse.json( { error: 'Role tidak sesuai' }, { status: 401 } ); } // Verify password let isPasswordValid; try { // For admin, check if password is plain text (not hashed) if (user.role_user === 'admin') { // Check if stored password is plain text (not starting with $2a$ or $2b$) if (!user.password.startsWith('$2a$') && !user.password.startsWith('$2b$')) { // Plain text password - direct comparison isPasswordValid = password === user.password; } else { // Hashed password - use bcrypt isPasswordValid = await bcrypt.compare(password, user.password); } } else { // For dosen/kajur, always use bcrypt (should be hashed) isPasswordValid = await bcrypt.compare(password, user.password); } } catch (bcryptError) { return NextResponse.json( { error: 'Terjadi kesalahan saat memverifikasi password' }, { status: 500 } ); } if (!isPasswordValid) { return NextResponse.json( { error: role === 'admin' ? 'Username atau password salah' : 'NIP atau password salah' }, { status: 401 } ); } // Create JWT token let token; try { const tokenPayload: any = { id: user.id_user, role: user.role_user }; // Add username for admin, NIP for dosen/kajur if (user.role_user === 'admin') { tokenPayload.username = user.username; } else { tokenPayload.nip = user.nip; } token = await new SignJWT(tokenPayload) .setProtectedHeader({ alg: 'HS256' }) .setExpirationTime('24h') .sign(new TextEncoder().encode(process.env.JWT_SECRET || 'your-secret-key')); } catch (jwtError) { return NextResponse.json( { error: 'Terjadi kesalahan saat membuat token' }, { status: 500 } ); } // Set cookie const userResponse: any = { id: user.id_user, role: user.role_user }; // Add username for admin, NIP for dosen/kajur if (user.role_user === 'admin') { userResponse.username = user.username; } else { userResponse.nip = user.nip; } const response = NextResponse.json({ user: userResponse }); response.cookies.set('token', token, { httpOnly: true, secure: false, sameSite: 'lax', maxAge: 60 * 60 * 24 // 24 hours }); return response; } catch (error) { if (error instanceof Error) { console.error('Error message:', error.message); } 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', } }); }