79 lines
3.6 KiB
JavaScript
79 lines
3.6 KiB
JavaScript
const bcrypt = require('bcryptjs');
|
|
const jwt = require('jsonwebtoken');
|
|
|
|
let db;
|
|
let JWT_SECRET;
|
|
|
|
function init(database, jwtSecret) {
|
|
db = database;
|
|
JWT_SECRET = jwtSecret;
|
|
}
|
|
|
|
function authenticateToken(req, res, next) {
|
|
const authHeader = req.headers['authorization'];
|
|
const token = authHeader && authHeader.split(' ')[1];
|
|
if (!token) return res.status(401).json({ error: 'Unauthorized' });
|
|
jwt.verify(token, JWT_SECRET, (err, user) => {
|
|
if (err) return res.status(403).json({ error: 'Invalid or expired token' });
|
|
req.user = user;
|
|
next();
|
|
});
|
|
}
|
|
|
|
function requireAdmin(req, res, next) {
|
|
if (req.user.role !== 'admin') return res.status(403).json({ error: 'Admin access required' });
|
|
next();
|
|
}
|
|
|
|
function login(req, res) {
|
|
const { login, password } = req.body;
|
|
if (!login || !password) return res.status(400).json({ error: 'Login and password required' });
|
|
db.get(`SELECT id, login, password_hash, full_name, email, role FROM users WHERE login = ?`, [login], (err, user) => {
|
|
if (err) return res.status(500).json({ error: 'Database error' });
|
|
if (!user) return res.status(401).json({ error: 'Invalid credentials' });
|
|
const match = bcrypt.compareSync(password, user.password_hash);
|
|
if (!match) return res.status(401).json({ error: 'Invalid credentials' });
|
|
const token = jwt.sign({ id: user.id, login: user.login, role: user.role }, JWT_SECRET, { expiresIn: '24h' });
|
|
res.json({
|
|
token,
|
|
user: { id: user.id, login: user.login, full_name: user.full_name, email: user.email, role: user.role }
|
|
});
|
|
});
|
|
}
|
|
|
|
function updateProfile(req, res) {
|
|
const { full_name, email } = req.body;
|
|
db.run(`UPDATE users SET full_name = COALESCE(?, full_name), email = COALESCE(?, email) WHERE id = ?`,
|
|
[full_name || null, email || null, req.user.id], function(err) {
|
|
if (err) return res.status(500).json({ error: 'Database error' });
|
|
db.get(`SELECT id, login, full_name, email, role FROM users WHERE id = ?`, [req.user.id], (err, row) => {
|
|
if (err) return res.status(500).json({ error: 'Database error' });
|
|
res.json({ message: 'Profile updated', user: row });
|
|
});
|
|
});
|
|
}
|
|
|
|
function changePassword(req, res) {
|
|
const { current_password, new_password } = req.body;
|
|
if (!current_password || !new_password) return res.status(400).json({ error: 'Current and new password required' });
|
|
if (new_password.length < 4) return res.status(400).json({ error: 'Password must be at least 4 characters' });
|
|
db.get(`SELECT password_hash FROM users WHERE id = ?`, [req.user.id], (err, row) => {
|
|
if (err) return res.status(500).json({ error: 'Database error' });
|
|
if (!row) return res.status(404).json({ error: 'User not found' });
|
|
const match = bcrypt.compareSync(current_password, row.password_hash);
|
|
if (!match) return res.status(401).json({ error: 'Current password is incorrect' });
|
|
const hash = bcrypt.hashSync(new_password, 10);
|
|
db.run(`UPDATE users SET password_hash = ? WHERE id = ?`, [hash, req.user.id], (err) => {
|
|
if (err) return res.status(500).json({ error: 'Database error' });
|
|
res.json({ message: 'Password changed successfully' });
|
|
});
|
|
});
|
|
}
|
|
|
|
function setupRoutes(app) {
|
|
app.post('/api/auth/login', login);
|
|
app.put('/api/auth/me', authenticateToken, updateProfile);
|
|
app.post('/api/auth/change-password', authenticateToken, changePassword);
|
|
}
|
|
|
|
module.exports = { init, setupRoutes, authenticateToken, requireAdmin, login }; |