diff --git a/apps/api/src/.env.development b/apps/api/src/.env.development index 2bee90979c8..a714a764ded 100644 --- a/apps/api/src/.env.development +++ b/apps/api/src/.env.development @@ -25,7 +25,7 @@ REDIS_CACHE_FAMILY= REDIS_CACHE_KEY_PREFIX= REDIS_CACHE_ENABLE_AUTOPIPELINING=true -IS_REQUEST_RATE_LIMITING_ENABLED=false +IS_API_RATE_LIMITING_ENABLED=false IS_IN_MEMORY_CLUSTER_MODE_ENABLED=false ELASTICACHE_CLUSTER_SERVICE_HOST= ELASTICACHE_CLUSTER_SERVICE_PORT= diff --git a/apps/api/src/.env.production b/apps/api/src/.env.production index d7fe721448c..93b7d61eb5b 100644 --- a/apps/api/src/.env.production +++ b/apps/api/src/.env.production @@ -13,7 +13,7 @@ REDIS_PORT=6379 REDIS_PREFIX= REDIS_DB_INDEX=2 -IS_REQUEST_RATE_LIMITING_ENABLED=false +IS_API_RATE_LIMITING_ENABLED=false IS_IN_MEMORY_CLUSTER_MODE_ENABLED=false ELASTICACHE_CLUSTER_SERVICE_HOST= ELASTICACHE_CLUSTER_SERVICE_PORT= diff --git a/apps/api/src/.env.test b/apps/api/src/.env.test index 4c4e94f8a1f..0f469e0c054 100644 --- a/apps/api/src/.env.test +++ b/apps/api/src/.env.test @@ -23,7 +23,7 @@ REDIS_CACHE_FAMILY= REDIS_CACHE_KEY_PREFIX= REDIS_CACHE_ENABLE_AUTOPIPELINING=false -IS_REQUEST_RATE_LIMITING_ENABLED=false +IS_API_RATE_LIMITING_ENABLED=false IS_IN_MEMORY_CLUSTER_MODE_ENABLED=false ELASTICACHE_CLUSTER_SERVICE_HOST= ELASTICACHE_CLUSTER_SERVICE_PORT= diff --git a/apps/api/src/.example.env b/apps/api/src/.example.env index 688ddb2bf25..486452b6788 100644 --- a/apps/api/src/.example.env +++ b/apps/api/src/.example.env @@ -23,7 +23,7 @@ REDIS_CACHE_FAMILY= REDIS_CACHE_KEY_PREFIX= REDIS_CACHE_ENABLE_AUTOPIPELINING= -IS_REQUEST_RATE_LIMITING_ENABLED=false +IS_API_RATE_LIMITING_ENABLED=false IS_IN_MEMORY_CLUSTER_MODE_ENABLED=false REDIS_CLUSTER_SERVICE_HOST= REDIS_CLUSTER_SERVICE_PORT= diff --git a/libs/shared/src/types/feature-flags/feature-flags.ts b/libs/shared/src/types/feature-flags/feature-flags.ts index 56697725074..dda55480998 100644 --- a/libs/shared/src/types/feature-flags/feature-flags.ts +++ b/libs/shared/src/types/feature-flags/feature-flags.ts @@ -3,4 +3,5 @@ export enum FeatureFlagsKeysEnum { IS_TOPIC_NOTIFICATION_ENABLED = 'IS_TOPIC_NOTIFICATION_ENABLED', IS_MULTI_TENANCY_ENABLED = 'IS_MULTI_TENANCY_ENABLED', IS_USE_MERGED_DIGEST_ID_ENABLED = 'IS_USE_MERGED_DIGEST_ID_ENABLED', + IS_API_RATE_LIMITING_ENABLED = 'IS_API_RATE_LIMITING_ENABLED', } diff --git a/libs/shared/src/types/feature-flags/system-critical-flags.ts b/libs/shared/src/types/feature-flags/system-critical-flags.ts index 946f6d40a75..23a1a0ffb8d 100644 --- a/libs/shared/src/types/feature-flags/system-critical-flags.ts +++ b/libs/shared/src/types/feature-flags/system-critical-flags.ts @@ -1,4 +1,3 @@ export enum SystemCriticalFlagsEnum { IS_IN_MEMORY_CLUSTER_MODE_ENABLED = 'IS_IN_MEMORY_CLUSTER_MODE_ENABLED', - IS_REQUEST_RATE_LIMITING_ENABLED = 'IS_REQUEST_RATE_LIMITING_ENABLED', } diff --git a/packages/application-generic/src/custom-providers/index.ts b/packages/application-generic/src/custom-providers/index.ts index 0a36030d08c..d876d41fef3 100644 --- a/packages/application-generic/src/custom-providers/index.ts +++ b/packages/application-generic/src/custom-providers/index.ts @@ -12,6 +12,7 @@ import { WorkflowQueueService, } from '../services'; import { + GetIsApiRateLimitingEnabled, GetIsTopicNotificationEnabled, GetUseMergedDigestId, } from '../usecases'; @@ -50,6 +51,18 @@ export const getIsTopicNotificationEnabled = { inject: [FeatureFlagsService], }; +export const getIsApiRateLimitingEnabled = { + provide: GetIsApiRateLimitingEnabled, + useFactory: async ( + featureFlagsServiceItem: FeatureFlagsService + ): Promise => { + const useCase = new GetIsApiRateLimitingEnabled(featureFlagsServiceItem); + + return useCase; + }, + inject: [FeatureFlagsService], +}; + export const cacheInMemoryProviderService = { provide: CacheInMemoryProviderService, useFactory: (): CacheInMemoryProviderService => { diff --git a/packages/application-generic/src/usecases/get-feature-flag/get-feature-flag.test.ts b/packages/application-generic/src/usecases/get-feature-flag/get-feature-flag.test.ts index c278401e575..b5ef823b802 100644 --- a/packages/application-generic/src/usecases/get-feature-flag/get-feature-flag.test.ts +++ b/packages/application-generic/src/usecases/get-feature-flag/get-feature-flag.test.ts @@ -1,4 +1,5 @@ import { + GetIsApiRateLimitingEnabled, GetIsTemplateStoreEnabled, GetIsTopicNotificationEnabled, } from './index'; @@ -75,6 +76,34 @@ describe('Get Feature Flag', () => { expect(result).toEqual(false); }); }); + + describe('IS_API_RATE_LIMITING_ENABLED', () => { + it('should return default hardcoded value when no SDK env is set and no feature flag is set', async () => { + process.env.IS_API_RATE_LIMITING_ENABLED = ''; + + const getIsApiRateLimitingEnabled = new GetIsApiRateLimitingEnabled( + new FeatureFlagsService() + ); + + const result = await getIsApiRateLimitingEnabled.execute( + featureFlagCommand + ); + expect(result).toEqual(false); + }); + + it('should return env variable value when no SDK env is set but the feature flag is set', async () => { + process.env.IS_API_RATE_LIMITING_ENABLED = 'true'; + + const getIsApiRateLimitingEnabled = new GetIsApiRateLimitingEnabled( + new FeatureFlagsService() + ); + + const result = await getIsApiRateLimitingEnabled.execute( + featureFlagCommand + ); + expect(result).toEqual(true); + }); + }); }); describe('SDK key environment variable is set', () => { diff --git a/packages/application-generic/src/usecases/get-feature-flag/get-is-api-rate-limiting-enabled.use-case.ts b/packages/application-generic/src/usecases/get-feature-flag/get-is-api-rate-limiting-enabled.use-case.ts new file mode 100644 index 00000000000..be34c7e1379 --- /dev/null +++ b/packages/application-generic/src/usecases/get-feature-flag/get-is-api-rate-limiting-enabled.use-case.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@nestjs/common'; +import { FeatureFlagsKeysEnum } from '@novu/shared'; + +import { FeatureFlagCommand } from './get-feature-flag.command'; +import { GetFeatureFlag } from './get-feature-flag.use-case'; + +@Injectable() +export class GetIsApiRateLimitingEnabled extends GetFeatureFlag { + async execute(featureFlagCommand: FeatureFlagCommand): Promise { + const value = process.env.IS_API_RATE_LIMITING_ENABLED; + const fallbackValue = false; + const defaultValue = this.prepareBooleanStringFeatureFlag( + value, + fallbackValue + ); + const key = FeatureFlagsKeysEnum.IS_API_RATE_LIMITING_ENABLED; + + const command = this.buildCommand(key, defaultValue, featureFlagCommand); + + return await this.featureFlagsService.getWithContext(command); + } +} diff --git a/packages/application-generic/src/usecases/get-feature-flag/get-is-request-rate-limiting-enabled.use-case.ts b/packages/application-generic/src/usecases/get-feature-flag/get-is-request-rate-limiting-enabled.use-case.ts deleted file mode 100644 index 46fbd8a01b5..00000000000 --- a/packages/application-generic/src/usecases/get-feature-flag/get-is-request-rate-limiting-enabled.use-case.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { SystemCriticalFlagsEnum } from '@novu/shared'; - -import { GetSystemCriticalFlag } from './get-system-critical-flag.use-case'; - -@Injectable() -export class GetIsRequestRateLimitingEnabled extends GetSystemCriticalFlag { - execute(): boolean { - const value = process.env.IS_REQUEST_RATE_LIMITING_ENABLED; - const fallbackValue = false; - const defaultValue = this.prepareBooleanStringSystemCriticalFlag( - value, - fallbackValue - ); - const key = SystemCriticalFlagsEnum.IS_REQUEST_RATE_LIMITING_ENABLED; - - this.log(key, defaultValue); - - return defaultValue; - } -} diff --git a/packages/application-generic/src/usecases/get-feature-flag/get-system-critical-flag.test.ts b/packages/application-generic/src/usecases/get-feature-flag/get-system-critical-flag.test.ts index 39bcd15cdcf..0e37f47cfeb 100644 --- a/packages/application-generic/src/usecases/get-feature-flag/get-system-critical-flag.test.ts +++ b/packages/application-generic/src/usecases/get-feature-flag/get-system-critical-flag.test.ts @@ -1,7 +1,4 @@ -import { - GetIsInMemoryClusterModeEnabled, - GetIsRequestRateLimitingEnabled, -} from './index'; +import { GetIsInMemoryClusterModeEnabled } from './index'; describe('Get System Critical Flag', () => { describe('SystemCriticalFlagEnum.IS_IN_MEMORY_CLUSTER_MODE_ENABLED', () => { @@ -53,26 +50,4 @@ describe('Get System Critical Flag', () => { expect(result).toEqual(false); }); }); - - describe('SystemCriticalFlagEnum.IS_REQUEST_RATE_LIMITING_ENABLED', () => { - it('should return default hardcoded value when no environment variable is set', async () => { - process.env.IS_REQUEST_RATE_LIMITING_ENABLED = ''; - - const getIsRequestRateLimitingEnabled = - new GetIsRequestRateLimitingEnabled(); - - const result = getIsRequestRateLimitingEnabled.execute(); - expect(result).toEqual(false); - }); - - it('should return environment variable value when environment variable is set', async () => { - process.env.IS_REQUEST_RATE_LIMITING_ENABLED = 'true'; - - const getIsRequestRateLimitingEnabled = - new GetIsRequestRateLimitingEnabled(); - - const result = getIsRequestRateLimitingEnabled.execute(); - expect(result).toEqual(true); - }); - }); }); diff --git a/packages/application-generic/src/usecases/get-feature-flag/index.ts b/packages/application-generic/src/usecases/get-feature-flag/index.ts index 3b177d2f159..8dc07e0e0aa 100644 --- a/packages/application-generic/src/usecases/get-feature-flag/index.ts +++ b/packages/application-generic/src/usecases/get-feature-flag/index.ts @@ -4,7 +4,7 @@ export { } from './get-feature-flag.command'; export { GetFeatureFlag } from './get-feature-flag.use-case'; export { GetIsInMemoryClusterModeEnabled } from './get-is-in-memory-cluster-mode-enabled.use-case'; -export { GetIsRequestRateLimitingEnabled } from './get-is-request-rate-limiting-enabled.use-case'; +export { GetIsApiRateLimitingEnabled } from './get-is-api-rate-limiting-enabled.use-case'; export { GetIsTemplateStoreEnabled } from './get-is-template-store-enabled.use-case'; export { GetIsTopicNotificationEnabled } from './get-is-topic-notification-enabled.use-case'; export { GetUseMergedDigestId } from './get-use-merged-digest-id.use-case';