Files
clube67_newwhats.local/clube67/newwhats.local/backend/src/modules/auth/auth.routes.ts
T
VPS 4 Deploy Agent 0dc5eefa06
continuous-integration/webhook Falha no deploy de clube67_newwhats.local (VPS 4)
chore(ops): restore missing root files in newwhats.clube67.com
2026-05-18 03:27:25 +02:00

128 lines
3.7 KiB
TypeScript

import { Router, type Request, type Response } from 'express'
import { z } from 'zod'
import { AuthService } from './auth.service'
import { authMiddleware } from '../../shared/middlewares/auth.middleware'
const service = new AuthService()
// ─── Schemas de validação ─────────────────────────────────────────────────────
const registerSchema = z.object({
name: z.string().min(2).max(100),
email: z.string().email(),
password: z.string().min(8).max(128),
planId: z.string().uuid().optional(),
})
const loginSchema = z.object({
email: z.string().email(),
password: z.string().min(1),
})
const refreshSchema = z.object({
refreshToken: z.string().min(1),
})
const changePasswordSchema = z.object({
currentPassword: z.string().min(1),
newPassword: z.string().min(8).max(128),
})
// ─── Helper para erros de validação / serviço ─────────────────────────────────
function handleError(res: Response, err: unknown) {
if (err instanceof z.ZodError) {
res.status(400).json({ error: 'Dados inválidos', details: err.flatten().fieldErrors })
return
}
const e = err as Error & { statusCode?: number }
res.status(e.statusCode ?? 500).json({ error: e.message ?? 'Erro interno' })
}
// ─── Router ───────────────────────────────────────────────────────────────────
export const authRouter = Router()
/**
* POST /api/auth/register
* Cria novo tenant (usuário com role USER).
* Retorna access + refresh token e dados do usuário.
*/
authRouter.post('/register', async (req: Request, res: Response) => {
try {
const body = registerSchema.parse(req.body) as any
const result = await service.register(body)
res.status(201).json(result)
} catch (err) {
handleError(res, err)
}
})
/**
* POST /api/auth/login
* Autentica usuário. Retorna access + refresh token.
*/
authRouter.post('/login', async (req: Request, res: Response) => {
try {
const body = loginSchema.parse(req.body) as any
const result = await service.login(body)
res.json(result)
} catch (err) {
handleError(res, err)
}
})
/**
* POST /api/auth/refresh
* Renova o access token usando o refresh token.
*/
authRouter.post('/refresh', async (req: Request, res: Response) => {
try {
const { refreshToken } = refreshSchema.parse(req.body)
const result = await service.refresh(refreshToken)
res.json(result)
} catch (err) {
handleError(res, err)
}
})
/**
* POST /api/auth/logout
* Revoga o refresh token do usuário autenticado.
*/
authRouter.post('/logout', authMiddleware, async (req: Request, res: Response) => {
try {
await service.logout(req.tenantId!)
res.json({ message: 'Sessão encerrada' })
} catch (err) {
handleError(res, err)
}
})
/**
* GET /api/auth/me
* Retorna dados do usuário autenticado + dias restantes do trial.
*/
authRouter.get('/me', authMiddleware, async (req: Request, res: Response) => {
try {
const user = await service.me(req.tenantId!)
res.json(user)
} catch (err) {
handleError(res, err)
}
})
/**
* PATCH /api/auth/password
* Altera a senha do usuário autenticado.
*/
authRouter.patch('/password', authMiddleware, async (req: Request, res: Response) => {
try {
const body = changePasswordSchema.parse(req.body) as any
await service.changePassword(req.tenantId!, body)
res.json({ message: 'Senha alterada com sucesso' })
} catch (err) {
handleError(res, err)
}
})