Files
sloth-manager/backend/src/users.js
T
2026-06-02 01:00:27 +02:00

85 lines
2.5 KiB
JavaScript

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 };