141 lines
4.9 KiB
JavaScript
Executable File
141 lines
4.9 KiB
JavaScript
Executable File
// Authentication API Routes - with Dynamic Staff Users
|
|
import express from 'express';
|
|
import pool from '../db.js';
|
|
import crypto from 'crypto';
|
|
|
|
const router = express.Router();
|
|
|
|
// Password hashing (same as staff.js)
|
|
const hashPassword = (password) => {
|
|
return crypto.createHash('sha256').update(password).digest('hex');
|
|
};
|
|
|
|
// Fallback hardcoded credentials (for initial setup before any staff exists)
|
|
const FALLBACK_ADMIN = {
|
|
username: 'Adminabsensiswa',
|
|
password: 'Smanab100%'
|
|
};
|
|
|
|
const STUDENT_PASSWORD = 'Smanab#1';
|
|
|
|
// POST /api/auth/login - User login
|
|
router.post('/login', async (req, res) => {
|
|
try {
|
|
const { username, password } = req.body;
|
|
|
|
// 1. Check Staff Users from Database First
|
|
const hashedPassword = hashPassword(password);
|
|
const [staffRows] = await pool.query(
|
|
'SELECT id, username, name, role FROM staff_users WHERE username = ? AND password = ? AND is_active = TRUE',
|
|
[username, hashedPassword]
|
|
);
|
|
|
|
if (staffRows.length > 0) {
|
|
const staff = staffRows[0];
|
|
return res.json({
|
|
success: true,
|
|
user: {
|
|
id: staff.id,
|
|
name: staff.name,
|
|
role: staff.role,
|
|
createdAt: Date.now()
|
|
}
|
|
});
|
|
}
|
|
|
|
// 2. Fallback: Check hardcoded Admin (for first-time setup)
|
|
if (username === FALLBACK_ADMIN.username && password === FALLBACK_ADMIN.password) {
|
|
// Check if any admin exists in database
|
|
const [adminCount] = await pool.query(
|
|
"SELECT COUNT(*) as count FROM staff_users WHERE role = 'ADMIN'"
|
|
);
|
|
|
|
// If no admin in DB yet, allow fallback login
|
|
if (adminCount[0].count === 0) {
|
|
return res.json({
|
|
success: true,
|
|
user: {
|
|
id: 'admin-fallback',
|
|
name: 'Administrator (Setup)',
|
|
role: 'ADMIN',
|
|
createdAt: Date.now(),
|
|
isSetup: true // Flag to indicate first-time setup
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// 3. Check Student (username = NIS, password = STUDENT_PASSWORD)
|
|
if (password === STUDENT_PASSWORD) {
|
|
const [rows] = await pool.query(
|
|
'SELECT id, name, nis, class_name, shift, role, registered_face, face_descriptor, created_at FROM users WHERE nis = ?',
|
|
[username]
|
|
);
|
|
|
|
if (rows.length > 0) {
|
|
const student = rows[0];
|
|
return res.json({
|
|
success: true,
|
|
user: {
|
|
id: student.id,
|
|
name: student.name,
|
|
nis: student.nis,
|
|
className: student.class_name,
|
|
shift: student.shift,
|
|
role: student.role || 'STUDENT',
|
|
registeredFace: student.registered_face,
|
|
faceDescriptor: student.face_descriptor,
|
|
createdAt: student.created_at
|
|
}
|
|
});
|
|
} else {
|
|
return res.json({
|
|
success: false,
|
|
message: 'NIS tidak ditemukan. Hubungi Admin.'
|
|
});
|
|
}
|
|
}
|
|
|
|
// Invalid credentials
|
|
res.json({
|
|
success: false,
|
|
message: 'Username atau Password salah.'
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('POST /api/auth/login Error:', error);
|
|
res.status(500).json({ success: false, message: error.message });
|
|
}
|
|
});
|
|
|
|
// POST /api/auth/change-password - Change password for staff
|
|
router.post('/change-password', async (req, res) => {
|
|
try {
|
|
const { userId, oldPassword, newPassword } = req.body;
|
|
|
|
if (!userId || !oldPassword || !newPassword) {
|
|
return res.status(400).json({ error: 'Data tidak lengkap.' });
|
|
}
|
|
|
|
const hashedOld = hashPassword(oldPassword);
|
|
const [user] = await pool.query(
|
|
'SELECT id FROM staff_users WHERE id = ? AND password = ?',
|
|
[userId, hashedOld]
|
|
);
|
|
|
|
if (user.length === 0) {
|
|
return res.json({ success: false, message: 'Password lama salah.' });
|
|
}
|
|
|
|
const hashedNew = hashPassword(newPassword);
|
|
await pool.query('UPDATE staff_users SET password = ? WHERE id = ?', [hashedNew, userId]);
|
|
|
|
res.json({ success: true, message: 'Password berhasil diubah.' });
|
|
} catch (error) {
|
|
console.error('POST /api/auth/change-password Error:', error);
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
export default router;
|