Files
smanab/absensi-siswa/backend/routes/auth.js

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;