fase(9): auth module with casl rbac and session management
This commit is contained in:
170
dist/modules/auth/infrastructure/http/AuthController.js
vendored
Normal file
170
dist/modules/auth/infrastructure/http/AuthController.js
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createAuthController = createAuthController;
|
||||
const express_1 = require("express");
|
||||
const AuthMiddleware_1 = require("../../application/middleware/AuthMiddleware");
|
||||
function createAuthController(registerCommand, loginCommand, createOrgCommand, inviteMemberCommand, createApiKeyCommand, getUserQuery, listOrgMembersQuery, sessionRepository, apiKeyRepository, userRepository) {
|
||||
const router = (0, express_1.Router)();
|
||||
const authMiddleware = (0, AuthMiddleware_1.createAuthMiddleware)(userRepository, sessionRepository, apiKeyRepository);
|
||||
// POST /api/auth/register
|
||||
router.post('/register', async (req, res) => {
|
||||
const result = await registerCommand.execute({
|
||||
email: req.body.email,
|
||||
password: req.body.password,
|
||||
name: req.body.name,
|
||||
role: req.body.role,
|
||||
});
|
||||
if (!result.ok) {
|
||||
res.status(400).json({ error: result.error });
|
||||
return;
|
||||
}
|
||||
res.status(201).json(result.value);
|
||||
});
|
||||
// POST /api/auth/login
|
||||
router.post('/login', async (req, res) => {
|
||||
const result = await loginCommand.execute({
|
||||
email: req.body.email,
|
||||
password: req.body.password,
|
||||
});
|
||||
if (!result.ok) {
|
||||
res.status(401).json({ error: result.error });
|
||||
return;
|
||||
}
|
||||
const { sessionToken, expiresAt, ...userData } = result.value;
|
||||
res.cookie('abe_session', sessionToken, {
|
||||
httpOnly: true,
|
||||
secure: process.env['NODE_ENV'] === 'production',
|
||||
sameSite: 'lax',
|
||||
expires: expiresAt,
|
||||
});
|
||||
res.json({ ...userData, sessionToken });
|
||||
});
|
||||
// POST /api/auth/logout
|
||||
router.post('/logout', authMiddleware, async (req, res) => {
|
||||
const token = req.cookies?.['abe_session'] ?? req.headers.authorization?.substring(7);
|
||||
if (token) {
|
||||
await sessionRepository.deleteByToken(token);
|
||||
}
|
||||
res.clearCookie('abe_session');
|
||||
res.json({ success: true });
|
||||
});
|
||||
// GET /api/auth/me
|
||||
router.get('/me', authMiddleware, async (req, res) => {
|
||||
const result = await getUserQuery.execute({ userId: req.user.id });
|
||||
if (!result.ok) {
|
||||
res.status(404).json({ error: result.error });
|
||||
return;
|
||||
}
|
||||
res.json(result.value);
|
||||
});
|
||||
// GET /api/auth/setup-required
|
||||
router.get('/setup-required', async (_req, res) => {
|
||||
const count = await userRepository.count();
|
||||
res.json({ required: count === 0 });
|
||||
});
|
||||
// POST /api/auth/setup — first-run setup
|
||||
router.post('/setup', async (req, res) => {
|
||||
const count = await userRepository.count();
|
||||
if (count > 0) {
|
||||
res.status(400).json({ error: 'Setup already completed' });
|
||||
return;
|
||||
}
|
||||
const registerResult = await registerCommand.execute({
|
||||
email: req.body.email,
|
||||
password: req.body.password,
|
||||
name: req.body.name,
|
||||
role: 'owner',
|
||||
});
|
||||
if (!registerResult.ok) {
|
||||
res.status(400).json({ error: registerResult.error });
|
||||
return;
|
||||
}
|
||||
const createOrgResult = await createOrgCommand.execute({
|
||||
name: req.body.orgName ?? 'My Organization',
|
||||
ownerId: registerResult.value.userId,
|
||||
});
|
||||
if (!createOrgResult.ok) {
|
||||
res.status(400).json({ error: createOrgResult.error });
|
||||
return;
|
||||
}
|
||||
res.status(201).json({
|
||||
user: registerResult.value,
|
||||
organization: createOrgResult.value,
|
||||
});
|
||||
});
|
||||
// POST /api/auth/organizations — create org
|
||||
router.post('/organizations', authMiddleware, async (req, res) => {
|
||||
const result = await createOrgCommand.execute({
|
||||
name: req.body.name,
|
||||
ownerId: req.user.id,
|
||||
});
|
||||
if (!result.ok) {
|
||||
res.status(400).json({ error: result.error });
|
||||
return;
|
||||
}
|
||||
res.status(201).json(result.value);
|
||||
});
|
||||
// POST /api/auth/organizations/:orgId/members — invite member
|
||||
router.post('/organizations/:orgId/members', authMiddleware, async (req, res) => {
|
||||
const result = await inviteMemberCommand.execute({
|
||||
orgId: String(req.params['orgId']),
|
||||
inviterUserId: req.user.id,
|
||||
email: req.body.email,
|
||||
role: req.body.role ?? 'member',
|
||||
});
|
||||
if (!result.ok) {
|
||||
res.status(400).json({ error: result.error });
|
||||
return;
|
||||
}
|
||||
res.status(201).json(result.value);
|
||||
});
|
||||
// GET /api/auth/organizations/:orgId/members
|
||||
router.get('/organizations/:orgId/members', authMiddleware, async (req, res) => {
|
||||
const result = await listOrgMembersQuery.execute({ orgId: String(req.params['orgId']) });
|
||||
if (!result.ok) {
|
||||
res.status(404).json({ error: result.error });
|
||||
return;
|
||||
}
|
||||
res.json(result.value);
|
||||
});
|
||||
// POST /api/auth/api-keys — create API key
|
||||
router.post('/api-keys', authMiddleware, async (req, res) => {
|
||||
const result = await createApiKeyCommand.execute({
|
||||
userId: req.user.id,
|
||||
orgId: req.user.orgId ?? 'default',
|
||||
name: req.body.name,
|
||||
permissions: req.body.permissions,
|
||||
expiresAt: req.body.expiresAt ? new Date(req.body.expiresAt) : undefined,
|
||||
});
|
||||
if (!result.ok) {
|
||||
res.status(400).json({ error: result.error });
|
||||
return;
|
||||
}
|
||||
res.status(201).json(result.value);
|
||||
});
|
||||
// GET /api/auth/api-keys — list API keys
|
||||
router.get('/api-keys', authMiddleware, async (req, res) => {
|
||||
const keys = await apiKeyRepository.listByUser(req.user.id);
|
||||
res.json(keys.map((k) => ({
|
||||
id: k.id.toString(),
|
||||
name: k.name,
|
||||
keyPrefix: k.keyPrefix,
|
||||
permissions: k.permissions,
|
||||
expiresAt: k.expiresAt,
|
||||
lastUsedAt: k.lastUsedAt,
|
||||
createdAt: k.createdAt,
|
||||
})));
|
||||
});
|
||||
// DELETE /api/auth/api-keys/:id — revoke API key
|
||||
router.delete('/api-keys/:id', authMiddleware, async (req, res) => {
|
||||
const keyId = String(req.params['id']);
|
||||
const key = await apiKeyRepository.findById(keyId);
|
||||
if (!key || key.userId !== req.user.id) {
|
||||
res.status(404).json({ error: 'API key not found' });
|
||||
return;
|
||||
}
|
||||
await apiKeyRepository.delete(keyId);
|
||||
res.json({ success: true });
|
||||
});
|
||||
return router;
|
||||
}
|
||||
Reference in New Issue
Block a user