diff --git a/.gitignore b/.gitignore index 0a3c59f36..d89d3c862 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ node_modules/ # Ignorar arquivos de build dist/ + + diff --git a/.prettierrc b/.prettierrc index a20502b7f..6de9cff5b 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,5 @@ { "singleQuote": true, - "trailingComma": "all" + "trailingComma": "all", + "endOfLine": "lf" } diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..7e6882bfa --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "files.eol": "\n" +} diff --git a/README.md b/README.md index 0e942242b..fea91ec4b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 [circleci-url]: https://circleci.com/gh/nestjs/nest - +

A progressive Node.js framework for building efficient and scalable server-side applications.

NPM Version @@ -70,4 +70,4 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors ## License - Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE). +Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE). diff --git a/docker-compose.yml b/docker-compose.yml index ebec4c445..4d534a217 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: - POSTGRES_PASSWORD=${DATABASE_PASSWORD} - POSTGRES_DB=${DATABASE_NAME} ports: - - "5432:5432" + - '5432:5432' volumes: - postgres_data:/var/lib/postgresql/data diff --git a/package-lock.json b/package-lock.json index cd7e9f049..9e5e870b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10243,4 +10243,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/app.module.ts b/src/app.module.ts index 449e9979a..e2721d5f0 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,13 +1,27 @@ import { Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; +import configuration from './config/configuration'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { EventModule } from './event/event.module'; import { OrganizerModule } from './organizer/organizer.module'; import { VolunteerModule } from './volunteer/volunteer.module'; +import { AuthModule } from './auth/auth.module'; +import { PrismaModule } from './prisma/prisma.module'; @Module({ - imports: [EventModule, OrganizerModule, VolunteerModule], + imports: [ + ConfigModule.forRoot({ + load: [configuration], + isGlobal: true, + }), + EventModule, + OrganizerModule, + VolunteerModule, + AuthModule, + PrismaModule, + ], controllers: [AppController], providers: [AppService], }) -export class AppModule { } +export class AppModule {} diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts new file mode 100644 index 000000000..7b0b6d05d --- /dev/null +++ b/src/auth/auth.controller.ts @@ -0,0 +1,26 @@ +import { Controller, Post, Body, UnauthorizedException } from '@nestjs/common'; +import { AuthService } from './auth.service'; +import { JwtService } from '@nestjs/jwt'; + +@Controller('auth') +export class AuthController { + constructor( + private authService: AuthService, + private jwtService: JwtService, + ) {} + + @Post('login') + async login(@Body() body: { email: string; password: string }) { + const user = await this.authService.validateUser(body.email, body.password); + if (!user) { + throw new UnauthorizedException('Invalid credentials'); + } + + const payload = { email: user.email, sub: user.id, type: user.type }; + const accessToken = this.jwtService.sign(payload); + return { + access_token: accessToken, + user: user, + }; + } +} diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts new file mode 100644 index 000000000..369db014d --- /dev/null +++ b/src/auth/auth.module.ts @@ -0,0 +1,23 @@ +import { Module } from '@nestjs/common'; +import { AuthService } from './auth.service'; + +import { PrismaModule } from '../prisma/prisma.module'; +import { JwtModule } from '@nestjs/jwt'; + +import { PassportModule } from '@nestjs/passport'; +import { AuthController } from './auth.controller'; +import { JwtStrategy } from './jwt.strategy'; + +@Module({ + imports: [ + PrismaModule, + PassportModule, + JwtModule.register({ + secret: 'your_jwt_secret_key', + signOptions: { expiresIn: '60m' }, + }), + ], + providers: [AuthService, JwtStrategy], + controllers: [AuthController], +}) +export class AuthModule {} diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts new file mode 100644 index 000000000..a9c0e616f --- /dev/null +++ b/src/auth/auth.service.ts @@ -0,0 +1,27 @@ +import { Injectable, UnauthorizedException } from '@nestjs/common'; +import { PrismaService } from '../prisma/prisma.service'; + +@Injectable() +export class AuthService { + constructor(private prisma: PrismaService) {} + + async validateUser(email: string, password: string): Promise { + const organizer = await this.prisma.organizer.findUnique({ + where: { email }, + }); + + if (organizer && organizer.password === password) { + return { ...organizer, type: 'organizer' }; + } + + const volunteer = await this.prisma.volunteer.findUnique({ + where: { email }, + }); + + if (volunteer && volunteer.password === password) { + return { ...volunteer, type: 'volunteer' }; + } + + throw new UnauthorizedException('Invalid credentials'); + } +} diff --git a/src/auth/jwt.strategy.ts b/src/auth/jwt.strategy.ts new file mode 100644 index 000000000..8b6d0649a --- /dev/null +++ b/src/auth/jwt.strategy.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@nestjs/common'; +import { PassportStrategy } from '@nestjs/passport'; +import { ExtractJwt, Strategy } from 'passport-jwt'; +import { ConfigService } from '@nestjs/config'; + +@Injectable() +export class JwtStrategy extends PassportStrategy(Strategy) { + constructor(private readonly configService: ConfigService) { + super({ + jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), + ignoreExpiration: false, + secretOrKey: configService.get('JWT_SECRET'), + }); + } + + async validate(payload: any) { + return { userId: payload.sub, email: payload.email, type: payload.type }; + } +} diff --git a/src/config/configuration.ts b/src/config/configuration.ts new file mode 100644 index 000000000..59f184f3f --- /dev/null +++ b/src/config/configuration.ts @@ -0,0 +1,3 @@ +export default () => ({ + JWT_SECRET: process.env.JWT_SECRET, +}); diff --git a/src/config/env.d.ts b/src/config/env.d.ts new file mode 100644 index 000000000..4f28be3a2 --- /dev/null +++ b/src/config/env.d.ts @@ -0,0 +1,5 @@ +declare namespace NodeJS { + interface ProcessEnv { + JWT_SECRET: string; + } +} diff --git a/src/event/event.controller.ts b/src/event/event.controller.ts index 3e3a9f5eb..274d02843 100644 --- a/src/event/event.controller.ts +++ b/src/event/event.controller.ts @@ -13,7 +13,7 @@ import { CreateEventDto, EventService } from './event.service'; @ApiTags('events') @Controller('events') export class EventController { - constructor(private readonly eventService: EventService) { } + constructor(private readonly eventService: EventService) {} @Post() @ApiOperation({ summary: 'Create an event' }) diff --git a/src/event/event.module.ts b/src/event/event.module.ts index a302390a5..659553404 100644 --- a/src/event/event.module.ts +++ b/src/event/event.module.ts @@ -6,4 +6,4 @@ import { EventService } from './event.service'; controllers: [EventController], providers: [EventService], }) -export class EventModule { } +export class EventModule {} diff --git a/src/main.ts b/src/main.ts index 8f217db79..cce0e1b21 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,6 +5,13 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); + // Configurar CORS usando enableCors + app.enableCors({ + origin: 'http://localhost:3001', // Adicione a origem permitida aqui + methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', + credentials: true, // Se precisar permitir cookies entre diferentes origens + }); + const config = new DocumentBuilder() .setTitle('API-MAIN --- ConnectTech') .setDescription('Connect Tech ') diff --git a/src/organizer/organizer.controller.ts b/src/organizer/organizer.controller.ts index 065965789..d0850128e 100644 --- a/src/organizer/organizer.controller.ts +++ b/src/organizer/organizer.controller.ts @@ -14,7 +14,7 @@ import { Organizer } from '@prisma/client'; @ApiTags('organizers') @Controller('organizers') export class OrganizerController { - constructor(private readonly organizerService: OrganizerService) { } + constructor(private readonly organizerService: OrganizerService) {} @Post() @ApiOperation({ summary: 'Create organizer' }) diff --git a/src/organizer/organizer.module.ts b/src/organizer/organizer.module.ts index 0175d6dd1..be11d255f 100644 --- a/src/organizer/organizer.module.ts +++ b/src/organizer/organizer.module.ts @@ -6,4 +6,4 @@ import { OrganizerService } from './organizer.service'; controllers: [OrganizerController], providers: [OrganizerService], }) -export class OrganizerModule { } +export class OrganizerModule {} diff --git a/src/prisma/prisma.module.ts b/src/prisma/prisma.module.ts new file mode 100644 index 000000000..ec0ce3291 --- /dev/null +++ b/src/prisma/prisma.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { PrismaService } from './prisma.service'; + +@Module({ + providers: [PrismaService], + exports: [PrismaService], +}) +export class PrismaModule {} diff --git a/src/prisma/prisma.service.ts b/src/prisma/prisma.service.ts new file mode 100644 index 000000000..7ffd32daa --- /dev/null +++ b/src/prisma/prisma.service.ts @@ -0,0 +1,16 @@ +import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; +import { PrismaClient } from '@prisma/client'; + +@Injectable() +export class PrismaService + extends PrismaClient + implements OnModuleInit, OnModuleDestroy +{ + async onModuleInit() { + await this.$connect(); + } + + async onModuleDestroy() { + await this.$disconnect(); + } +} diff --git a/src/volunteer/volunteer.controller.ts b/src/volunteer/volunteer.controller.ts index c2a056f75..c7c034ebe 100644 --- a/src/volunteer/volunteer.controller.ts +++ b/src/volunteer/volunteer.controller.ts @@ -14,7 +14,7 @@ import { Volunteer } from '@prisma/client'; @ApiTags('volunteers') @Controller('volunteers') export class VolunteerController { - constructor(private readonly volunteerService: VolunteerService) { } + constructor(private readonly volunteerService: VolunteerService) {} @Post() @ApiOperation({ summary: 'Create a new volunteer' }) diff --git a/src/volunteer/volunteer.module.ts b/src/volunteer/volunteer.module.ts index dfcfeb1e8..063d2fbef 100644 --- a/src/volunteer/volunteer.module.ts +++ b/src/volunteer/volunteer.module.ts @@ -6,4 +6,4 @@ import { VolunteerService } from './volunteer.service'; controllers: [VolunteerController], providers: [VolunteerService], }) -export class VolunteerModule { } +export class VolunteerModule {}