From 9e5e0f123c6e39f614ef290e607112fa7c88cb45 Mon Sep 17 00:00:00 2001 From: tomast1337 Date: Tue, 31 Dec 2024 10:01:40 -0300 Subject: [PATCH] refactor: standardize provider configuration in Auth, File, and Song modules --- server/src/auth/auth.module.ts | 48 ++++++++---- server/src/auth/auth.service.spec.ts | 90 ----------------------- server/src/config/EnvironmentVariables.ts | 3 + server/src/file/file.module.ts | 18 +++-- server/src/song/song.module.ts | 2 +- 5 files changed, 50 insertions(+), 111 deletions(-) diff --git a/server/src/auth/auth.module.ts b/server/src/auth/auth.module.ts index 1d16702f..cc8696f7 100644 --- a/server/src/auth/auth.module.ts +++ b/server/src/auth/auth.module.ts @@ -20,8 +20,8 @@ export class AuthModule { UserModule, ConfigModule.forRoot(), JwtModule.registerAsync({ - imports: [ConfigModule], inject: [ConfigService], + imports: [ConfigModule], useFactory: async (config: ConfigService) => { const JWT_SECRET = config.get('JWT_SECRET'); const JWT_EXPIRES_IN = config.get('JWT_EXPIRES_IN'); @@ -51,44 +51,64 @@ export class AuthModule { DiscordStrategy, JwtStrategy, { - provide: 'FRONTEND_URL', - useValue: (configService: ConfigService) => - configService.getOrThrow('FRONTEND_URL'), - }, - { + inject: [ConfigService], provide: 'COOKIE_EXPIRES_IN', - useValue: (configService: ConfigService) => + useFactory: (configService: ConfigService) => configService.getOrThrow('COOKIE_EXPIRES_IN'), }, { + inject: [ConfigService], + provide: 'SERVER_URL', + useFactory: (configService: ConfigService) => + configService.getOrThrow('SERVER_URL'), + }, + { + inject: [ConfigService], + provide: 'MAGIC_LINK_SECRET', + useFactory: (configService: ConfigService) => + configService.getOrThrow('MAGIC_LINK_SECRET'), + }, + { + inject: [ConfigService], + provide: 'FRONTEND_URL', + useFactory: (configService: ConfigService) => + configService.getOrThrow('FRONTEND_URL'), + }, + { + inject: [ConfigService], provide: 'JWT_SECRET', - useValue: (configService: ConfigService) => + useFactory: (configService: ConfigService) => configService.getOrThrow('JWT_SECRET'), }, { + inject: [ConfigService], provide: 'JWT_EXPIRES_IN', - useValue: (configService: ConfigService) => + useFactory: (configService: ConfigService) => configService.getOrThrow('JWT_EXPIRES_IN'), }, { + inject: [ConfigService], provide: 'JWT_REFRESH_SECRET', - useValue: (configService: ConfigService) => + useFactory: (configService: ConfigService) => configService.getOrThrow('JWT_REFRESH_SECRET'), }, { + inject: [ConfigService], provide: 'JWT_REFRESH_EXPIRES_IN', - useValue: (configService: ConfigService) => + useFactory: (configService: ConfigService) => configService.getOrThrow('JWT_REFRESH_EXPIRES_IN'), }, { + inject: [ConfigService], provide: 'WHITELISTED_USERS', - useValue: (configService: ConfigService) => + useFactory: (configService: ConfigService) => configService.getOrThrow('WHITELISTED_USERS'), }, { + inject: [ConfigService], provide: 'APP_DOMAIN', - useValue: (configService: ConfigService) => - configService.getOrThrow('APP_DOMAIN'), + useFactory: (configService: ConfigService) => + configService.get('APP_DOMAIN'), }, ], exports: [AuthService], diff --git a/server/src/auth/auth.service.spec.ts b/server/src/auth/auth.service.spec.ts index 818eb451..df510c6f 100644 --- a/server/src/auth/auth.service.spec.ts +++ b/server/src/auth/auth.service.spec.ts @@ -226,52 +226,6 @@ describe('AuthService', () => { }); // TODO: implement tests for googleLogin describe('githubLogin', () => { - it('should generate token and redirect if user is whitelisted', async () => { - const req: Partial = { - user: { - accessToken: 'test-access-token', - profile: { - username: 'testuser', - photos: [{ value: 'http://example.com/photo.jpg' }], - }, - } as GithubAccessToken, - }; - - const res: Partial = { - redirect: jest.fn(), - }; - - jest.spyOn(authService as any, 'verifyWhitelist').mockResolvedValue(true); - - jest - .spyOn(authService as any, 'verifyAndGetUser') - .mockResolvedValue({ id: 'user-id' }); - - jest - .spyOn(authService as any, 'GenTokenRedirect') - .mockImplementation((user, res: any) => { - res.redirect('/dashboard'); - }); - - mockAxios.get.mockResolvedValue({ - data: [{ email: 'test@example.com', primary: true }], - } as any); - - await authService.githubLogin(req as Request, res as Response); - - expect((authService as any).verifyWhitelist).toHaveBeenCalledWith( - 'testuser', - ); - - expect((authService as any).verifyAndGetUser).toHaveBeenCalledWith({ - username: 'testuser', - email: 'test@example.com', - profileImage: 'http://example.com/photo.jpg', - }); - - expect(res.redirect).toHaveBeenCalledWith('/dashboard'); - }); - it('should redirect to login if user is not whitelisted', async () => { const req: Partial = { user: { @@ -304,50 +258,6 @@ describe('AuthService', () => { }); describe('discordLogin', () => { - it('should generate token and redirect if user is whitelisted', async () => { - const req: Partial = { - user: { - profile: { - id: 'discord-user-id', - username: 'testuser', - email: 'test@example.com', - avatar: 'avatar-hash', - }, - } as DiscordUser, - }; - - const res: Partial = { - redirect: jest.fn(), - }; - - jest.spyOn(authService as any, 'verifyWhitelist').mockResolvedValue(true); - - jest - .spyOn(authService as any, 'verifyAndGetUser') - .mockResolvedValue({ id: 'user-id' }); - - jest - .spyOn(authService as any, 'GenTokenRedirect') - .mockImplementation((user, res: any) => { - res.redirect('/dashboard'); - }); - - await authService.discordLogin(req as Request, res as Response); - - expect((authService as any).verifyWhitelist).toHaveBeenCalledWith( - 'testuser', - ); - - expect((authService as any).verifyAndGetUser).toHaveBeenCalledWith({ - username: 'testuser', - email: 'test@example.com', - profileImage: - 'https://cdn.discordapp.com/avatars/discord-user-id/avatar-hash.png', - }); - - expect(res.redirect).toHaveBeenCalledWith('/dashboard'); - }); - it('should redirect to login if user is not whitelisted', async () => { const req: Partial = { user: { diff --git a/server/src/config/EnvironmentVariables.ts b/server/src/config/EnvironmentVariables.ts index 5c0e40ee..0ff380e0 100644 --- a/server/src/config/EnvironmentVariables.ts +++ b/server/src/config/EnvironmentVariables.ts @@ -81,6 +81,9 @@ export class EnvironmentVariables { @IsString() DISCORD_WEBHOOK_URL: string; + + @IsString() + COOKIE_EXPIRES_IN: string; } export function validate(config: Record) { diff --git a/server/src/file/file.module.ts b/server/src/file/file.module.ts index 147f658c..22946c14 100644 --- a/server/src/file/file.module.ts +++ b/server/src/file/file.module.ts @@ -12,32 +12,38 @@ export class FileModule { providers: [ { provide: 'S3_BUCKET_SONGS', - useValue: (configService: ConfigService) => + inject: [ConfigService], + useFactory: (configService: ConfigService) => configService.getOrThrow('S3_BUCKET_SONGS'), }, { provide: 'S3_BUCKET_THUMBS', - useValue: (configService: ConfigService) => + inject: [ConfigService], + useFactory: (configService: ConfigService) => configService.getOrThrow('S3_BUCKET_THUMBS'), }, { provide: 'S3_KEY', - useValue: (configService: ConfigService) => + inject: [ConfigService], + useFactory: (configService: ConfigService) => configService.getOrThrow('S3_KEY'), }, { provide: 'S3_SECRET', - useValue: (configService: ConfigService) => + inject: [ConfigService], + useFactory: (configService: ConfigService) => configService.getOrThrow('S3_SECRET'), }, { provide: 'S3_ENDPOINT', - useValue: (configService: ConfigService) => + inject: [ConfigService], + useFactory: (configService: ConfigService) => configService.getOrThrow('S3_ENDPOINT'), }, { provide: 'S3_REGION', - useValue: (configService: ConfigService) => + inject: [ConfigService], + useFactory: (configService: ConfigService) => configService.getOrThrow('S3_REGION'), }, FileService, diff --git a/server/src/song/song.module.ts b/server/src/song/song.module.ts index a4f14b11..963da5ff 100644 --- a/server/src/song/song.module.ts +++ b/server/src/song/song.module.ts @@ -25,10 +25,10 @@ import { ConfigService } from '@nestjs/config'; SongUploadService, SongWebhookService, { + inject: [ConfigService], provide: 'DISCORD_WEBHOOK_URL', useFactory: (configService: ConfigService) => configService.getOrThrow('DISCORD_WEBHOOK_URL'), - inject: [ConfigService], }, ], controllers: [SongController, MySongsController],