125 lines
4.8 KiB
JavaScript
125 lines
4.8 KiB
JavaScript
const jwt = require('jsonwebtoken');
|
|
const bcrypt = require('bcryptjs');
|
|
|
|
let db;
|
|
|
|
function init(database) {
|
|
db = database;
|
|
}
|
|
|
|
function authenticateToken(req, res, next) {
|
|
const authHeader = req.headers['authorization'];
|
|
const token = authHeader && authHeader.split(' ')[1];
|
|
if (!token) {
|
|
return res.status(401).json({ error: 'Требуется авторизация' });
|
|
}
|
|
jwt.verify(token, process.env.HOTEL777KEY, (err, user) => {
|
|
if (err) {
|
|
return res.status(403).json({ error: 'Недействительный токен' });
|
|
}
|
|
req.user = user;
|
|
next();
|
|
});
|
|
}
|
|
|
|
function requireAdmin(req, res, next) {
|
|
if (req.user && req.user.role === 'admin') {
|
|
return next();
|
|
}
|
|
return res.status(403).json({ error: 'Требуются права администратора' });
|
|
}
|
|
|
|
function syncAdmin() {
|
|
return new Promise((resolve) => {
|
|
const login = process.env.ADMIN_USERNAME || 'admin';
|
|
const password = process.env.ADMIN_PASSWORD || 'admin123';
|
|
const hash = bcrypt.hashSync(password, 10);
|
|
|
|
db.get(`SELECT id FROM users WHERE login = ?`, [login], (err, row) => {
|
|
if (row) {
|
|
db.run(`UPDATE users SET password_hash = ?, role = 'admin' WHERE login = ?`, [hash, login], function() {
|
|
resolve();
|
|
});
|
|
} else {
|
|
db.run(`INSERT INTO users (login, password_hash, full_name, role) VALUES (?, ?, ?, 'admin')`,
|
|
[login, hash, 'Администратор'], function() {
|
|
resolve();
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function setupRoutes(app) {
|
|
app.post('/api/auth/login', (req, res) => {
|
|
const { login, password } = req.body;
|
|
if (!login || !password) {
|
|
return res.status(400).json({ error: 'Логин и пароль обязательны' });
|
|
}
|
|
|
|
db.get(`SELECT * FROM users WHERE login = ?`, [login], (err, user) => {
|
|
if (err || !user) {
|
|
return res.status(401).json({ error: 'Неверный логин или пароль' });
|
|
}
|
|
|
|
const valid = bcrypt.compareSync(password, user.password_hash);
|
|
if (!valid) {
|
|
return res.status(401).json({ error: 'Неверный логин или пароль' });
|
|
}
|
|
|
|
const token = jwt.sign(
|
|
{ id: user.id, login: user.login, role: user.role },
|
|
process.env.HOTEL777KEY,
|
|
{ expiresIn: '24h' }
|
|
);
|
|
|
|
res.json({
|
|
token,
|
|
user: {
|
|
id: user.id,
|
|
login: user.login,
|
|
full_name: user.full_name,
|
|
role: user.role
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
app.get('/api/auth/me', authenticateToken, (req, res) => {
|
|
db.get(`SELECT id, login, full_name, role, created_at FROM users WHERE id = ?`, [req.user.id], (err, user) => {
|
|
if (err || !user) {
|
|
return res.status(404).json({ error: 'Пользователь не найден' });
|
|
}
|
|
res.json(user);
|
|
});
|
|
});
|
|
|
|
app.put('/api/auth/me', authenticateToken, (req, res) => {
|
|
const { full_name } = req.body;
|
|
db.run(`UPDATE users SET full_name = ? WHERE id = ?`, [full_name || '', req.user.id], function(err) {
|
|
if (err) return res.status(500).json({ error: 'Ошибка обновления' });
|
|
res.json({ message: 'Профиль обновлён' });
|
|
});
|
|
});
|
|
|
|
app.post('/api/auth/change-password', authenticateToken, (req, res) => {
|
|
const { old_password, new_password } = req.body;
|
|
if (!old_password || !new_password) {
|
|
return res.status(400).json({ error: 'Старый и новый пароль обязательны' });
|
|
}
|
|
db.get(`SELECT password_hash FROM users WHERE id = ?`, [req.user.id], (err, user) => {
|
|
if (err || !user) return res.status(404).json({ error: 'Пользователь не найден' });
|
|
if (!bcrypt.compareSync(old_password, user.password_hash)) {
|
|
return res.status(400).json({ error: 'Неверный старый пароль' });
|
|
}
|
|
const hash = bcrypt.hashSync(new_password, 10);
|
|
db.run(`UPDATE users SET password_hash = ? WHERE id = ?`, [hash, req.user.id], (err2) => {
|
|
if (err2) return res.status(500).json({ error: 'Ошибка обновления пароля' });
|
|
res.json({ message: 'Пароль изменён' });
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
module.exports = { init, authenticateToken, requireAdmin, syncAdmin, setupRoutes };
|