Skip to content

Commit

Permalink
feat: add project, environment module
Browse files Browse the repository at this point in the history
  • Loading branch information
rajdip-b committed Jan 2, 2024
1 parent 50e64ee commit fd5c4d7
Show file tree
Hide file tree
Showing 69 changed files with 5,336 additions and 6,732 deletions.
8 changes: 6 additions & 2 deletions apps/api/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import { PrismaModule } from '../prisma/prisma.module'
import { CommonModule } from '../common/common.module'
import { ResendModule } from '../resend/resend.module'
import { APP_GUARD } from '@nestjs/core'
import { AuthGuard } from '../auth/auth.guard'
import { AuthGuard } from '../auth/guard/auth.guard'
import { UserModule } from '../user/user.module'
import { ProjectModule } from '../project/project.module'
import { EnvironmentModule } from '../environment/environment.module'

@Module({
controllers: [AppController],
Expand All @@ -24,7 +26,9 @@ import { UserModule } from '../user/user.module'
CommonModule,
ResendModule,
SupabaseModule,
UserModule
UserModule,
ProjectModule,
EnvironmentModule
],
providers: [
{
Expand Down
18 changes: 14 additions & 4 deletions apps/api/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Module } from '@nestjs/common'
import { AuthService } from './auth.service'
import { AuthController } from './auth.controller'
import { AuthService } from './service/auth.service'
import { AuthController } from './controller/auth.controller'
import { JwtModule } from '@nestjs/jwt'
import { UserModule } from '../user/user.module'
import { AUTH_REPOSITORY } from './repository/interface.repository'
import { AuthRepository } from './repository/auth.repository'

@Module({
imports: [
Expand All @@ -13,9 +16,16 @@ import { JwtModule } from '@nestjs/jwt'
issuer: 'keyshade.xyz',
algorithm: 'HS256'
}
})
}),
UserModule
],
providers: [
AuthService,
{
provide: AUTH_REPOSITORY,
useClass: AuthRepository
}
],
providers: [AuthService],
controllers: [AuthController]
})
export class AuthModule {}
29 changes: 0 additions & 29 deletions apps/api/src/auth/auth.service.spec.ts

This file was deleted.

59 changes: 0 additions & 59 deletions apps/api/src/auth/auth.service.ts

This file was deleted.

35 changes: 35 additions & 0 deletions apps/api/src/auth/controller/auth.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Test, TestingModule } from '@nestjs/testing'
import { MockAuthRepository } from '../repository/mock.repository'
import { AUTH_REPOSITORY } from '../repository/interface.repository'
import { AuthService } from '../service/auth.service'
import { RESEND_SERVICE } from '../../resend/services/resend.service.interface'
import { MockResend } from '../../resend/services/mock.resend'
import { JwtService } from '@nestjs/jwt'
import { PrismaService } from '../../prisma/prisma.service'
import { AuthController } from './auth.controller'
import { USER_REPOSITORY } from '../../user/repository/interface.repository'
import { MockUserRepository } from '../../user/repository/mock.repository'

describe('AuthController', () => {
let controller: AuthController

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [AuthController],
providers: [
AuthService,
{ provide: RESEND_SERVICE, useClass: MockResend },
{ provide: AUTH_REPOSITORY, useClass: MockAuthRepository },
{ provide: USER_REPOSITORY, useClass: MockUserRepository },
JwtService,
PrismaService
]
}).compile()

controller = module.get<AuthController>(AuthController)
})

it('should be defined', () => {
expect(controller).toBeDefined()
})
})
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Controller, Param, Post, Query } from '@nestjs/common'
import { AuthService } from './auth.service'
import { UserAuthenticatedResponse } from './auth.types'
import { Public } from '../decorators/public.decorator'
import { AuthService } from '../service/auth.service'
import { UserAuthenticatedResponse } from '../auth.types'
import { Public } from '../../decorators/public.decorator'

