feat: login unificado BI-CCC com deteccao automatica de role
- Adiciona coluna 'role' na tabela agentes (agente|admin)
- Migra admins existentes para tabela agentes com role='admin'
- Unifica login em /login com redirect baseado em role
- Sessao unificada req.session.user com {id, email, nome, role, agente_id}
- Middleware requireRole() para proteger rotas por role
- Admin panel com selector de role ao criar/editar usuarios
- Atualiza branding para "BI - CCC" com logo CambioReal
- Redirects: /admin/login -> /login, /admin/logout -> /logout
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
66
src/auth.js
66
src/auth.js
@@ -1,18 +1,33 @@
|
||||
/**
|
||||
* Autenticação — login/logout com bcrypt + express-session
|
||||
* Autenticacao Unificada — login/logout com bcrypt + express-session
|
||||
* Suporta roles: 'agente' | 'admin'
|
||||
*/
|
||||
const bcrypt = require('bcrypt');
|
||||
const db = require('./db-local');
|
||||
|
||||
const SALT_ROUNDS = 10;
|
||||
|
||||
async function createAgente(email, senha, agenteId, nome) {
|
||||
/**
|
||||
* Cria um novo usuario (agente ou admin)
|
||||
*/
|
||||
async function createUser(email, senha, nome, role = 'agente', agenteId = 0) {
|
||||
const hash = await bcrypt.hash(senha, SALT_ROUNDS);
|
||||
return db.prepare(
|
||||
'INSERT INTO agentes (email, senha_hash, agente_id, nome) VALUES (?, ?, ?, ?)'
|
||||
).run(email, hash, agenteId, nome);
|
||||
'INSERT INTO agentes (email, senha_hash, agente_id, nome, role) VALUES (?, ?, ?, ?, ?)'
|
||||
).run(email, hash, agenteId, nome, role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cria agente (retrocompatibilidade)
|
||||
*/
|
||||
async function createAgente(email, senha, agenteId, nome) {
|
||||
return createUser(email, senha, nome, 'agente', agenteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Autentica usuario por email/senha
|
||||
* Retorna usuario com role ou null se invalido
|
||||
*/
|
||||
async function authenticate(email, senha) {
|
||||
const row = db.prepare(
|
||||
'SELECT * FROM agentes WHERE email = ? AND ativo = 1'
|
||||
@@ -22,9 +37,48 @@ async function authenticate(email, senha) {
|
||||
return match ? row : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware que verifica autenticacao e roles
|
||||
* Uso: requireRole() - qualquer usuario logado
|
||||
* requireRole('admin') - apenas admins
|
||||
* requireRole('agente', 'admin') - ambos
|
||||
*/
|
||||
function requireRole(...roles) {
|
||||
return (req, res, next) => {
|
||||
if (!req.session?.user) {
|
||||
return res.redirect('/login');
|
||||
}
|
||||
if (roles.length && !roles.includes(req.session.user.role)) {
|
||||
return res.status(403).send('Acesso negado');
|
||||
}
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware simples - apenas verifica se esta logado
|
||||
* Retrocompatibilidade com requireAuth
|
||||
*/
|
||||
function requireAuth(req, res, next) {
|
||||
if (req.session && req.session.agente) return next();
|
||||
if (req.session && req.session.user) return next();
|
||||
res.redirect('/login');
|
||||
}
|
||||
|
||||
module.exports = { createAgente, authenticate, requireAuth };
|
||||
/**
|
||||
* Atualiza senha de usuario
|
||||
*/
|
||||
async function updatePassword(id, novaSenha) {
|
||||
const hash = await bcrypt.hash(novaSenha, SALT_ROUNDS);
|
||||
return db.prepare(
|
||||
'UPDATE agentes SET senha_hash = ? WHERE id = ?'
|
||||
).run(hash, id);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createUser,
|
||||
createAgente,
|
||||
authenticate,
|
||||
requireAuth,
|
||||
requireRole,
|
||||
updatePassword
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user