diff --git a/packages/hoppscotch-backend/src/errors.ts b/packages/hoppscotch-backend/src/errors.ts index ddff27b22..b004cfffb 100644 --- a/packages/hoppscotch-backend/src/errors.ts +++ b/packages/hoppscotch-backend/src/errors.ts @@ -676,6 +676,13 @@ export const INFRA_CONFIG_RESET_FAILED = 'infra_config/reset_failed' as const; */ export const INFRA_CONFIG_INVALID_INPUT = 'infra_config/invalid_input' as const; +/** + * Infra Config service (auth provider/mailer/audit logs) not configured + * (InfraConfigService) + */ +export const INFRA_CONFIG_SERVICE_NOT_CONFIGURED = + 'infra_config/service_not_configured' as const; + /** * Error message for when the database table does not exist * (InfraConfigService) diff --git a/packages/hoppscotch-backend/src/infra-config/infra-config.service.ts b/packages/hoppscotch-backend/src/infra-config/infra-config.service.ts index 5f8f34868..ba5d7a130 100644 --- a/packages/hoppscotch-backend/src/infra-config/infra-config.service.ts +++ b/packages/hoppscotch-backend/src/infra-config/infra-config.service.ts @@ -15,11 +15,13 @@ import { INFRA_CONFIG_NOT_LISTED, INFRA_CONFIG_RESET_FAILED, INFRA_CONFIG_UPDATE_FAILED, + INFRA_CONFIG_SERVICE_NOT_CONFIGURED, } from 'src/errors'; import { throwErr, validateEmail, validateSMTPUrl } from 'src/utils'; import { ConfigService } from '@nestjs/config'; import { ServiceStatus, stopApp } from './helper'; import { EnableAndDisableSSOArgs, InfraConfigArgs } from './input-args'; +import { AuthProvider } from 'src/auth/helper'; @Injectable() export class InfraConfigService implements OnModuleInit { @@ -124,7 +126,7 @@ export class InfraConfigService implements OnModuleInit { cast(dbInfraConfig: DBInfraConfig) { return { name: dbInfraConfig.name, - value: dbInfraConfig.value, + value: dbInfraConfig.value ?? '', }; } @@ -182,6 +184,51 @@ export class InfraConfigService implements OnModuleInit { } } + /** + * Check if the service is configured or not + * @param service Service can be Auth Provider, Mailer, Audit Log etc. + * @returns Either true or false + */ + async isServiceConfigured(service: AuthProvider) { + switch (service) { + case AuthProvider.GOOGLE: + if ( + !this.configService.get('INFRA.GOOGLE_CLIENT_ID') || + !this.configService.get('INFRA.GOOGLE_CLIENT_SECRET') + ) { + return false; + } + break; + case AuthProvider.GITHUB: + if ( + !this.configService.get('INFRA.GITHUB_CLIENT_ID') || + !this.configService.get('INFRA.GITHUB_CLIENT_SECRET') + ) { + return false; + } + break; + case AuthProvider.MICROSOFT: + if ( + !this.configService.get('INFRA.MICROSOFT_CLIENT_ID') || + !this.configService.get('INFRA.MICROSOFT_CLIENT_SECRET') + ) { + return false; + } + break; + case AuthProvider.EMAIL: + if ( + !this.configService.get('INFRA.MAILER_SMTP_URL') || + !this.configService.get('INFRA.MAILER_ADDRESS_FROM') + ) { + return false; + } + break; + default: + break; + } + return true; + } + /** * Enable or Disable SSO for login/signup * @param provider Auth Provider to enable or disable @@ -195,15 +242,21 @@ export class InfraConfigService implements OnModuleInit { let updatedAuthProviders = allowedAuthProviders; - providerInfo.forEach(({ provider, status }) => { + for (let i = 0; i < providerInfo.length; i++) { + const { provider, status } = providerInfo[i]; + if (status === ServiceStatus.ENABLE) { + const isConfigured = await this.isServiceConfigured(provider); + if (!isConfigured) { + throwErr(INFRA_CONFIG_SERVICE_NOT_CONFIGURED); + } updatedAuthProviders.push(provider); } else if (status === ServiceStatus.DISABLE) { updatedAuthProviders = updatedAuthProviders.filter( (p) => p !== provider, ); } - }); + } updatedAuthProviders = [...new Set(updatedAuthProviders)]; @@ -286,6 +339,9 @@ export class InfraConfigService implements OnModuleInit { } } + /** + * Validate the values of the InfraConfigs + */ validateEnvValues( infraConfigs: { name: InfraConfigEnumForClient | InfraConfigEnum; @@ -302,6 +358,24 @@ export class InfraConfigService implements OnModuleInit { const isValidEmail = validateEmail(infraConfigs[i].value); if (!isValidEmail) return E.left(INFRA_CONFIG_INVALID_INPUT); break; + case InfraConfigEnumForClient.GOOGLE_CLIENT_ID: + if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT); + break; + case InfraConfigEnumForClient.GOOGLE_CLIENT_SECRET: + if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT); + break; + case InfraConfigEnumForClient.GITHUB_CLIENT_ID: + if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT); + break; + case InfraConfigEnumForClient.GITHUB_CLIENT_SECRET: + if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT); + break; + case InfraConfigEnumForClient.MICROSOFT_CLIENT_ID: + if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT); + break; + case InfraConfigEnumForClient.MICROSOFT_CLIENT_SECRET: + if (!infraConfigs[i].value) return E.left(INFRA_CONFIG_INVALID_INPUT); + break; default: break; }