From 143a6a8ab9c2f1dba9227d8f4240985468bd9cd7 Mon Sep 17 00:00:00 2001 From: aniebietafia Date: Tue, 3 Sep 2024 13:13:04 +0100 Subject: [PATCH 1/8] feat: jwt payload interface --- brints-estate-api/src/types/jwt.interface.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 brints-estate-api/src/types/jwt.interface.ts diff --git a/brints-estate-api/src/types/jwt.interface.ts b/brints-estate-api/src/types/jwt.interface.ts new file mode 100644 index 0000000..3fa155e --- /dev/null +++ b/brints-estate-api/src/types/jwt.interface.ts @@ -0,0 +1,10 @@ +export interface JwtPayload { + sub: string; + first_name: string; + last_name: string; + email: string; + role: string; + verified: boolean; + iat?: number; + exp?: number; +} From 343094037cff7ba4341f8e77785839af0867ea3c Mon Sep 17 00:00:00 2001 From: aniebietafia Date: Tue, 3 Sep 2024 13:13:44 +0100 Subject: [PATCH 2/8] feat: jwt configurations --- brints-estate-api/src/auth/config/jwt.config.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 brints-estate-api/src/auth/config/jwt.config.ts diff --git a/brints-estate-api/src/auth/config/jwt.config.ts b/brints-estate-api/src/auth/config/jwt.config.ts new file mode 100644 index 0000000..059b97f --- /dev/null +++ b/brints-estate-api/src/auth/config/jwt.config.ts @@ -0,0 +1,10 @@ +import { registerAs } from '@nestjs/config'; + +export default registerAs('jwt', () => { + return { + secret: process.env.JWT_SECRET, + expiresIn: parseInt(process.env.JWT_ACCESS_TOKEN_TTL ?? '3600', 10), + audience: process.env.JWT_TOKEN_AUDIENCE, + issuer: process.env.JWT_TOKEN_ISSUER, + }; +}); From 6860985602937c9f63695edcbe9a72a9f798fff4 Mon Sep 17 00:00:00 2001 From: aniebietafia Date: Tue, 3 Sep 2024 13:14:43 +0100 Subject: [PATCH 3/8] feat: added exception check if user is not verified --- .../src/auth/providers/login-user.provider.ts | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/brints-estate-api/src/auth/providers/login-user.provider.ts b/brints-estate-api/src/auth/providers/login-user.provider.ts index 0c48ce6..d8ca355 100644 --- a/brints-estate-api/src/auth/providers/login-user.provider.ts +++ b/brints-estate-api/src/auth/providers/login-user.provider.ts @@ -1,11 +1,15 @@ import { forwardRef, HttpStatus, Inject, Injectable } from '@nestjs/common'; import { Repository } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; +import { JwtService } from '@nestjs/jwt'; +import { ConfigType } from '@nestjs/config'; import { User } from 'src/users/entities/user.entity'; import { HashingProvider } from './hashing.provider'; import { LoginUserDto } from '../dto/login.dto'; import { CustomException } from 'src/exceptions/custom.exception'; +import jwtConfig from '../config/jwt.config'; +import { JwtPayload } from 'src/types/jwt.interface'; @Injectable() export class LoginUserProvider { @@ -15,9 +19,16 @@ export class LoginUserProvider { @Inject(forwardRef(() => HashingProvider)) private readonly hashingProvider: HashingProvider, + + private readonly jwtService: JwtService, + + @Inject(jwtConfig.KEY) + private readonly jwtConfiguration: ConfigType, ) {} - public async loginUser(loginUserDto: LoginUserDto): Promise { + public async loginUser( + loginUserDto: LoginUserDto, + ): Promise<{ access_token: string }> { const user = await this.userRepository.findOne({ where: { email: loginUserDto.email }, }); @@ -38,6 +49,29 @@ export class LoginUserProvider { ); } - return user; + if (!user.isVerified) { + throw new CustomException( + HttpStatus.BAD_REQUEST, + 'User account not verified', + ); + } + + const payload: JwtPayload = { + sub: user.id, + first_name: user.first_name, + last_name: user.last_name, + email: user.email, + role: user.role, + verified: user.isVerified, + }; + + const access_token = await this.jwtService.signAsync(payload, { + secret: this.jwtConfiguration.secret, + expiresIn: this.jwtConfiguration.expiresIn, + audience: this.jwtConfiguration.audience, + issuer: this.jwtConfiguration.issuer, + }); + + return { access_token }; } } From 573863b1062e492ce4092669fc59f56b2f9a4c16 Mon Sep 17 00:00:00 2001 From: aniebietafia Date: Tue, 3 Sep 2024 13:15:38 +0100 Subject: [PATCH 4/8] feat: injected JwtModule --- brints-estate-api/src/auth/auth.module.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/brints-estate-api/src/auth/auth.module.ts b/brints-estate-api/src/auth/auth.module.ts index 4dd887e..cdda500 100644 --- a/brints-estate-api/src/auth/auth.module.ts +++ b/brints-estate-api/src/auth/auth.module.ts @@ -1,17 +1,22 @@ import { forwardRef, Module } from '@nestjs/common'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { JwtModule } from '@nestjs/jwt'; + import { AuthController } from './auth.controller'; import { AuthService } from './providers/auth.service'; import { UsersModule } from 'src/users/users.module'; import { HashingProvider } from './providers/hashing.provider'; import { BcryptProvider } from './providers/bcrypt.provider'; import { CreateUserProvider } from './providers/create-user.provider'; -import { UserHelper } from 'src/utils/userHelper.lib'; -import { GenerateTokenHelper } from 'src/utils/generate-token.lib'; +import { UserHelper } from '../utils/userHelper.lib'; +import { GenerateTokenHelper } from '../utils/generate-token.lib'; import { LoginUserProvider } from './providers/login-user.provider'; +import jwtConfig from './config/jwt.config'; @Module({ controllers: [AuthController], providers: [ + ConfigService, AuthService, CreateUserProvider, LoginUserProvider, @@ -22,7 +27,11 @@ import { LoginUserProvider } from './providers/login-user.provider'; useClass: BcryptProvider, }, ], - imports: [forwardRef(() => UsersModule)], + imports: [ + forwardRef(() => UsersModule), + ConfigModule.forFeature(jwtConfig), + JwtModule.registerAsync(jwtConfig.asProvider()), + ], exports: [AuthService, HashingProvider], }) export class AuthModule {} From 8098b9d525ad641df61fe2fbc2c26204adfeffba Mon Sep 17 00:00:00 2001 From: aniebietafia Date: Tue, 3 Sep 2024 13:16:17 +0100 Subject: [PATCH 5/8] feat: added global exception filters --- brints-estate-api/src/main.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/brints-estate-api/src/main.ts b/brints-estate-api/src/main.ts index d5215b5..6724f62 100644 --- a/brints-estate-api/src/main.ts +++ b/brints-estate-api/src/main.ts @@ -4,6 +4,7 @@ import { Logger, ValidationPipe } from '@nestjs/common'; import { AppModule } from './app.module'; import { swaggerInitializer } from './config/config.swagger'; +import { HttpExceptionFilter } from './exceptions/http-exception.filter'; async function bootstrap() { const app = await NestFactory.create(AppModule); @@ -14,6 +15,8 @@ async function bootstrap() { }), ); + app.useGlobalFilters(new HttpExceptionFilter()); + const configService = new ConfigService(); const port = configService.get('APP_PORT'); From 71da612fc364e182868d1796080f552445e98359 Mon Sep 17 00:00:00 2001 From: aniebietafia Date: Tue, 3 Sep 2024 13:17:09 +0100 Subject: [PATCH 6/8] initializing access token guard --- .../auth/guards/access-token/access-token.guard.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 brints-estate-api/src/auth/guards/access-token/access-token.guard.ts diff --git a/brints-estate-api/src/auth/guards/access-token/access-token.guard.ts b/brints-estate-api/src/auth/guards/access-token/access-token.guard.ts new file mode 100644 index 0000000..e88de7d --- /dev/null +++ b/brints-estate-api/src/auth/guards/access-token/access-token.guard.ts @@ -0,0 +1,11 @@ +import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; +import { Observable } from 'rxjs'; + +@Injectable() +export class AccessTokenGuard implements CanActivate { + canActivate( + context: ExecutionContext, + ): boolean | Promise | Observable { + return true; + } +} From 4fae9ac3d6103ffc1604f6dccb524d5afcdcdf63 Mon Sep 17 00:00:00 2001 From: aniebietafia Date: Tue, 3 Sep 2024 13:18:00 +0100 Subject: [PATCH 7/8] feat: updated with jwt config --- brints-estate-api/src/config/config.service.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/brints-estate-api/src/config/config.service.ts b/brints-estate-api/src/config/config.service.ts index 18cdcf5..8c3df9b 100644 --- a/brints-estate-api/src/config/config.service.ts +++ b/brints-estate-api/src/config/config.service.ts @@ -17,6 +17,16 @@ export class AppConfigService { app: { port: this.configService.get('APP_PORT') as number, }, + jwt: { + secret: this.configService.get('JWT_SECRET') as string, + expiresIn: this.configService.get( + 'JWT_ACCESS_TOKEN_TTL', + ) as number, + audience: this.configService.get( + 'JWT_TOKEN_AUDIENCE', + ) as string, + issuer: this.configService.get('JWT_TOKEN_ISSUER') as string, + }, }; } } From 42f0e05db000791cb59fde56a4684cf08de7be51 Mon Sep 17 00:00:00 2001 From: aniebietafia Date: Tue, 3 Sep 2024 13:18:26 +0100 Subject: [PATCH 8/8] tsconfig build --- brints-estate-api/tsconfig.build.json | 1 + 1 file changed, 1 insertion(+) diff --git a/brints-estate-api/tsconfig.build.json b/brints-estate-api/tsconfig.build.json index 64f86c6..3ff5f0b 100644 --- a/brints-estate-api/tsconfig.build.json +++ b/brints-estate-api/tsconfig.build.json @@ -1,4 +1,5 @@ { "extends": "./tsconfig.json", + "include": ["src/**/*.ts", "src/**/*.d.ts"], "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] }