Files
Autonomous-Bug-Explorer/dist/modules/auth/infrastructure/http/AuthController.js
debian 08011d22d5 fase(25-26): keyboard shortcuts, mobile responsive, enterprise SSO/audit
- Phase 25.4: N shortcut for new exploration on dashboard (react-hotkeys-hook)
- Phase 25.5: overflow-x-auto on tables, responsive padding (p-4 md:p-6)
- Phase 26: SAML/OIDC/LDAP providers (build-fixed), TOTP/MFA service
- Phase 26: KyselySSOConfigRepository + KyselyTOTPRepository
- Phase 26: SSO HTTP controller (config CRUD + MFA setup/verify/disable)
- Phase 26: Audit module index.ts + SSO module index.ts
- Phase 26: Session management endpoints (findByUserId, deleteById, list/revoke)
- Phase 26: SSO and audit routes feature-gated (auth:sso, audit:logs)
- Phase 26: Frontend SSOSection (SAML/OIDC/LDAP config + TOTP setup)
- Phase 26: Frontend SessionsSection (list/revoke active sessions)
- Phase 26: Settings navigation updated with SSO & Sessions sections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 13:38:25 -04:00

193 lines
7.5 KiB
JavaScript

"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 });
});
// GET /api/auth/sessions — list active sessions (session management dashboard)
router.get('/sessions', authMiddleware, async (req, res) => {
const sessions = await sessionRepository.findByUserId(req.user.id);
res.json(sessions.map((s) => ({
id: s.id,
createdAt: new Date(s.createdAt).toISOString(),
expiresAt: new Date(s.expiresAt).toISOString(),
})));
});
// DELETE /api/auth/sessions/:id — revoke a specific session
router.delete('/sessions/:id', authMiddleware, async (req, res) => {
const sessionId = String(req.params['id']);
// Only allow revoking own sessions
const userSessions = await sessionRepository.findByUserId(req.user.id);
const owns = userSessions.some((s) => s.id === sessionId);
if (!owns) {
res.status(404).json({ error: 'Session not found' });
return;
}
await sessionRepository.deleteById(sessionId);
res.json({ success: true });
});
return router;
}