"use strict"; // ============================================================ // Plugin: core-auth — Routes // ============================================================ // Migrated from: backend/src/routes/auth.routes.ts // backend/src/controllers/auth.controller.ts var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAuthRoutes = createAuthRoutes; const express_1 = require("express"); const bcryptjs_1 = __importDefault(require("bcryptjs")); const jsonwebtoken_1 = __importDefault(require("jsonwebtoken")); function createAuthRoutes(ctx) { const router = (0, express_1.Router)(); const { db, hooks } = ctx; // ── POST /login ─────────────────────────────────────── router.post('/login', async (req, res) => { try { const { email, password } = req.body; if (!email || !password) { return res.status(400).json({ error: 'Email e senha são obrigatórios' }); } const user = await db('users').where({ email }).first(); if (!user) { return res.status(401).json({ error: 'Credenciais inválidas' }); } const isValid = await bcryptjs_1.default.compare(password, user.password_hash); if (!isValid) { return res.status(401).json({ error: 'Credenciais inválidas' }); } const accessToken = jsonwebtoken_1.default.sign({ id: user.id, email: user.email, role: user.role }, process.env.JWT_SECRET, { expiresIn: (process.env.JWT_EXPIRES_IN || '15m') }); const refreshToken = jsonwebtoken_1.default.sign({ id: user.id, type: 'refresh' }, process.env.JWT_REFRESH_SECRET, { expiresIn: (process.env.JWT_REFRESH_EXPIRES_IN || '7d') }); // Emit hook event await hooks.emit('user:login', { userId: user.id, ip: req.ip }); // Audit log await db('audit_log').insert({ user_id: user.id, action: 'LOGIN', entity_type: 'user', entity_id: user.id, details: 'Usuário logou no sistema', ip_address: req.ip, }).catch(() => { }); // non-critical const { password_hash, ...safeUser } = user; res.json({ user: safeUser, accessToken, refreshToken }); } catch (err) { ctx.logger.error(`Login error: ${err.message}`); res.status(500).json({ error: 'Erro interno no servidor' }); } }); // ── POST /register ──────────────────────────────────── router.post('/register', async (req, res) => { try { const { name, email, password, cpf, whatsapp, city, neighborhood, state } = req.body; if (!name || !email || !password) { return res.status(400).json({ error: 'Nome, email e senha são obrigatórios' }); } const existing = await db('users').where({ email }).first(); if (existing) { return res.status(409).json({ error: 'Email já cadastrado' }); } const password_hash = await bcryptjs_1.default.hash(password, 12); const [id] = await db('users').insert({ name, email, password_hash, cpf: cpf || null, whatsapp: whatsapp || null, city: city || null, neighborhood: neighborhood || null, state: state || null, role: 'user', status: 'active', }); await hooks.emit('user:register', { userId: id, email }); res.status(201).json({ id, name, email, role: 'user' }); } catch (err) { ctx.logger.error(`Register error: ${err.message}`); res.status(500).json({ error: 'Erro interno no servidor' }); } }); // ── GET /me ─────────────────────────────────────────── router.get('/me', async (req, res) => { try { const authHeader = req.headers.authorization; if (!authHeader?.startsWith('Bearer ')) { return res.status(401).json({ error: 'Token não fornecido' }); } const token = authHeader.split(' ')[1]; const payload = jsonwebtoken_1.default.verify(token, process.env.JWT_SECRET); const user = await db('users') .where({ id: payload.id }) .select('id', 'name', 'email', 'role', 'status', 'whatsapp', 'cpf', 'city', 'neighborhood', 'state', 'partner_id', 'created_at') .first(); if (!user) { return res.status(404).json({ error: 'Usuário não encontrado' }); } let partnerConsent = false; let partnerConsentAt = null; let partnerConsentIp = null; if (user?.partner_id) { const partner = await db('partners') .where({ id: user.partner_id }) .select('data_consent', 'consent_at', 'consent_ip') .first(); partnerConsent = Boolean(partner?.data_consent); partnerConsentAt = partner?.consent_at || null; partnerConsentIp = partner?.consent_ip || null; } res.json({ ...user, partnerConsent, partnerConsentAt, partnerConsentIp }); } catch (err) { if (err.name === 'TokenExpiredError') { return res.status(401).json({ error: 'Token expirado' }); } res.status(401).json({ error: 'Token inválido' }); } }); // ── POST /refresh ───────────────────────────────────── router.post('/refresh', async (req, res) => { try { const { refreshToken } = req.body; if (!refreshToken) { return res.status(400).json({ error: 'Refresh token obrigatório' }); } const payload = jsonwebtoken_1.default.verify(refreshToken, process.env.JWT_REFRESH_SECRET); if (payload.type !== 'refresh') { return res.status(401).json({ error: 'Token inválido' }); } const user = await db('users').where({ id: payload.id }).first(); if (!user) { return res.status(404).json({ error: 'Usuário não encontrado' }); } const newAccessToken = jsonwebtoken_1.default.sign({ id: user.id, email: user.email, role: user.role }, process.env.JWT_SECRET, { expiresIn: (process.env.JWT_EXPIRES_IN || '15m') }); await hooks.emit('token:refresh', { userId: user.id }); res.json({ accessToken: newAccessToken }); } catch (err) { res.status(401).json({ error: 'Refresh token inválido ou expirado' }); } }); return router; } //# sourceMappingURL=routes.js.map