perimeterx-js-core 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/action/utils.js +1 -1
- package/lib/activities/HttpActivityClient.d.ts +5 -5
- package/lib/activities/HttpActivityClient.js +28 -39
- package/lib/activities/HttpBatchedActivityClient.d.ts +2 -2
- package/lib/activities/HttpBatchedActivityClient.js +19 -32
- package/lib/activities/model/AsyncActivity.d.ts +14 -0
- package/lib/activities/model/{ActivityDetails.d.ts → AsyncActivityDetails.d.ts} +6 -23
- package/lib/activities/model/CommonActivityDetails.d.ts +40 -0
- package/lib/activities/model/CommonActivityDetails.js +1 -0
- package/lib/activities/model/HeaderEntry.d.ts +4 -0
- package/lib/activities/model/HeaderEntry.js +1 -0
- package/lib/activities/model/index.d.ts +4 -2
- package/lib/activities/model/index.js +4 -2
- package/lib/activities/utils.d.ts +6071 -9
- package/lib/activities/utils.js +111 -35
- package/lib/additional_activity_handler/AdditionalActivityHandler.d.ts +1 -1
- package/lib/additional_activity_handler/AdditionalActivityHandlerUtils.js +4 -12
- package/lib/config/ConfigurationParams.d.ts +2 -1
- package/lib/config/DefaultConfigurations.js +1 -0
- package/lib/config/IConfiguration.d.ts +5 -1
- package/lib/config/StaticConfigurationBase.d.ts +2 -1
- package/lib/config/StaticConfigurationBase.js +6 -1
- package/lib/context/DefaultContext.d.ts +1 -1
- package/lib/context/DefaultContext.js +40 -8
- package/lib/context/interfaces/RiskApiData.d.ts +4 -0
- package/lib/cors/DefaultCors.js +21 -31
- package/lib/custom_parameters/CustomParametersUtils.js +3 -12
- package/lib/enforcer/EnforcerBase.d.ts +2 -1
- package/lib/enforcer/EnforcerBase.js +56 -57
- package/lib/enforcer/options/EnforcerBaseOptions.d.ts +2 -0
- package/lib/graphql/DefaultGraphQLParser.js +30 -39
- package/lib/http/index.d.ts +0 -1
- package/lib/http/index.js +0 -1
- package/lib/http/interfaces/IBody.d.ts +3 -2
- package/lib/http/interfaces/IIncomingRequest.d.ts +4 -0
- package/lib/http/interfaces/IURL.d.ts +3 -0
- package/lib/http/interfaces/IURLSearchParams.d.ts +9 -0
- package/lib/http/interfaces/IURLSearchParams.js +1 -0
- package/lib/http/interfaces/index.d.ts +1 -0
- package/lib/http/interfaces/index.js +1 -0
- package/lib/http/{impl → utils}/FormDataImpl.js +4 -4
- package/lib/http/{impl → utils}/MinimalResponseImpl.js +3 -0
- package/lib/http/utils/MinimalResponseUtils.js +5 -7
- package/lib/http/utils/MultipartFormDataUtils.js +4 -5
- package/lib/http/{impl → utils}/OutgoingRequestImpl.d.ts +1 -1
- package/lib/http/{impl → utils}/OutgoingRequestImpl.js +5 -1
- package/lib/http/utils/URLUtils.d.ts +7 -0
- package/lib/http/utils/URLUtils.js +62 -0
- package/lib/http/utils/UrlImpl.d.ts +18 -0
- package/lib/http/utils/UrlImpl.js +54 -0
- package/lib/http/utils/UrlSearchParamsImpl.d.ts +19 -0
- package/lib/http/utils/UrlSearchParamsImpl.js +116 -0
- package/lib/http/utils/index.d.ts +6 -0
- package/lib/http/utils/index.js +6 -0
- package/lib/{utils → impl}/base64/AtobBase64Utils.d.ts +1 -1
- package/lib/{utils → impl}/base64/BufferBase64Utils.d.ts +1 -1
- package/lib/{utils → impl}/base64/BufferBase64Utils.js +1 -1
- package/lib/{utils → impl}/base64/JSBase64Base64Utils.d.ts +1 -1
- package/lib/{utils → impl}/cipher/CryptoCipherUtils.d.ts +1 -1
- package/lib/impl/cipher/CryptoCipherUtils.js +18 -0
- package/lib/{utils → impl}/cipher/SubtleCryptoCipherUtils.d.ts +1 -2
- package/lib/impl/cipher/SubtleCryptoCipherUtils.js +38 -0
- package/lib/{utils → impl}/hash/CryptoHashUtils.d.ts +1 -2
- package/lib/impl/hash/CryptoHashUtils.js +10 -0
- package/lib/{utils → impl}/hash/CryptoJSHashUtils.d.ts +1 -2
- package/lib/{utils → impl}/hash/CryptoJSHashUtils.js +1 -1
- package/lib/{utils → impl}/hash/SubtleCryptoHashUtils.d.ts +1 -2
- package/lib/impl/hash/SubtleCryptoHashUtils.js +21 -0
- package/lib/{utils → impl}/hmac/CryptoHmacUtils.d.ts +1 -2
- package/lib/{utils → impl}/hmac/CryptoHmacUtils.js +2 -1
- package/lib/{utils → impl}/hmac/CryptoJSHmacUtils.d.ts +1 -2
- package/lib/{utils → impl}/hmac/CryptoJSHmacUtils.js +1 -1
- package/lib/{http/impl → impl/http}/phin/PhinHttpClient.d.ts +1 -1
- package/lib/impl/http/phin/PhinHttpClient.js +31 -0
- package/lib/{http/impl → impl/http}/phin/PhinIncomingResponse.d.ts +2 -2
- package/lib/impl/http/phin/PhinIncomingResponse.js +23 -0
- package/lib/{utils → impl}/ip_range_checker/DefaultIpRangeChecker.d.ts +1 -1
- package/lib/{utils → impl}/request_id_generator/UuidRequestIdGenerator.d.ts +1 -1
- package/lib/{utils → impl}/url_parser/DefaultUrlParser.d.ts +4 -4
- package/lib/{utils → impl}/url_parser/DefaultUrlParser.js +9 -2
- package/lib/logger/HttpLogServiceClient.d.ts +17 -0
- package/lib/logger/HttpLogServiceClient.js +52 -0
- package/lib/logger/ILogServiceClient.d.ts +6 -0
- package/lib/logger/ILogServiceClient.js +1 -0
- package/lib/logger/ILogger.d.ts +6 -0
- package/lib/logger/LoggerBase.d.ts +6 -2
- package/lib/logger/LoggerBase.js +14 -1
- package/lib/logger/constants.d.ts +2 -0
- package/lib/logger/constants.js +2 -0
- package/lib/logger/index.d.ts +4 -0
- package/lib/logger/index.js +3 -0
- package/lib/logger/model/EnrichedLogRecord.d.ts +3 -0
- package/lib/logger/model/EnrichedLogRecord.js +1 -0
- package/lib/logger/model/LogMetadata.d.ts +9 -0
- package/lib/logger/model/LogMetadata.js +1 -0
- package/lib/logger/model/LogRecord.d.ts +6 -0
- package/lib/logger/model/LogRecord.js +1 -0
- package/lib/logger/model/index.d.ts +3 -0
- package/lib/logger/model/index.js +3 -0
- package/lib/phase/flow/EndEnforcerFlow.d.ts +6 -0
- package/lib/phase/flow/EndEnforcerFlow.js +10 -0
- package/lib/phase/flow/index.d.ts +1 -0
- package/lib/phase/flow/index.js +1 -0
- package/lib/phase/impl/AdditionalActivityHandlerPhase.js +4 -15
- package/lib/phase/impl/CompositePhase.js +9 -19
- package/lib/phase/impl/CreateBlockResponsePhase.js +24 -35
- package/lib/phase/impl/DecideActionPhase.js +11 -21
- package/lib/phase/impl/EnrichContextFromRequestPhase.js +28 -45
- package/lib/phase/impl/EnrichContextFromResponsePhase.js +12 -23
- package/lib/phase/impl/FilterPhase.js +3 -13
- package/lib/phase/impl/FirstPartyPhase.js +21 -32
- package/lib/phase/impl/ModifyIncomingRequestPhase.js +4 -14
- package/lib/phase/impl/ModifyOutgoingResponsePhase.js +7 -18
- package/lib/phase/impl/ParseTokenPhase.js +5 -15
- package/lib/phase/impl/PreflightPhase.js +12 -20
- package/lib/phase/impl/RiskApiPhase.js +24 -36
- package/lib/phase/impl/SendAsyncActivitiesOnRequestPhase.js +8 -20
- package/lib/phase/impl/SendAsyncActivitiesOnResponsePhase.js +4 -14
- package/lib/phase/impl/SendLogsPhase.d.ts +11 -0
- package/lib/phase/impl/SendLogsPhase.js +16 -0
- package/lib/phase/impl/TelemetryPhase.js +9 -21
- package/lib/phase/impl/index.d.ts +1 -0
- package/lib/phase/impl/index.js +1 -0
- package/lib/products/account_defender/AccountDefender.js +16 -35
- package/lib/products/bot_defender/BotDefender.js +51 -72
- package/lib/products/bot_defender/BotDefenderActionData.js +2 -0
- package/lib/products/bot_defender/block/DefaultBotDefenderBlocker.d.ts +4 -4
- package/lib/products/bot_defender/block/DefaultBotDefenderBlocker.js +5 -3
- package/lib/products/bot_defender/block/captcha/CaptchaBlocker.d.ts +7 -4
- package/lib/products/bot_defender/block/captcha/CaptchaBlocker.js +12 -8
- package/lib/products/bot_defender/block/captcha/HtmlCaptchaBlocker.d.ts +1 -1
- package/lib/products/bot_defender/block/captcha/HtmlCaptchaBlocker.js +1 -0
- package/lib/products/bot_defender/block/captcha/JsonCaptchaBlocker.d.ts +1 -1
- package/lib/products/bot_defender/block/captcha/JsonCaptchaBlocker.js +5 -4
- package/lib/products/bot_defender/block/captcha/MobileCaptchaBlocker.d.ts +2 -2
- package/lib/products/bot_defender/block/captcha/MobileCaptchaBlocker.js +2 -0
- package/lib/products/bot_defender/block/utils.js +1 -2
- package/lib/products/bot_defender/filter/DefaultBotDefenderFilter.js +7 -1
- package/lib/products/bot_defender/first_party/DefaultBotDefenderFirstParty.js +51 -68
- package/lib/products/bot_defender/first_party/constants.d.ts +0 -4
- package/lib/products/bot_defender/first_party/constants.js +0 -7
- package/lib/products/credential_intelligence/CredentialIntelligence.js +42 -63
- package/lib/products/credential_intelligence/endpoint/CredentialEndpoint.js +15 -23
- package/lib/products/credential_intelligence/endpoint/CredentialEndpointManager.js +9 -22
- package/lib/products/credential_intelligence/endpoint/extractor/BodyCredentialExtractor.d.ts +5 -5
- package/lib/products/credential_intelligence/endpoint/extractor/BodyCredentialExtractor.js +22 -33
- package/lib/products/credential_intelligence/endpoint/extractor/CustomCredentialExtractor.js +8 -18
- package/lib/products/credential_intelligence/endpoint/extractor/HeaderCredentialExtractor.js +2 -0
- package/lib/products/credential_intelligence/endpoint/extractor/QueryParamCredentialExtractor.d.ts +1 -1
- package/lib/products/credential_intelligence/endpoint/extractor/QueryParamCredentialExtractor.js +11 -16
- package/lib/products/credential_intelligence/endpoint/hash_protocol/MultistepHashProtocol.js +11 -21
- package/lib/products/credential_intelligence/endpoint/hash_protocol/SingleStepAndMultistepHashProtocol.js +9 -18
- package/lib/products/credential_intelligence/endpoint/hash_protocol/SingleStepHashProtocol.js +13 -25
- package/lib/products/credential_intelligence/endpoint/login_successful/BodyLoginSuccessfulParser.js +4 -14
- package/lib/products/credential_intelligence/endpoint/login_successful/CustomLoginSuccessfulParser.js +10 -20
- package/lib/products/credential_intelligence/endpoint/login_successful/HeaderLoginSuccessfulParser.js +7 -16
- package/lib/products/credential_intelligence/endpoint/login_successful/LoginSuccessfulParserFactory.js +7 -6
- package/lib/products/credential_intelligence/endpoint/login_successful/StatusLoginSuccessfulParser.js +3 -13
- package/lib/products/credential_intelligence/endpoint/matcher/ExactPathEndpointMatcher.js +2 -0
- package/lib/products/credential_intelligence/endpoint/matcher/RegexPathEndpointMatcher.js +2 -0
- package/lib/pxde/DefaultDataEnrichment.js +47 -61
- package/lib/pxhd/PXHDUtils.js +2 -2
- package/lib/risk_api/client/PostRiskApiClientBase.d.ts +7 -12
- package/lib/risk_api/client/PostRiskApiClientBase.js +70 -171
- package/lib/risk_api/model/RiskActivity.d.ts +5 -45
- package/lib/risk_api/risk_response/IRiskResponse.d.ts +1 -0
- package/lib/risk_api/risk_response/RiskResponseBase.d.ts +1 -0
- package/lib/risk_api/risk_response/RiskResponseBase.js +20 -33
- package/lib/risk_api/risk_response/v2/DefaultRiskResponseV2.d.ts +1 -1
- package/lib/risk_api/risk_response/v2/DefaultRiskResponseV2.js +3 -5
- package/lib/risk_api/risk_response/v2/RiskResponseV2Payload.d.ts +1 -0
- package/lib/risk_api/risk_response/v3/DefaultRiskResponseV3.js +2 -4
- package/lib/risk_api/risk_response/v3/RiskResponseV3Payload.d.ts +1 -0
- package/lib/risk_token/parser/TokenParserBase.js +25 -36
- package/lib/risk_token/token/TokenBase.js +24 -29
- package/lib/risk_token/token/v2/DefaultTokenV2.js +34 -49
- package/lib/risk_token/token/v3/DefaultTokenV3.js +63 -77
- package/lib/telemetry/DefaultTelemetry.js +46 -58
- package/lib/utils/base64/index.d.ts +0 -3
- package/lib/utils/base64/index.js +0 -3
- package/lib/utils/cipher/index.d.ts +1 -3
- package/lib/utils/cipher/index.js +1 -2
- package/lib/utils/constants.d.ts +2 -1
- package/lib/utils/constants.js +2 -1
- package/lib/utils/hash/index.d.ts +0 -3
- package/lib/utils/hash/index.js +0 -3
- package/lib/utils/hmac/index.d.ts +0 -2
- package/lib/utils/hmac/index.js +0 -2
- package/lib/utils/ip_range_checker/index.d.ts +1 -2
- package/lib/utils/ip_range_checker/index.js +1 -1
- package/lib/utils/request_id_generator/index.d.ts +1 -2
- package/lib/utils/request_id_generator/index.js +1 -1
- package/lib/utils/url_parser/index.d.ts +0 -1
- package/lib/utils/url_parser/index.js +0 -1
- package/lib/utils/utils.d.ts +1 -7
- package/lib/utils/utils.js +3 -25
- package/package.json +12 -6
- package/lib/activities/model/Activity.d.ts +0 -13
- package/lib/http/impl/index.d.ts +0 -4
- package/lib/http/impl/index.js +0 -4
- package/lib/http/impl/phin/PhinHttpClient.js +0 -41
- package/lib/http/impl/phin/PhinIncomingResponse.js +0 -38
- package/lib/utils/cipher/CryptoCipherUtils.js +0 -28
- package/lib/utils/cipher/SubtleCryptoCipherUtils.js +0 -47
- package/lib/utils/hash/CryptoHashUtils.js +0 -20
- package/lib/utils/hash/SubtleCryptoHashUtils.js +0 -31
- /package/lib/activities/model/{Activity.js → AsyncActivity.js} +0 -0
- /package/lib/activities/model/{ActivityDetails.js → AsyncActivityDetails.js} +0 -0
- /package/lib/http/{impl → utils}/FormDataImpl.d.ts +0 -0
- /package/lib/http/{impl → utils}/MinimalResponseImpl.d.ts +0 -0
- /package/lib/{utils → impl}/base64/AtobBase64Utils.js +0 -0
- /package/lib/{utils → impl}/base64/JSBase64Base64Utils.js +0 -0
- /package/lib/{http/impl → impl/http}/phin/index.d.ts +0 -0
- /package/lib/{http/impl → impl/http}/phin/index.js +0 -0
- /package/lib/{utils → impl}/ip_range_checker/DefaultIpRangeChecker.js +0 -0
- /package/lib/{utils → impl}/request_id_generator/UuidRequestIdGenerator.js +0 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// This file is based on the implementation found here:
|
|
2
|
+
// https://github.com/pinglu85/BFEdevSolutions/blob/main/Coding-Problems/80.implement-your-own-URLSearchParams.md
|
|
3
|
+
import { URLUtils } from './URLUtils';
|
|
4
|
+
export class UrlSearchParamsImpl {
|
|
5
|
+
_searchParamsArray;
|
|
6
|
+
_searchParamsMap;
|
|
7
|
+
constructor(init) {
|
|
8
|
+
this._searchParamsArray = [];
|
|
9
|
+
this._searchParamsMap = new Map();
|
|
10
|
+
if (init) {
|
|
11
|
+
if (typeof init !== 'object') {
|
|
12
|
+
this._constructSearchParamsFromString(init);
|
|
13
|
+
}
|
|
14
|
+
else if (Array.isArray(init)) {
|
|
15
|
+
this._constructSearchParamsFromArray(init);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
this._constructSearchParamsFromObject(init);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
append(name, value) {
|
|
23
|
+
name = String(name);
|
|
24
|
+
value = String(value);
|
|
25
|
+
this._saveParam(name, value);
|
|
26
|
+
}
|
|
27
|
+
delete(name) {
|
|
28
|
+
name = String(name);
|
|
29
|
+
this._searchParamsMap.delete(name);
|
|
30
|
+
this._searchParamsArray = this._searchParamsArray.filter((param) => param[0] !== name);
|
|
31
|
+
}
|
|
32
|
+
forEach(callback) {
|
|
33
|
+
this._searchParamsArray.forEach((param) => {
|
|
34
|
+
callback(param[1], param[0], this);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
get(name) {
|
|
38
|
+
name = String(name);
|
|
39
|
+
const value = this._searchParamsMap.get(name);
|
|
40
|
+
return value ? value[0] : null;
|
|
41
|
+
}
|
|
42
|
+
getAll(name) {
|
|
43
|
+
name = String(name);
|
|
44
|
+
const value = this._searchParamsMap.get(name);
|
|
45
|
+
return value ? value : [];
|
|
46
|
+
}
|
|
47
|
+
has(name) {
|
|
48
|
+
name = String(name);
|
|
49
|
+
return this._searchParamsMap.has(name);
|
|
50
|
+
}
|
|
51
|
+
set(name, value) {
|
|
52
|
+
name = String(name);
|
|
53
|
+
value = String(value);
|
|
54
|
+
if (!this.has(name)) {
|
|
55
|
+
this.append(name, value);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
name = URLUtils.decodeUriComponent(name);
|
|
59
|
+
value = URLUtils.decodeUriComponent(value);
|
|
60
|
+
this._searchParamsMap.set(name, [value]);
|
|
61
|
+
const searchParamIdx = this._searchParamsArray.findIndex((param) => param[0] === name);
|
|
62
|
+
this._searchParamsArray[searchParamIdx][1] = value;
|
|
63
|
+
this._searchParamsArray = this._searchParamsArray.filter((param, idx) => param[0] !== name || idx === searchParamIdx);
|
|
64
|
+
}
|
|
65
|
+
toString() {
|
|
66
|
+
return this._searchParamsArray
|
|
67
|
+
.map(([key, value]) => `${URLUtils.encodeUriComponent(key)}=${URLUtils.encodeUriComponent(value)}`)
|
|
68
|
+
.join('&');
|
|
69
|
+
}
|
|
70
|
+
_constructSearchParamsFromString(init) {
|
|
71
|
+
let searchParams = String(init);
|
|
72
|
+
if (searchParams.startsWith('?')) {
|
|
73
|
+
searchParams = searchParams.slice(1);
|
|
74
|
+
}
|
|
75
|
+
searchParams.split('&').forEach((param) => {
|
|
76
|
+
let [key, value] = param.split('=');
|
|
77
|
+
if (!value) {
|
|
78
|
+
value = '';
|
|
79
|
+
}
|
|
80
|
+
this._saveParam(key, value);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
_constructSearchParamsFromArray(init) {
|
|
84
|
+
for (const param of init) {
|
|
85
|
+
if (!Array.isArray(param || param.length !== 2)) {
|
|
86
|
+
throw new Error("Failed to construct 'UrlSearchParamsImpl'");
|
|
87
|
+
}
|
|
88
|
+
const key = String(param[0]);
|
|
89
|
+
const value = String(param[1]);
|
|
90
|
+
this._saveParam(key, value);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
_constructSearchParamsFromObject(init) {
|
|
94
|
+
if (init instanceof Set) {
|
|
95
|
+
throw new Error("Failed to construct 'UrlSearchParamsImpl'");
|
|
96
|
+
}
|
|
97
|
+
for (const key of Object.keys(init)) {
|
|
98
|
+
const value = String(init[key]);
|
|
99
|
+
this._saveParam(key, value);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
_saveParam(key, value) {
|
|
103
|
+
key = URLUtils.decodeUriComponent(key);
|
|
104
|
+
value = URLUtils.decodeUriComponent(value);
|
|
105
|
+
this._searchParamsArray.push([key, value]);
|
|
106
|
+
this._storeParamInSearchParamsMap(key, value);
|
|
107
|
+
}
|
|
108
|
+
_storeParamInSearchParamsMap(key, value) {
|
|
109
|
+
let values = this._searchParamsMap.get(key);
|
|
110
|
+
if (!values) {
|
|
111
|
+
values = [];
|
|
112
|
+
this._searchParamsMap.set(key, values);
|
|
113
|
+
}
|
|
114
|
+
values.push(value);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -3,3 +3,9 @@ export * from './constants';
|
|
|
3
3
|
export * from './HttpMethod';
|
|
4
4
|
export * from './MinimalResponseUtils';
|
|
5
5
|
export * from './MultipartFormDataUtils';
|
|
6
|
+
export * from './FormDataImpl';
|
|
7
|
+
export * from './MinimalResponseImpl';
|
|
8
|
+
export * from './OutgoingRequestImpl';
|
|
9
|
+
export * from './UrlImpl';
|
|
10
|
+
export * from './UrlSearchParamsImpl';
|
|
11
|
+
export * from './URLUtils';
|
package/lib/http/utils/index.js
CHANGED
|
@@ -3,3 +3,9 @@ export * from './constants';
|
|
|
3
3
|
export * from './HttpMethod';
|
|
4
4
|
export * from './MinimalResponseUtils';
|
|
5
5
|
export * from './MultipartFormDataUtils';
|
|
6
|
+
export * from './FormDataImpl';
|
|
7
|
+
export * from './MinimalResponseImpl';
|
|
8
|
+
export * from './OutgoingRequestImpl';
|
|
9
|
+
export * from './UrlImpl';
|
|
10
|
+
export * from './UrlSearchParamsImpl';
|
|
11
|
+
export * from './URLUtils';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export class BufferBase64Utils {
|
|
2
|
+
static BASE_64_ENCODING = 'base64';
|
|
2
3
|
base64Decode(stringToDecode) {
|
|
3
4
|
const buffer = Buffer.from(stringToDecode, BufferBase64Utils.BASE_64_ENCODING);
|
|
4
5
|
return buffer.toString('utf8');
|
|
@@ -8,4 +9,3 @@ export class BufferBase64Utils {
|
|
|
8
9
|
return buffer.toString(BufferBase64Utils.BASE_64_ENCODING);
|
|
9
10
|
}
|
|
10
11
|
}
|
|
11
|
-
BufferBase64Utils.BASE_64_ENCODING = 'base64';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import * as crypto from 'crypto';
|
|
3
|
-
import { ICipherUtils, Pbkdf2DecryptOptions } from '
|
|
3
|
+
import { ICipherUtils, Pbkdf2DecryptOptions } from '../../utils';
|
|
4
4
|
declare type CryptoModule = typeof crypto;
|
|
5
5
|
export declare class CryptoCipherUtils implements ICipherUtils {
|
|
6
6
|
private crypto;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
export class CryptoCipherUtils {
|
|
3
|
+
crypto;
|
|
4
|
+
constructor(cryptoModule = crypto) {
|
|
5
|
+
this.crypto = cryptoModule;
|
|
6
|
+
}
|
|
7
|
+
async pbkdf2Decrypt(secret, encryptedString, iterations, salt, options) {
|
|
8
|
+
const keylen = options?.keylen || 32;
|
|
9
|
+
const ivlen = options?.ivlen || 16;
|
|
10
|
+
const derivation = this.crypto.pbkdf2Sync(secret, Buffer.from(salt, 'base64'), iterations, keylen + ivlen, 'sha256');
|
|
11
|
+
const key = derivation.subarray(0, keylen);
|
|
12
|
+
const iv = derivation.subarray(keylen);
|
|
13
|
+
const cipher = this.crypto.createDecipheriv('aes-256-cbc', key, iv);
|
|
14
|
+
let decrypted = cipher.update(encryptedString, 'base64', 'utf8');
|
|
15
|
+
decrypted += cipher.final('utf8');
|
|
16
|
+
return decrypted;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { IBase64Utils } from '
|
|
2
|
-
import { ICipherUtils, Pbkdf2DecryptOptions } from './ICipherUtils';
|
|
1
|
+
import { ICipherUtils, IBase64Utils, Pbkdf2DecryptOptions } from '../../utils';
|
|
3
2
|
export declare class SubtleCryptoCipherUtils implements ICipherUtils {
|
|
4
3
|
private base64Utils;
|
|
5
4
|
private subtleCrypto;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export class SubtleCryptoCipherUtils {
|
|
2
|
+
base64Utils;
|
|
3
|
+
subtleCrypto;
|
|
4
|
+
constructor(base64Utils, subtleCrypto = crypto.subtle) {
|
|
5
|
+
this.subtleCrypto = subtleCrypto;
|
|
6
|
+
this.base64Utils = base64Utils;
|
|
7
|
+
}
|
|
8
|
+
async pbkdf2Decrypt(secret, encryptedString, iterations, salt, options) {
|
|
9
|
+
const ivlen = options?.ivlen || 16;
|
|
10
|
+
const keylen = options?.keylen || 32;
|
|
11
|
+
const bitsLength = (ivlen + keylen) * 8;
|
|
12
|
+
const encodedPassword = new TextEncoder().encode(secret);
|
|
13
|
+
const encodedSalt = this.base64ToArrayBuffer(salt);
|
|
14
|
+
const importedKey = await this.subtleCrypto.importKey('raw', encodedPassword, 'PBKDF2', false, ['deriveBits']);
|
|
15
|
+
const params = { name: 'PBKDF2', hash: 'SHA-256', salt: encodedSalt, iterations: iterations };
|
|
16
|
+
const derivation = await this.subtleCrypto.deriveBits(params, importedKey, bitsLength);
|
|
17
|
+
const derivedKey = derivation.slice(0, keylen);
|
|
18
|
+
const iv = derivation.slice(keylen);
|
|
19
|
+
const cookieBuffer = this.base64ToArrayBuffer(encryptedString);
|
|
20
|
+
const importedDecryptionKey = await this.subtleCrypto.importKey('raw', derivedKey, { name: 'AES-CBC' }, false, [
|
|
21
|
+
'decrypt',
|
|
22
|
+
]);
|
|
23
|
+
const decrypted = await this.subtleCrypto.decrypt({
|
|
24
|
+
name: 'AES-CBC',
|
|
25
|
+
iv: iv,
|
|
26
|
+
}, importedDecryptionKey, cookieBuffer);
|
|
27
|
+
return new TextDecoder('utf-8').decode(decrypted);
|
|
28
|
+
}
|
|
29
|
+
base64ToArrayBuffer(base64String) {
|
|
30
|
+
const binaryString = this.base64Utils.base64Decode(base64String);
|
|
31
|
+
const length = binaryString.length;
|
|
32
|
+
const bytes = new Uint8Array(length);
|
|
33
|
+
binaryString.split('').forEach((char, index) => {
|
|
34
|
+
bytes[index] = char.charCodeAt(0);
|
|
35
|
+
});
|
|
36
|
+
return bytes.buffer;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import * as crypto from 'crypto';
|
|
3
|
-
import { IHashUtils } from '
|
|
4
|
-
import { Algorithm } from '../Algorithm';
|
|
3
|
+
import { Algorithm, IHashUtils } from '../../utils';
|
|
5
4
|
declare type CryptoModule = typeof crypto;
|
|
6
5
|
export declare class CryptoHashUtils implements IHashUtils {
|
|
7
6
|
private readonly crypto;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Algorithm } from '
|
|
2
|
-
import { IHashUtils } from './IHashUtils';
|
|
1
|
+
import { Algorithm, IHashUtils } from '../../utils';
|
|
3
2
|
export declare class SubtleCryptoHashUtils implements IHashUtils {
|
|
4
3
|
private readonly subtle;
|
|
5
4
|
constructor(subtleCrypto?: SubtleCrypto);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
import { Algorithm } from '../../utils';
|
|
3
|
+
export class SubtleCryptoHashUtils {
|
|
4
|
+
subtle;
|
|
5
|
+
constructor(subtleCrypto = crypto.subtle) {
|
|
6
|
+
this.subtle = subtleCrypto;
|
|
7
|
+
}
|
|
8
|
+
async hashString(text, algo) {
|
|
9
|
+
const textUint8 = new TextEncoder().encode(text);
|
|
10
|
+
const hashBuffer = await this.subtle.digest(this.convertAlgo(algo), textUint8);
|
|
11
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
12
|
+
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
13
|
+
}
|
|
14
|
+
convertAlgo(algo) {
|
|
15
|
+
switch (algo) {
|
|
16
|
+
case Algorithm.SHA256:
|
|
17
|
+
default:
|
|
18
|
+
return 'SHA-256';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import * as crypto from 'crypto';
|
|
3
|
-
import { IHmacUtils } from '
|
|
4
|
-
import { Algorithm } from '../Algorithm';
|
|
3
|
+
import { Algorithm, IHmacUtils } from '../../utils';
|
|
5
4
|
declare type CryptoModule = typeof crypto;
|
|
6
5
|
export declare class CryptoHmacUtils implements IHmacUtils {
|
|
7
6
|
private readonly crypto;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { IHmacUtils } from '
|
|
2
|
-
import { Algorithm } from '../Algorithm';
|
|
1
|
+
import { Algorithm, IHmacUtils } from '../../utils';
|
|
3
2
|
export declare class CryptoJSHmacUtils implements IHmacUtils {
|
|
4
3
|
createHmac(algo: Algorithm, payload: string, secret: string): string;
|
|
5
4
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HttpSendOptions, IHttpClient, IIncomingResponse, IOutgoingRequest } from '
|
|
1
|
+
import { HttpSendOptions, IHttpClient, IIncomingResponse, IOutgoingRequest } from '../../../http/interfaces';
|
|
2
2
|
export declare class PhinHttpClient implements IHttpClient {
|
|
3
3
|
private readonly httpsKeepAliveAgent;
|
|
4
4
|
constructor();
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Agent as HttpAgent } from 'http';
|
|
2
|
+
import { Agent as HttpsAgent } from 'https';
|
|
3
|
+
import phin from 'phin';
|
|
4
|
+
import { EnforcerTimeoutError } from '../../../utils';
|
|
5
|
+
import { joinHeaderValues, } from '../../../http/interfaces';
|
|
6
|
+
import { PhinIncomingResponse } from './PhinIncomingResponse';
|
|
7
|
+
export class PhinHttpClient {
|
|
8
|
+
httpsKeepAliveAgent;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.httpsKeepAliveAgent = new HttpsAgent({ keepAlive: true });
|
|
11
|
+
}
|
|
12
|
+
async send(request, options) {
|
|
13
|
+
try {
|
|
14
|
+
const res = await phin.promisified({
|
|
15
|
+
url: request.url,
|
|
16
|
+
method: request.method,
|
|
17
|
+
headers: joinHeaderValues(request.headers),
|
|
18
|
+
data: request.body,
|
|
19
|
+
timeout: options?.timeoutMs || null,
|
|
20
|
+
core: {
|
|
21
|
+
agent: request.url.startsWith('https://') ? this.httpsKeepAliveAgent : new HttpAgent(),
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
return new PhinIncomingResponse(res);
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
const isTimeout = e.toString().toLowerCase().includes('timeout');
|
|
28
|
+
throw isTimeout ? new EnforcerTimeoutError(options.timeoutMs) : e;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { IResponse } from 'phin';
|
|
3
|
-
import { IFormData, IIncomingResponse, ReadonlyHeaders } from '
|
|
3
|
+
import { IFormData, IIncomingResponse, IURLSearchParams, ReadonlyHeaders } from '../../../http';
|
|
4
4
|
export declare class PhinIncomingResponse implements IIncomingResponse {
|
|
5
5
|
readonly status: number;
|
|
6
6
|
readonly headers: ReadonlyHeaders;
|
|
7
7
|
readonly body: Buffer;
|
|
8
8
|
constructor(response: IResponse);
|
|
9
9
|
formData(): Promise<IFormData>;
|
|
10
|
-
formUrlEncoded(): Promise<
|
|
10
|
+
formUrlEncoded(): Promise<IURLSearchParams>;
|
|
11
11
|
json(): Promise<any>;
|
|
12
12
|
text(): Promise<string>;
|
|
13
13
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CONTENT_TYPE_HEADER_NAME, MultipartFormDataUtils, URLUtils, } from '../../../http';
|
|
2
|
+
export class PhinIncomingResponse {
|
|
3
|
+
status;
|
|
4
|
+
headers;
|
|
5
|
+
body;
|
|
6
|
+
constructor(response) {
|
|
7
|
+
this.status = response.statusCode;
|
|
8
|
+
this.body = response.body;
|
|
9
|
+
this.headers = Object.fromEntries(Object.entries(response.headers).map(([key, val]) => [key, typeof val === 'string' ? [val] : val]));
|
|
10
|
+
}
|
|
11
|
+
async formData() {
|
|
12
|
+
return MultipartFormDataUtils.createFormDataWithoutFiles(await this.text(), this.headers[CONTENT_TYPE_HEADER_NAME]?.[0]);
|
|
13
|
+
}
|
|
14
|
+
async formUrlEncoded() {
|
|
15
|
+
return URLUtils.parseSearchParams(await this.text());
|
|
16
|
+
}
|
|
17
|
+
async json() {
|
|
18
|
+
return JSON.parse(await this.text());
|
|
19
|
+
}
|
|
20
|
+
async text() {
|
|
21
|
+
return this.body.toString();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { IURLParser } from './IURLParser';
|
|
2
1
|
import { IURL } from '../../http';
|
|
2
|
+
import { IURLParser } from '../../utils';
|
|
3
3
|
export type UrlParserOptions = {
|
|
4
4
|
normalize?: boolean;
|
|
5
5
|
reverseCharactersEncoding?: boolean;
|
|
6
6
|
};
|
|
7
7
|
export declare class DefaultUrlParser implements IURLParser {
|
|
8
|
-
|
|
8
|
+
protected options: UrlParserOptions;
|
|
9
9
|
constructor(options?: UrlParserOptions);
|
|
10
10
|
parse(rawUrl: string): IURL;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
protected reverseCharactersEncoding(path: string): string;
|
|
12
|
+
protected normalize(path: string): string;
|
|
13
13
|
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
import { URLUtils } from '../../http';
|
|
1
2
|
export class DefaultUrlParser {
|
|
3
|
+
options;
|
|
2
4
|
constructor(options) {
|
|
3
|
-
this.options =
|
|
5
|
+
this.options = {
|
|
6
|
+
normalize: true,
|
|
7
|
+
reverseCharactersEncoding: false,
|
|
8
|
+
...options,
|
|
9
|
+
};
|
|
4
10
|
}
|
|
5
11
|
parse(rawUrl) {
|
|
6
|
-
const url =
|
|
12
|
+
const url = URLUtils.parseURL(rawUrl);
|
|
7
13
|
if (this.options.reverseCharactersEncoding) {
|
|
8
14
|
url.pathname = this.reverseCharactersEncoding(url.pathname);
|
|
9
15
|
}
|
|
@@ -13,6 +19,7 @@ export class DefaultUrlParser {
|
|
|
13
19
|
return url;
|
|
14
20
|
}
|
|
15
21
|
reverseCharactersEncoding(path) {
|
|
22
|
+
// NOTICE: Find a suitable polyfill in case decodeURI doesn't exist in the global scope
|
|
16
23
|
return decodeURI(path);
|
|
17
24
|
}
|
|
18
25
|
normalize(path) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EnrichedLogRecord, LogRecord } from './model';
|
|
2
|
+
import { ReadonlyContext } from '../context';
|
|
3
|
+
import { IConfiguration } from '../config';
|
|
4
|
+
import { IHttpClient } from '../http';
|
|
5
|
+
import { ILogger } from '../logger';
|
|
6
|
+
import { ILogServiceClient } from './ILogServiceClient';
|
|
7
|
+
export declare class HttpLogServiceClient<Req, Res> implements ILogServiceClient<Req, Res> {
|
|
8
|
+
protected readonly appId: string;
|
|
9
|
+
protected readonly backendUrl: string;
|
|
10
|
+
protected readonly loggerAuthToken: string;
|
|
11
|
+
protected readonly logger: ILogger;
|
|
12
|
+
protected readonly httpClient: IHttpClient;
|
|
13
|
+
constructor(config: IConfiguration<Req, Res>, httpClient: IHttpClient);
|
|
14
|
+
sendLogs(context: ReadonlyContext<Req, Res>, logs: LogRecord[]): Promise<void>;
|
|
15
|
+
protected enrichLogRecord(context: ReadonlyContext<Req, Res>, log: LogRecord): EnrichedLogRecord;
|
|
16
|
+
protected postLogs(logRecords: EnrichedLogRecord[]): Promise<boolean>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { EXTERNAL_LOGGER_SERVICE_PATH } from './constants';
|
|
2
|
+
import { AUTHORIZATION_HEADER_NAME, CONTENT_TYPE_HEADER_NAME, ContentType, HttpMethod, OutgoingRequestImpl, URLUtils, } from '../http';
|
|
3
|
+
import { getAuthorizationHeader } from '../utils';
|
|
4
|
+
export class HttpLogServiceClient {
|
|
5
|
+
appId;
|
|
6
|
+
backendUrl;
|
|
7
|
+
loggerAuthToken;
|
|
8
|
+
logger;
|
|
9
|
+
httpClient;
|
|
10
|
+
constructor(config, httpClient) {
|
|
11
|
+
this.appId = config.appId;
|
|
12
|
+
this.backendUrl = config.backendScoreApiUrl;
|
|
13
|
+
this.loggerAuthToken = config.loggerAuthToken;
|
|
14
|
+
this.logger = config.logger;
|
|
15
|
+
this.httpClient = httpClient;
|
|
16
|
+
}
|
|
17
|
+
async sendLogs(context, logs) {
|
|
18
|
+
try {
|
|
19
|
+
const enrichedLogs = logs.map((log) => this.enrichLogRecord(context, log));
|
|
20
|
+
await this.postLogs(enrichedLogs);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
this.logger.error(`unable to send logs: ${e}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
enrichLogRecord(context, log) {
|
|
27
|
+
const requestData = context.requestData;
|
|
28
|
+
const url = URLUtils.parseURL(requestData.rawUrl);
|
|
29
|
+
const logMeta = {
|
|
30
|
+
container: 'enforcer',
|
|
31
|
+
appID: this.appId,
|
|
32
|
+
method: requestData.method,
|
|
33
|
+
host: url.host,
|
|
34
|
+
url: requestData.rawUrl,
|
|
35
|
+
path: url.pathname + requestData.url.search,
|
|
36
|
+
requestId: context.requestId,
|
|
37
|
+
};
|
|
38
|
+
return { ...logMeta, ...log };
|
|
39
|
+
}
|
|
40
|
+
async postLogs(logRecords) {
|
|
41
|
+
const url = `${this.backendUrl}${EXTERNAL_LOGGER_SERVICE_PATH}`;
|
|
42
|
+
const method = HttpMethod.POST;
|
|
43
|
+
const headers = {
|
|
44
|
+
[CONTENT_TYPE_HEADER_NAME]: [ContentType.APPLICATION_JSON],
|
|
45
|
+
[AUTHORIZATION_HEADER_NAME]: [getAuthorizationHeader(this.loggerAuthToken)],
|
|
46
|
+
};
|
|
47
|
+
const body = JSON.stringify(logRecords);
|
|
48
|
+
const req = new OutgoingRequestImpl({ url, method, headers, body });
|
|
49
|
+
const res = await this.httpClient.send(req);
|
|
50
|
+
return res?.status === 200;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ReadonlyContext } from '../context';
|
|
2
|
+
import { LogRecord } from './model';
|
|
3
|
+
import { AsyncOrSync } from 'ts-essentials';
|
|
4
|
+
export interface ILogServiceClient<Req, Res> {
|
|
5
|
+
sendLogs(context: ReadonlyContext<Req, Res>, logs: LogRecord[]): AsyncOrSync<void>;
|
|
6
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/logger/ILogger.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LoggerSeverity } from './LoggerSeverity';
|
|
2
|
+
import { LogRecord } from './model';
|
|
2
3
|
export interface ILogger {
|
|
3
4
|
/**
|
|
4
5
|
* @returns LoggerSeverity - The current logger severity.
|
|
@@ -21,4 +22,9 @@ export interface ILogger {
|
|
|
21
22
|
* @returns void
|
|
22
23
|
*/
|
|
23
24
|
error(message: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get all the saved logs for that request
|
|
27
|
+
* @returns LogRecord[]
|
|
28
|
+
*/
|
|
29
|
+
getLogs(): LogRecord[];
|
|
24
30
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ILogger } from './ILogger';
|
|
2
2
|
import { LoggerSeverity } from './LoggerSeverity';
|
|
3
|
+
import { LogRecord } from './model';
|
|
3
4
|
export declare abstract class LoggerBase implements ILogger {
|
|
4
|
-
|
|
5
|
-
protected
|
|
5
|
+
protected loggerSeverity: LoggerSeverity;
|
|
6
|
+
protected logs: LogRecord[];
|
|
7
|
+
protected constructor(loggerSeverity?: LoggerSeverity, logs?: LogRecord[]);
|
|
6
8
|
protected abstract log(message: string): void;
|
|
7
9
|
debug(message: string): void;
|
|
8
10
|
error(message: string): void;
|
|
@@ -10,4 +12,6 @@ export declare abstract class LoggerBase implements ILogger {
|
|
|
10
12
|
setLoggerSeverity(loggerSeverity: LoggerSeverity): void;
|
|
11
13
|
protected logError(message: string): void;
|
|
12
14
|
protected logDebug(message: string): void;
|
|
15
|
+
getLogs(): LogRecord[];
|
|
16
|
+
protected recordLog(message: string, loggerSeverity: LoggerSeverity): void;
|
|
13
17
|
}
|
package/lib/logger/LoggerBase.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { LoggerSeverity } from './LoggerSeverity';
|
|
2
2
|
export class LoggerBase {
|
|
3
|
-
|
|
3
|
+
loggerSeverity;
|
|
4
|
+
logs;
|
|
5
|
+
constructor(loggerSeverity = LoggerSeverity.ERROR, logs = []) {
|
|
4
6
|
this.loggerSeverity = loggerSeverity;
|
|
7
|
+
this.logs = logs;
|
|
5
8
|
}
|
|
6
9
|
debug(message) {
|
|
10
|
+
this.recordLog(message, LoggerSeverity.DEBUG);
|
|
7
11
|
if (this.loggerSeverity == LoggerSeverity.DEBUG) {
|
|
8
12
|
this.logDebug(message);
|
|
9
13
|
}
|
|
10
14
|
}
|
|
11
15
|
error(message) {
|
|
16
|
+
this.recordLog(message, LoggerSeverity.ERROR);
|
|
12
17
|
if (this.loggerSeverity != LoggerSeverity.NONE) {
|
|
13
18
|
this.logError(message);
|
|
14
19
|
}
|
|
@@ -27,4 +32,12 @@ export class LoggerBase {
|
|
|
27
32
|
logDebug(message) {
|
|
28
33
|
this.log(message);
|
|
29
34
|
}
|
|
35
|
+
// default implementation, can be overridden
|
|
36
|
+
getLogs() {
|
|
37
|
+
return this.logs;
|
|
38
|
+
}
|
|
39
|
+
recordLog(message, loggerSeverity) {
|
|
40
|
+
const logRecord = { message: message, severity: loggerSeverity, messageTimestamp: Date.now() };
|
|
41
|
+
this.logs.push(logRecord);
|
|
42
|
+
}
|
|
30
43
|
}
|