47 lines
1.5 KiB
JavaScript
47 lines
1.5 KiB
JavaScript
const bcrypt = require('bcryptjs');
|
|
const { User } = require('../models');
|
|
|
|
function unauthorized(res) {
|
|
res.set('WWW-Authenticate', 'Basic realm="REST API", charset="UTF-8"');
|
|
return res.status(401).json({
|
|
success: false,
|
|
error: { code: 401, message: 'Invalid login or password.' },
|
|
});
|
|
}
|
|
|
|
async function authenticate(req, res, next) {
|
|
const header = req.get('authorization') || '';
|
|
const match = /^Basic\s+([A-Za-z0-9+/]+={0,2})$/i.exec(header);
|
|
if (!match) return unauthorized(res);
|
|
|
|
const decoded = Buffer.from(match[1], 'base64').toString('utf8');
|
|
const separator = decoded.indexOf(':');
|
|
if (separator < 1) return unauthorized(res);
|
|
|
|
const login = decoded.slice(0, separator);
|
|
const password = decoded.slice(separator + 1);
|
|
const user = await User.unscoped().findOne({
|
|
attributes: ['id', 'login', 'password', 'role', 'active', 'email', 'first_name', 'last_name', 'last_login', 'created', 'modified'],
|
|
where: { login },
|
|
});
|
|
if (!user || !user.active) return unauthorized(res);
|
|
|
|
const compatibleHash = user.password.replace(/^\$2y\$/, '$2b$');
|
|
if (!(await bcrypt.compare(password, compatibleHash))) return unauthorized(res);
|
|
|
|
req.user = user;
|
|
next();
|
|
}
|
|
|
|
function requireAdmin(req, res, next) {
|
|
if (req.user.role !== 'admin') {
|
|
return res.status(403).json({
|
|
success: false,
|
|
error: { code: 403, message: 'This action requires the admin role.' },
|
|
});
|
|
}
|
|
next();
|
|
}
|
|
|
|
module.exports = { authenticate, requireAdmin };
|