diff --git a/package-lock.json b/package-lock.json index 6f6181d..9ee6bc3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@types/bcrypt": "^5.0.2", "bcrypt": "^5.1.1", "cors": "2.8.5", - "express": "^4.21.0", + "express": "^4.21.1", "express-validator": "^7.2.0", "mongodb": "5.9.0", "mysql2": "3.11.3", @@ -3023,9 +3023,9 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -3693,9 +3693,9 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", @@ -3703,7 +3703,7 @@ "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", diff --git a/package.json b/package.json index 5328e2b..a3f0130 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@types/bcrypt": "^5.0.2", "bcrypt": "^5.1.1", "cors": "2.8.5", - "express": "^4.21.0", + "express": "^4.21.1", "express-validator": "^7.2.0", "mongodb": "5.9.0", "mysql2": "3.11.3", diff --git a/src/app.ts b/src/app.ts index 3f4b2c1..4225e32 100644 --- a/src/app.ts +++ b/src/app.ts @@ -12,35 +12,61 @@ import professorRouter from './routes/professorRoutes'; import alunoRouter from './routes/alunoRoutes'; import loginRouter from './routes/loginRoutes'; import pdiRouter from './routes/pdiRoutes'; -MysqlDataSource.initialize() - .then(() => { - console.log('Database initialized!'); - }) - .catch((err) => { - console.error('Database Error: ', err); - }); -const app = express(); +// Função para iniciar o banco de dados +const initializeDatabase = async () => { + try { + await MysqlDataSource.initialize(); + console.log('✅ Database initialized!'); + } catch (err) { + console.error('❌ Database initialization failed:', err); + process.exit(1); // Encerra o processo em caso de erro + } +}; + +// Função para configurar o Swagger +const setupSwagger = (app: express.Application) => { + const swaggerSpec = swaggerJSDoc(swaggerConfig); + app.use('/swagger', swaggerUI.serve, swaggerUI.setup(swaggerSpec)); + app.get('/swagger.json', (_req, res) => res.send(swaggerSpec)); + console.log('✅ Swagger configured at /swagger'); +}; + +const main = async () => { + await initializeDatabase(); -app.use(express.json()); -app.use(cors({ origin: true })); + const app = express(); -app.use('/admin', adminRouter); -app.use('/membros', membrosRouter); -app.use('/turmas', turmasRouter); -app.use('/professores', professorRouter); -app.use('/alunos', alunoRouter); -app.use('/auth', loginRouter); -app.use('/pdi', pdiRouter); -app.use(errorHandler); + // Middlewares + app.use(express.json()); + app.use(cors({ origin: true })); -const swaggerSpec = swaggerJSDoc(swaggerConfig); + // Rotas + app.use('/admin', adminRouter); + app.use('/membros', membrosRouter); + app.use('/turmas', turmasRouter); + app.use('/professores', professorRouter); + app.use('/pdi', pdiRouter); + app.use('/alunos', alunoRouter); + app.use('/auth', loginRouter); -app.use('/swagger', swaggerUI.serve, swaggerUI.setup(swaggerSpec)); -app.get('/swagger.json', (_req, res) => res.send(swaggerSpec)); + // Configuração do Swagger + setupSwagger(app); -console.log(`Add swagger on /swagger`); + // Middleware de erros + app.use(errorHandler); + + // Validação de variáveis de ambiente + const PORT = process.env.SERVER_PORT || 3000; + if (!PORT) { + console.error('❌ SERVER_PORT não definido nas variáveis de ambiente.'); + process.exit(1); + } + + // Inicia o servidor + app.listen(PORT, () => { + console.log(`✅ Server listening on port ${PORT}`); + }); +}; -app.listen(process.env.SERVER_PORT, () => { - console.log(`Server listening on port ${process.env.SERVER_PORT}`); -}); +main(); diff --git a/src/config/swagger.ts b/src/config/swagger.ts index 4452338..0e304d9 100644 --- a/src/config/swagger.ts +++ b/src/config/swagger.ts @@ -1,29 +1,37 @@ import swaggerJSDoc from 'swagger-jsdoc'; -export const swaggerConfig: swaggerJSDoc.OAS3Options = { - swaggerDefinition: { +export const swaggerConfig: swaggerJSDoc.Options = { + definition: { openapi: '3.0.0', info: { title: 'Civitas API', description: 'Documentação da API do projeto Civitas', version: '1.0.0' }, - host: 'localhost:4444', - // Não obrigatório, serve apenas para definir a ordem das categorias - tags: [], + servers: [ + { + url: 'http://localhost:4444', // URL do servidor de desenvolvimento + description: 'Servidor Local' + } + ], externalDocs: { - description: 'View swagger.json', - url: '../swagger.json' + description: 'Swagger JSON', + url: '../swagger.json' // Confirme se esse caminho é acessível }, components: { securitySchemes: { BearerAuth: { - in: 'header', type: 'http', - scheme: 'bearer' + scheme: 'bearer', + bearerFormat: 'JWT' // Especifique que o formato esperado é JWT } } - } + }, + security: [ + { + BearerAuth: [] // Aplica a autenticação BearerAuth globalmente (se necessário) + } + ] }, - apis: ['src/routes/*.ts', 'routes/*.js'] + apis: ['src/routes/*.ts', 'routes/*.js'] // Caminhos para buscar as rotas }; diff --git a/src/routes/loginRoutes.ts b/src/routes/loginRoutes.ts index c0d0acf..bba44f5 100644 --- a/src/routes/loginRoutes.ts +++ b/src/routes/loginRoutes.ts @@ -4,6 +4,67 @@ import { LoginController } from '../controller/loginController'; const loginRoutes = Router(); const controller = new LoginController(); +/** + * @swagger + * tags: + * name: Login + * description: Autenticação e gerenciamento de login + */ + +/** + * @swagger + * /login: + * post: + * summary: Realiza o login de um usuário + * tags: [Login] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * email: + * type: string + * description: Email do usuário + * example: usuario@example.com + * password: + * type: string + * description: Senha do usuário + * format: password + * example: "12345678" + * responses: + * 200: + * description: Login bem-sucedido. + * content: + * application/json: + * schema: + * type: object + * properties: + * token: + * type: string + * description: Token de autenticação + * 400: + * description: Erro na requisição (dados inválidos). + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: Mensagem de erro detalhada + * 401: + * description: Credenciais inválidas. + * content: + * application/json: + * schema: + * type: object + * properties: + * error: + * type: string + * description: Mensagem de erro detalhada + */ loginRoutes.post('/login', (req, res) => controller.login(req, res)); export default loginRoutes;