fase(9): auth module with casl rbac and session management
This commit is contained in:
71
dist/modules/auth/application/middleware/AuthMiddleware.js
vendored
Normal file
71
dist/modules/auth/application/middleware/AuthMiddleware.js
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createAuthMiddleware = createAuthMiddleware;
|
||||
const crypto_1 = require("crypto");
|
||||
function createAuthMiddleware(userRepository, sessionRepository, apiKeyRepository) {
|
||||
return async function authMiddleware(req, res, next) {
|
||||
try {
|
||||
// 1. Check session cookie
|
||||
const sessionToken = req.cookies?.['abe_session'];
|
||||
if (sessionToken) {
|
||||
const session = await sessionRepository.findByToken(sessionToken);
|
||||
if (session && session.expiresAt > new Date()) {
|
||||
const user = await userRepository.findById(session.userId);
|
||||
if (user) {
|
||||
req.user = {
|
||||
id: user.id.toString(),
|
||||
email: user.email.value,
|
||||
name: user.name,
|
||||
role: user.role.value,
|
||||
orgId: user.orgId,
|
||||
};
|
||||
return next();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 2. Check Bearer JWT (session token in header)
|
||||
const authHeader = req.headers.authorization;
|
||||
if (authHeader?.startsWith('Bearer ')) {
|
||||
const token = authHeader.substring(7);
|
||||
const session = await sessionRepository.findByToken(token);
|
||||
if (session && session.expiresAt > new Date()) {
|
||||
const user = await userRepository.findById(session.userId);
|
||||
if (user) {
|
||||
req.user = {
|
||||
id: user.id.toString(),
|
||||
email: user.email.value,
|
||||
name: user.name,
|
||||
role: user.role.value,
|
||||
orgId: user.orgId,
|
||||
};
|
||||
return next();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 3. Check API key
|
||||
const apiKeyHeader = req.headers['x-abe-api-key'];
|
||||
if (apiKeyHeader && typeof apiKeyHeader === 'string') {
|
||||
const keyHash = (0, crypto_1.createHash)('sha256').update(apiKeyHeader).digest('hex');
|
||||
const apiKey = await apiKeyRepository.findByHash(keyHash);
|
||||
if (apiKey && !apiKey.isExpired()) {
|
||||
const user = await userRepository.findById(apiKey.userId);
|
||||
if (user) {
|
||||
await apiKeyRepository.updateLastUsed(apiKey.id.toString(), new Date());
|
||||
req.user = {
|
||||
id: user.id.toString(),
|
||||
email: user.email.value,
|
||||
name: user.name,
|
||||
role: user.role.value,
|
||||
orgId: user.orgId,
|
||||
};
|
||||
return next();
|
||||
}
|
||||
}
|
||||
}
|
||||
res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
catch {
|
||||
res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
};
|
||||
}
|
||||
21
dist/modules/auth/application/middleware/RBACMiddleware.js
vendored
Normal file
21
dist/modules/auth/application/middleware/RBACMiddleware.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.requirePermission = requirePermission;
|
||||
const AbilityFactory_1 = require("../../infrastructure/casl/AbilityFactory");
|
||||
function requirePermission(action, subject) {
|
||||
return function rbacMiddleware(req, res, next) {
|
||||
if (!req.user) {
|
||||
res.status(401).json({ error: 'Unauthorized' });
|
||||
return;
|
||||
}
|
||||
const ability = (0, AbilityFactory_1.defineAbilityFor)(req.user.role);
|
||||
if (!ability.can(action, subject)) {
|
||||
res.status(403).json({
|
||||
error: 'Forbidden',
|
||||
message: `You do not have permission to ${action} ${subject}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
next();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user