@Controller('auth')
export class AuthController {
Expand All @@ -15,7 +15,10 @@ export class AuthController {

@Public()
@Post('validate-otp')
async validateOtp(@Query('email') email: string, @Query('otp') otp: string): Promise<UserAuthenticatedResponse> {
async validateOtp(
@Query('email') email: string,
@Query('otp') otp: string
): Promise<UserAuthenticatedResponse> {
return await this.authService.validateOtp(email, otp)
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import { CanActivate, ExecutionContext, ForbiddenException, Injectable } from '@nestjs/common'
import {
CanActivate,
ExecutionContext,
ForbiddenException,
Inject,
Injectable
} from '@nestjs/common'
import { JwtService } from '@nestjs/jwt'
import { Request } from 'express'
import { PrismaRepository } from '../prisma/prisma.repository'
import { Reflector } from '@nestjs/core'
import { IS_PUBLIC_KEY } from '../decorators/public.decorator'
import { IS_PUBLIC_KEY } from '../../decorators/public.decorator'
import {
IUserRepository,
USER_REPOSITORY
} from '../../user/repository/interface.repository'

@Injectable()
export class AuthGuard implements CanActivate {
constructor(
private jwtService: JwtService,
private repository: PrismaRepository,
@Inject(USER_REPOSITORY) private repository: IUserRepository,
private reflector: Reflector
) {}

Expand Down
56 changes: 56 additions & 0 deletions apps/api/src/auth/repository/auth.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Otp, User } from '@prisma/client'
import { IAuthRepository } from './interface.repository'
import { PrismaService } from '../../prisma/prisma.service'

export class AuthRepository implements IAuthRepository {
constructor(private readonly prisma: PrismaService) {}

async isOtpValid(email: User['email'], otp: string): Promise<boolean> {
const timeNow = new Date()
return (
(await this.prisma.otp.count({
where: {
code: otp,
user: {
email
},
expiresAt: {
gt: timeNow
}
}
})) > 0
)
}

async createOtp(
email: User['email'],
otp: string,
expiresAfter: number
): Promise<Otp> {
const timeNow = new Date()
return await this.prisma.otp.create({
data: {
code: otp,
expiresAt: new Date(timeNow.getTime() + expiresAfter),
user: {
connect: {
email
}
}
}
})
}

async deleteOtp(email: User['email'], otp: string): Promise<void> {
await this.prisma.otp.delete({
where: {
code: otp,
AND: {
user: {
email
}
}
}
})
}
}
37 changes: 37 additions & 0 deletions apps/api/src/auth/repository/interface.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { User, Otp } from '@prisma/client'

export const AUTH_REPOSITORY = 'AUTH_REPOSITORY'

/**
* Interface for the Auth Repository.
*/
export interface IAuthRepository {
/**
* Checks if an OTP is valid for the given email.
* @param {User['email']} email - The email against which to check the OTP.
* @param {string} otp - The OTP code to check.
* @returns {Promise<boolean>} - A promise that resolves to true if the OTP is valid, false otherwise.
*/
isOtpValid(email: User['email'], otp: string): Promise<boolean>

/**
* Creates an OTP for the given email.
* @param {User['email']} email - The email to create the OTP for.
* @param {string} otp - The OTP code.
* @param {number} expiresAfter - The number of milliseconds after which the OTP expires.
* @returns {Promise<Otp>} - A promise that resolves to the created OTP.
*/
createOtp(
email: User['email'],
otp: string,
expiresAfter: number
): Promise<Otp>

/**
* Deletes an OTP.
* @param {User['email']} email - The email of the OTP to delete.
* @param {string} otp - The OTP code to delete.
* @returns {Promise<void>} - A promise that resolves when the OTP is successfully deleted.
*/
deleteOtp(email: User['email'], otp: string): Promise<void>
}
23 changes: 23 additions & 0 deletions apps/api/src/auth/repository/mock.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { IAuthRepository } from './interface.repository'

export class MockAuthRepository implements IAuthRepository {
isOtpValid(email: string, otp: string): Promise<boolean> {
throw new Error('Method not implemented.')
}
createOtp(
email: string,
otp: string,
expiresAfter: number
): Promise<{
code: string
userId: string
createdAt: Date
expiresAt: Date
}> {
throw new Error('Method not implemented.')
}
deleteOtp(email: string, otp: string): Promise<void> {
throw new Error('Method not implemented.')
}
}
33 changes: 33 additions & 0 deletions apps/api/src/auth/service/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Test, TestingModule } from '@nestjs/testing'
import { AuthService } from './auth.service'
import { MockResend } from '../../resend/services/mock.resend'
import { RESEND_SERVICE } from '../../resend/services/resend.service.interface'
import { JwtService } from '@nestjs/jwt'
import { PrismaService } from '../../prisma/prisma.service'
import { AUTH_REPOSITORY } from '../repository/interface.repository'
import { MockAuthRepository } from '../repository/mock.repository'
import { USER_REPOSITORY } from '../../user/repository/interface.repository'
import { MockUserRepository } from '../../user/repository/mock.repository'

describe('AuthService', () => {
let service: AuthService

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
AuthService,
{ provide: RESEND_SERVICE, useClass: MockResend },
{ provide: AUTH_REPOSITORY, useClass: MockAuthRepository },
{ provide: USER_REPOSITORY, useClass: MockUserRepository },
JwtService,
PrismaService
]
}).compile()

service = module.get<AuthService>(AuthService)
})

it('should be defined', () => {
expect(service).toBeDefined()
})
})
Loading

0 comments on commit fd5c4d7

Please sign in to comment.