Skip to content

Commit

Permalink
refactor: standardize provider configuration in Auth, File, and Song …
Browse files Browse the repository at this point in the history
…modules
  • Loading branch information
tomast1337 committed Dec 31, 2024
1 parent 656b3e6 commit 9e5e0f1
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 111 deletions.
48 changes: 34 additions & 14 deletions server/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -51,44 +51,64 @@ export class AuthModule {
DiscordStrategy,
JwtStrategy,
{
provide: 'FRONTEND_URL',
useValue: (configService: ConfigService) =>
configService.getOrThrow<string>('FRONTEND_URL'),
},
{
inject: [ConfigService],
provide: 'COOKIE_EXPIRES_IN',
useValue: (configService: ConfigService) =>
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('COOKIE_EXPIRES_IN'),
},
{
inject: [ConfigService],
provide: 'SERVER_URL',
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('SERVER_URL'),
},
{
inject: [ConfigService],
provide: 'MAGIC_LINK_SECRET',
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('MAGIC_LINK_SECRET'),
},
{
inject: [ConfigService],
provide: 'FRONTEND_URL',
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('FRONTEND_URL'),
},
{
inject: [ConfigService],
provide: 'JWT_SECRET',
useValue: (configService: ConfigService) =>
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('JWT_SECRET'),
},
{
inject: [ConfigService],
provide: 'JWT_EXPIRES_IN',
useValue: (configService: ConfigService) =>
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('JWT_EXPIRES_IN'),
},
{
inject: [ConfigService],
provide: 'JWT_REFRESH_SECRET',
useValue: (configService: ConfigService) =>
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('JWT_REFRESH_SECRET'),
},
{
inject: [ConfigService],
provide: 'JWT_REFRESH_EXPIRES_IN',
useValue: (configService: ConfigService) =>
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('JWT_REFRESH_EXPIRES_IN'),
},
{
inject: [ConfigService],
provide: 'WHITELISTED_USERS',
useValue: (configService: ConfigService) =>
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('WHITELISTED_USERS'),
},
{
inject: [ConfigService],
provide: 'APP_DOMAIN',
useValue: (configService: ConfigService) =>
configService.getOrThrow<string>('APP_DOMAIN'),
useFactory: (configService: ConfigService) =>
configService.get<string>('APP_DOMAIN'),
},
],
exports: [AuthService],
Expand Down
90 changes: 0 additions & 90 deletions server/src/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Request> = {
user: {
accessToken: 'test-access-token',
profile: {
username: 'testuser',
photos: [{ value: 'http://example.com/photo.jpg' }],
},
} as GithubAccessToken,
};

const res: Partial<Response> = {
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<Request> = {
user: {
Expand Down Expand Up @@ -304,50 +258,6 @@ describe('AuthService', () => {
});

describe('discordLogin', () => {
it('should generate token and redirect if user is whitelisted', async () => {
const req: Partial<Request> = {
user: {
profile: {
id: 'discord-user-id',
username: 'testuser',
email: 'test@example.com',
avatar: 'avatar-hash',
},
} as DiscordUser,
};

const res: Partial<Response> = {
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<Request> = {
user: {
Expand Down
3 changes: 3 additions & 0 deletions server/src/config/EnvironmentVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ export class EnvironmentVariables {

@IsString()
DISCORD_WEBHOOK_URL: string;

@IsString()
COOKIE_EXPIRES_IN: string;
}

export function validate(config: Record<string, unknown>) {
Expand Down
18 changes: 12 additions & 6 deletions server/src/file/file.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,38 @@ export class FileModule {
providers: [
{
provide: 'S3_BUCKET_SONGS',
useValue: (configService: ConfigService) =>
inject: [ConfigService],
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('S3_BUCKET_SONGS'),
},
{
provide: 'S3_BUCKET_THUMBS',
useValue: (configService: ConfigService) =>
inject: [ConfigService],
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('S3_BUCKET_THUMBS'),
},
{
provide: 'S3_KEY',
useValue: (configService: ConfigService) =>
inject: [ConfigService],
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('S3_KEY'),
},
{
provide: 'S3_SECRET',
useValue: (configService: ConfigService) =>
inject: [ConfigService],
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('S3_SECRET'),
},
{
provide: 'S3_ENDPOINT',
useValue: (configService: ConfigService) =>
inject: [ConfigService],
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('S3_ENDPOINT'),
},
{
provide: 'S3_REGION',
useValue: (configService: ConfigService) =>
inject: [ConfigService],
useFactory: (configService: ConfigService) =>
configService.getOrThrow<string>('S3_REGION'),
},
FileService,
Expand Down
2 changes: 1 addition & 1 deletion server/src/song/song.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down

0 comments on commit 9e5e0f1

Please sign in to comment.