const fs = require('fs'); const path = require('path'); const bcrypt = require('bcryptjs'); const USERS_PATH = process.env.USERS_PATH || path.join(__dirname, '..', 'users.json'); function load() { try { return JSON.parse(fs.readFileSync(USERS_PATH, 'utf8')); } catch { return []; } } function save(users) { fs.writeFileSync(USERS_PATH, JSON.stringify(users, null, 2), 'utf8'); } /** * On first run, create a default admin user if no users exist. * Prints a warning to remind the user to change the password. */ function ensureDefaultAdmin() { const users = load(); if (users.length === 0) { const hash = bcrypt.hashSync('admin', 10); save([{ id: '1', username: 'admin', passwordHash: hash, createdAt: new Date().toISOString() }]); console.warn('⚠️ No users found — created default admin account.'); console.warn('⚠️ Username: admin Password: admin'); console.warn('⚠️ Change this password immediately in Settings → Users.'); } } function getAll() { return load().map(({ passwordHash, ...u }) => u); // strip hash from output } function findByUsername(username) { return load().find(u => u.username.toLowerCase() === username.toLowerCase()) ?? null; } function findById(id) { return load().find(u => u.id === id) ?? null; } function create(username, password) { const users = load(); if (users.find(u => u.username.toLowerCase() === username.toLowerCase())) { throw new Error('Username already exists'); } const hash = bcrypt.hashSync(password, 10); const user = { id: Date.now().toString(), username, passwordHash: hash, createdAt: new Date().toISOString(), }; users.push(user); save(users); const { passwordHash, ...safe } = user; return safe; } function updatePassword(id, newPassword) { const users = load(); const idx = users.findIndex(u => u.id === id); if (idx === -1) throw new Error('User not found'); users[idx].passwordHash = bcrypt.hashSync(newPassword, 10); save(users); } function remove(id) { const users = load(); if (users.length === 1) throw new Error('Cannot delete the last user'); const filtered = users.filter(u => u.id !== id); if (filtered.length === users.length) throw new Error('User not found'); save(filtered); } function verifyPassword(user, password) { return bcrypt.compareSync(password, user.passwordHash); } module.exports = { ensureDefaultAdmin, getAll, findByUsername, findById, create, updatePassword, remove, verifyPassword };