omnichannel-backend/src/main.ts
Rafael Lopes 59db214ed9
Some checks are pending
Deploy Dev / deploy (push) Waiting to run
FEAT: Implementada segurança JWT e controle de acesso
- Adicionado JwtAuthGuard global para validar tokens nas rotas privadas
- Adicionados decorators Public e Roles para separar rotas públicas e permissões
- Adicionado RolesGuard para proteger rotas administrativas por perfil
- Rotas privadas passam a exigir Authorization Bearer Token
- WebSocket do WhatsApp passa a exigir JWT no handshake
- Adicionado rate limit global com @nestjs/throttler
- Adicionado LoginDto e ValidationPipe para validar payload de login
- Extraído SQL de acesso do usuário para UserAccessRepository
- Melhorados logs de login LDAP/Microsoft sem expor dados sensíveis
2026-05-29 12:13:44 -03:00

66 lines
2.0 KiB
TypeScript

import 'reflect-metadata';
import { Logger, ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { json, urlencoded } from 'express';
import { AppModule } from './app.module';
import { validateAppEnv } from './infra/config/env';
import { loadEnv } from './infra/config/load-env';
async function bootstrap() {
loadEnv();
validateAppEnv();
const app = await NestFactory.create(AppModule, { bodyParser: false });
const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:3000';
const allowedOrigins = new Set(
frontendUrl
.split(',')
.map((origin) => origin.trim())
.filter(Boolean),
);
allowedOrigins.add('http://localhost:3000');
allowedOrigins.add('http://localhost:5173');
const port = Number(process.env.PORT || process.env.BACKEND_PORT || 3001);
const requestBodyLimit = process.env.REQUEST_BODY_LIMIT || '25mb';
app.use(json({ limit: requestBodyLimit }));
app.use(urlencoded({ extended: true, limit: requestBodyLimit }));
app.useGlobalPipes(
new ValidationPipe({
forbidNonWhitelisted: true,
transform: true,
whitelist: true,
}),
);
app.enableCors({
origin(origin, callback) {
if (!origin || allowedOrigins.has(origin)) {
callback(null, true);
return;
}
Logger.warn(`Origem CORS bloqueada: ${origin}`, 'Cors');
callback(null, false);
},
credentials: true,
});
const swaggerConfig = new DocumentBuilder()
.setTitle('Omnichannel Backend API')
.setDescription('Documentacao das rotas da API do Omnichannel Sothis.')
.setVersion('1.0.0')
.addBearerAuth()
.build();
const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig);
SwaggerModule.setup('docs', app, swaggerDocument, {
jsonDocumentUrl: 'docs/openapi.json',
});
await app.listen(port);
Logger.log(`Backend ouvindo na porta ${port}`, 'Bootstrap');
Logger.log(`Swagger disponivel em /docs`, 'Bootstrap');
}
bootstrap();