From d1372bb5f99bdd9e4f08b5fdd18b96e6d6a99a71 Mon Sep 17 00:00:00 2001 From: JT Date: Thu, 15 Dec 2022 17:24:47 +0000 Subject: [PATCH 1/4] fix(filterAPI): add matching_user_id and params to types --- src/payload/models/filter_payload.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/payload/models/filter_payload.ts b/src/payload/models/filter_payload.ts index be31e79..b9ddfd8 100644 --- a/src/payload/models/filter_payload.ts +++ b/src/payload/models/filter_payload.ts @@ -13,4 +13,10 @@ export interface FilterPayload { ip: string; headers: IncomingHttpHeaders | { [key: string]: string | boolean }; }; + matching_user_id?: string; + params?: { + email?: string; + phone?: string; + username?: string; + } } From 9c3a3c4ddc257dbda2a0b2af344edc33431da1e5 Mon Sep 17 00:00:00 2001 From: JT Date: Thu, 15 Dec 2022 17:26:08 +0000 Subject: [PATCH 2/4] fix(riskAPI): make user.email optional --- src/payload/models/risk_payload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/payload/models/risk_payload.ts b/src/payload/models/risk_payload.ts index ac8c295..0f512b1 100644 --- a/src/payload/models/risk_payload.ts +++ b/src/payload/models/risk_payload.ts @@ -6,7 +6,7 @@ export interface RiskPayload { status: string; user: { id: string; - email: string; + email?: string; registered_at?: string; traits?: object; name?: string; From 314f26e9f76c33fa30b7cb5378ed6d276f4e9d21 Mon Sep 17 00:00:00 2001 From: JT Date: Thu, 15 Dec 2022 17:27:04 +0000 Subject: [PATCH 3/4] fix(filterAPI): handleFailover shouldn't expect user.id --- src/api/services/api-filter.service.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/api/services/api-filter.service.ts b/src/api/services/api-filter.service.ts index ef1ed4f..d03bbf5 100644 --- a/src/api/services/api-filter.service.ts +++ b/src/api/services/api-filter.service.ts @@ -7,7 +7,6 @@ import { APIService } from './api.service'; import AbortController from 'abort-controller'; const handleFailover = ( - userId: string, reason: string, configuration: Configuration, err?: Error @@ -18,7 +17,6 @@ const handleFailover = ( if (configuration.failoverStrategy === FailoverStrategy.throw) { throw err; } - return { policy: { action: configuration.failoverStrategy, @@ -52,9 +50,9 @@ export const APIFilterService = { ); } catch (e) { if (isTimeoutError(e)) { - return handleFailover(options.user.id, 'timeout', configuration, e); + return handleFailover('timeout', configuration, e); } else if (e instanceof InternalServerError) { - return handleFailover(options.user.id, 'server error', configuration); + return handleFailover('server error', configuration, e); } else { throw e; } From 98274924b4d873de5c82143586a5347bdd5fea89 Mon Sep 17 00:00:00 2001 From: JT Date: Thu, 15 Dec 2022 18:58:48 +0000 Subject: [PATCH 4/4] test(filterAPI): test failover strategy --- test/api/services/api-filter.service.test.ts | 57 +++++++++++++++++--- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/test/api/services/api-filter.service.test.ts b/test/api/services/api-filter.service.test.ts index 4ac36f8..37c4317 100644 --- a/test/api/services/api-filter.service.test.ts +++ b/test/api/services/api-filter.service.test.ts @@ -1,5 +1,6 @@ import { APIFilterService } from '../../../src/api/api.module'; import { Configuration } from '../../../src/configuraton'; +import { FailoverStrategy } from '../../../src/failover/models'; import type { FilterPayload } from '../../../src/payload/payload.module'; import MockDate from 'mockdate'; import fetchMock from 'fetch-mock'; @@ -16,11 +17,8 @@ describe('APIFilterService', () => { const sampleRequestData: FilterPayload = { event: '$login', request_token: 'token', - status: '$succeeded', - user: { - id: 'userid', - email: 'myemail', - }, + status: '$failed', + matching_user_id: 'userid', context: { ip: '8.8.8.8', headers: {}, @@ -38,7 +36,7 @@ describe('APIFilterService', () => { const config = new Configuration({ apiSecret: 'test', overrideFetch: fetch, - logger: { info: () => {} }, + logger: { info: () => { } }, }); const response = await (( @@ -58,7 +56,7 @@ describe('APIFilterService', () => { const config = new Configuration({ apiSecret: 'test', overrideFetch: fetch, - logger: { info: () => {} }, + logger: { info: () => { } }, }); const response = await APIFilterService.call(sampleRequestData, config); @@ -82,7 +80,7 @@ describe('APIFilterService', () => { const config = new Configuration({ apiSecret: 'test', overrideFetch: fetch, - logger: { info: () => {} }, + logger: { info: () => { } }, }); const response = await (( @@ -97,5 +95,48 @@ describe('APIFilterService', () => { ); expect(response.policy).toHaveProperty('name', 'Block Users from X'); }); + + it('handles timeouts with failover strategy', async () => { + jest.useFakeTimers(); + const fetch = fetchMock.sandbox().mock('*', { + action: 'deny', + device: { + token: 'device_token', + }, + policy: { + id: 'q-rbeMzBTdW2Fd09sbz55A', + revision_id: 'pke4zqO2TnqVr-NHJOAHEg', + name: 'Block Users from X', + }, + }, { + delay: 2000 + }); + + const config = new Configuration({ + apiSecret: 'test', + overrideFetch: fetch, + failoverStrategy: FailoverStrategy.allow, + timeout: 1000, + logger: { info: () => { } }, + }); + + const filterCall = (( + APIFilterService.call(sampleRequestData, config) + )); + jest.runAllTimers(); + + const response = await filterCall + + expect(response).toEqual({ + policy: { + action: 'allow', + }, + action: 'allow', + failover: true, + failover_reason: 'timeout' + }); + + jest.useRealTimers(); + }); }); });