From 6f25cd4b60f08a9df96e99dd08fcbea658eeaa9f Mon Sep 17 00:00:00 2001 From: surbhi-sharma1 Date: Wed, 12 Oct 2022 10:03:11 +0530 Subject: [PATCH] feat(providers): add option to apply ratelimiting over single API GH-46 --- README.md | 16 +++++++++++++--- src/__tests__/acceptance/fixtures/application.ts | 1 + .../unit/ratelimit-datasource.provider.unit.ts | 3 +++ src/providers/ratelimit-action.provider.ts | 12 +++++++++++- src/types.ts | 8 ++++++-- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 597b371..21c2eb5 100644 --- a/README.md +++ b/README.md @@ -27,17 +27,17 @@ For redis datasource, you have to pass the name of a loopback4 datasource ```ts this.bind(RateLimitSecurityBindings.CONFIG).to({ name: 'redis', - type:'RedisStore' + type: 'RedisStore', + enabledByDefault: true, }); ``` - For memcache datasource ```ts this.bind(RateLimitSecurityBindings.CONFIG).to({ client: memoryClient, - type:'MemcachedStore' + type: 'MemcachedStore', }); ``` @@ -72,9 +72,19 @@ this.bind(RateLimitSecurityBindings.CONFIG).to({ type: 'RedisStore', max: 60, keyGenerator: rateLimitKeyGen, + enabledByDefault:true }); ``` +## EnabledbyDefault + +enabledByDefault option in Config Binding will provide a configurable mode. +When its enabled (default value is true),it will provide a way to +ratelimit all API's except a few that are disabled using a decorator. + +When its disabled (enabledByDefault is set to false) ,ratelimiting will be +disabled for all APIs except those that are enabled using the decorator. + - The component exposes a sequence action which can be added to your server sequence class. Adding this will trigger ratelimiter middleware for all the requests passing through. ```ts diff --git a/src/__tests__/acceptance/fixtures/application.ts b/src/__tests__/acceptance/fixtures/application.ts index 92381e1..d54daf7 100644 --- a/src/__tests__/acceptance/fixtures/application.ts +++ b/src/__tests__/acceptance/fixtures/application.ts @@ -30,6 +30,7 @@ export class TestApplication extends BootMixin( name: 'inMemory', max: 5, windowMs: 2000, + enabledByDefault: true, }); } } diff --git a/src/__tests__/unit/ratelimit-datasource.provider.unit.ts b/src/__tests__/unit/ratelimit-datasource.provider.unit.ts index 8a74c00..095e691 100644 --- a/src/__tests__/unit/ratelimit-datasource.provider.unit.ts +++ b/src/__tests__/unit/ratelimit-datasource.provider.unit.ts @@ -11,6 +11,7 @@ describe('Rate Limit datasource Service', () => { const config: RateLimitOptions = { name: 'test_name', type: 'MemcachedStore', + enabledByDefault: true, }; const ratelimitDatasourceProvider = new RatelimitDatasourceProvider( () => { @@ -34,6 +35,7 @@ describe('Rate Limit datasource Service', () => { type: 'MongoStore', uri: 'test_uri', collectionName: 'test_collection_name', + enabledByDefault: true, }; const ratelimitDatasourceProvider = new RatelimitDatasourceProvider( () => { @@ -54,6 +56,7 @@ describe('Rate Limit datasource Service', () => { it('returns undefined if there is no redisDS', async () => { const config: RateLimitOptions = { name: 'test_name', + enabledByDefault: true, }; const ratelimitDatasourceProvider = await new RatelimitDatasourceProvider( () => { diff --git a/src/providers/ratelimit-action.provider.ts b/src/providers/ratelimit-action.provider.ts index a44a8af..ee45cc2 100644 --- a/src/providers/ratelimit-action.provider.ts +++ b/src/providers/ratelimit-action.provider.ts @@ -54,6 +54,16 @@ export class RatelimitActionProvider implements Provider { resolve(); }); }); - await promise; + if (this.config?.enabledByDefault === true) { + await promise; + } else if ( + this.config?.enabledByDefault === false && + metadata && + metadata.enabled + ) { + await promise; + } else { + return Promise.resolve(); + } } } diff --git a/src/types.ts b/src/types.ts index 63abdd7..d72a877 100644 --- a/src/types.ts +++ b/src/types.ts @@ -15,12 +15,16 @@ export interface DataSourceConfig { uri?: string; collectionName?: string; } - +export interface RateLimitConfig { + enabledByDefault: boolean; +} export interface RateLimitAction { (request: Request, response: Response): Promise; } -export type RateLimitOptions = Writable> & DataSourceConfig; +export type RateLimitOptions = Writable> & + DataSourceConfig & + RateLimitConfig; /** * Rate limit metadata interface for the method decorator