Make auth module optional to conditionnaly load auth providers (#518)

* Make auth module optional to conditionnaly load auth providers

* Fixes
This commit is contained in:
Charles Bochet
2023-07-05 15:46:09 +02:00
committed by GitHub
parent 463994df1f
commit 9ea765fcfd
6 changed files with 31 additions and 35 deletions

View File

@ -33,8 +33,8 @@ import GraphQLJSON from 'graphql-type-json';
PrismaModule, PrismaModule,
HealthModule, HealthModule,
AbilityModule, AbilityModule,
CoreModule,
IntegrationsModule, IntegrationsModule,
CoreModule,
], ],
providers: [AppService], providers: [AppService],
}) })

View File

@ -3,7 +3,6 @@ import { JwtModule } from '@nestjs/jwt';
import { JwtAuthStrategy } from './strategies/jwt.auth.strategy'; import { JwtAuthStrategy } from './strategies/jwt.auth.strategy';
import { AuthService } from './services/auth.service'; import { AuthService } from './services/auth.service';
import { GoogleAuthController } from './controllers/google-auth.controller'; import { GoogleAuthController } from './controllers/google-auth.controller';
import { GoogleStrategy } from './strategies/google.auth.strategy';
import { PrismaService } from 'src/database/prisma.service'; import { PrismaService } from 'src/database/prisma.service';
import { UserModule } from '../user/user.module'; import { UserModule } from '../user/user.module';
import { VerifyAuthController } from './controllers/verify-auth.controller'; import { VerifyAuthController } from './controllers/verify-auth.controller';
@ -30,7 +29,6 @@ const jwtModule = JwtModule.registerAsync({
AuthService, AuthService,
TokenService, TokenService,
JwtAuthStrategy, JwtAuthStrategy,
GoogleStrategy,
PrismaService, PrismaService,
AuthResolver, AuthResolver,
], ],

View File

@ -1,14 +1,17 @@
import { Injectable, CanActivate, HttpException } from '@nestjs/common'; import { Injectable, CanActivate, NotFoundException } from '@nestjs/common';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { EnvironmentService } from 'src/integrations/environment/environment.service'; import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { GoogleStrategy } from '../strategies/google.auth.strategy';
@Injectable() @Injectable()
export class GoogleProviderEnabledGuard implements CanActivate { export class GoogleProviderEnabledGuard implements CanActivate {
constructor(private readonly environmentService: EnvironmentService) {} constructor(private readonly environmentService: EnvironmentService) {}
canActivate(): boolean | Promise<boolean> | Observable<boolean> { canActivate(): boolean | Promise<boolean> | Observable<boolean> {
if (!this.environmentService.getAuthGoogleEnabled()) { if (!this.environmentService.getAuthGoogleEnabled()) {
throw new HttpException('Google auth is not enabled', 404); throw new NotFoundException('Google auth is not enabled');
} }
new GoogleStrategy(this.environmentService);
return true; return true;
} }
} }

View File

@ -16,17 +16,10 @@ export type GoogleRequest = Request & {
@Injectable() @Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor(environmentService: EnvironmentService) { constructor(environmentService: EnvironmentService) {
const isAuthGoogleEnabled = environmentService.getAuthGoogleEnabled();
super({ super({
clientID: isAuthGoogleEnabled clientID: environmentService.getAuthGoogleClientId(),
? environmentService.getAuthGoogleClientId() clientSecret: environmentService.getAuthGoogleClientSecret(),
: 'disabled', callbackURL: environmentService.getAuthGoogleCallbackUrl(),
clientSecret: isAuthGoogleEnabled
? environmentService.getAuthGoogleClientSecret()
: 'disabled',
callbackURL: isAuthGoogleEnabled
? environmentService.getAuthGoogleCallbackUrl()
: 'disabled',
scope: ['email', 'profile'], scope: ['email', 'profile'],
}); });
} }

View File

@ -0,0 +1,18 @@
import { Transform } from 'class-transformer';
export function CastToBoolean() {
return Transform(({ value }: { value: string }) => toBoolean(value));
}
const toBoolean = (value: any) => {
if (typeof value === 'boolean') {
return value;
}
if (['true', 'on', 'yes', '1'].includes(value.toLowerCase())) {
return true;
}
if (['false', 'off', 'no', '0'].includes(value.toLowerCase())) {
return false;
}
return undefined;
};

View File

@ -13,6 +13,7 @@ import { IsDuration } from './decorators/is-duration.decorator';
import { StorageType } from './interfaces/storage.interface'; import { StorageType } from './interfaces/storage.interface';
import { AwsRegion } from './interfaces/aws-region.interface'; import { AwsRegion } from './interfaces/aws-region.interface';
import { IsAWSRegion } from './decorators/is-aws-region.decorator'; import { IsAWSRegion } from './decorators/is-aws-region.decorator';
import { CastToBoolean } from './decorators/cast-to-boolean.decorator';
export class EnvironmentVariables { export class EnvironmentVariables {
// Database // Database
@ -39,7 +40,7 @@ export class EnvironmentVariables {
@IsUrl({ require_tld: false }) @IsUrl({ require_tld: false })
FRONT_AUTH_CALLBACK_URL: string; FRONT_AUTH_CALLBACK_URL: string;
@Transform(({ value }) => envValueToBoolean(value)) @CastToBoolean()
@IsOptional() @IsOptional()
@IsBoolean() @IsBoolean()
AUTH_GOOGLE_ENABLED?: boolean; AUTH_GOOGLE_ENABLED?: boolean;
@ -75,27 +76,10 @@ export class EnvironmentVariables {
} }
export function validate(config: Record<string, unknown>) { export function validate(config: Record<string, unknown>) {
const validatedConfig = plainToClass(EnvironmentVariables, config, { const validatedConfig = plainToClass(EnvironmentVariables, config);
enableImplicitConversion: false,
});
const errors = validateSync(validatedConfig, { const errors = validateSync(validatedConfig);
skipMissingProperties: false,
});
assert(!errors.length, errors.toString()); assert(!errors.length, errors.toString());
return validatedConfig; return validatedConfig;
} }
const envValueToBoolean = (value: any) => {
if (typeof value === 'boolean') {
return value;
}
if (['true', 'on', 'yes', '1'].includes(value.toLowerCase())) {
return true;
}
if (['false', 'off', 'no', '0'].includes(value.toLowerCase())) {
return false;
}
return undefined;
};