erp-construccion-backend/dist/modules/auth/middleware/auth.middleware.js

146 lines
4.5 KiB
JavaScript

"use strict";
/**
* Auth Middleware - Middleware de Autenticación
*
* Middleware para Express que valida JWT y extrae información del usuario.
* Configura el tenant_id para RLS en PostgreSQL.
*
* @module Auth
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthMiddleware = void 0;
exports.createAuthMiddleware = createAuthMiddleware;
class AuthMiddleware {
authService;
dataSource;
constructor(authService, dataSource) {
this.authService = authService;
this.dataSource = dataSource;
}
/**
* Middleware de autenticación requerida
*/
authenticate = async (req, res, next) => {
try {
const token = this.extractToken(req);
if (!token) {
res.status(401).json({
error: 'Unauthorized',
message: 'No token provided',
});
return;
}
const validation = this.authService.validateAccessToken(token);
if (!validation.valid || !validation.payload) {
res.status(401).json({
error: 'Unauthorized',
message: validation.error || 'Invalid token',
});
return;
}
// Establecer información en el request
req.user = validation.payload;
req.tenantId = validation.payload.tenantId;
// Configurar tenant_id para RLS en PostgreSQL
await this.setTenantContext(validation.payload.tenantId);
next();
}
catch (error) {
res.status(401).json({
error: 'Unauthorized',
message: 'Authentication failed',
});
}
};
/**
* Middleware de autenticación opcional
*/
optionalAuthenticate = async (req, _res, next) => {
try {
const token = this.extractToken(req);
if (token) {
const validation = this.authService.validateAccessToken(token);
if (validation.valid && validation.payload) {
req.user = validation.payload;
req.tenantId = validation.payload.tenantId;
await this.setTenantContext(validation.payload.tenantId);
}
}
next();
}
catch {
// Si hay error, continuar sin autenticación
next();
}
};
/**
* Middleware de autorización por roles
*/
authorize = (...allowedRoles) => {
return (req, res, next) => {
if (!req.user) {
res.status(401).json({
error: 'Unauthorized',
message: 'Authentication required',
});
return;
}
const hasRole = req.user.roles.some((role) => allowedRoles.includes(role));
if (!hasRole) {
res.status(403).json({
error: 'Forbidden',
message: 'Insufficient permissions',
});
return;
}
next();
};
};
/**
* Middleware que requiere rol de admin
*/
requireAdmin = (req, res, next) => {
return this.authorize('admin', 'super_admin')(req, res, next);
};
/**
* Middleware que requiere ser supervisor
*/
requireSupervisor = (req, res, next) => {
return this.authorize('admin', 'super_admin', 'supervisor_obra', 'supervisor_hse')(req, res, next);
};
/**
* Extraer token del header Authorization
*/
extractToken(req) {
const authHeader = req.headers.authorization;
if (!authHeader) {
return null;
}
// Bearer token
const [type, token] = authHeader.split(' ');
if (type !== 'Bearer' || !token) {
return null;
}
return token;
}
/**
* Configurar contexto de tenant para RLS
*/
async setTenantContext(tenantId) {
try {
await this.dataSource.query(`SET app.current_tenant_id = '${tenantId}'`);
}
catch (error) {
console.error('Error setting tenant context:', error);
throw new Error('Failed to set tenant context');
}
}
}
exports.AuthMiddleware = AuthMiddleware;
/**
* Factory para crear middleware de autenticación
*/
function createAuthMiddleware(authService, dataSource) {
return new AuthMiddleware(authService, dataSource);
}
//# sourceMappingURL=auth.middleware.js.map