@mondaydotcomorg/monday-authorization 1.2.18 → 1.2.19-incr-moshesa-upgrade-to-httpclient-and-use-profile--stubisauthorizedfetch.1f00782
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/dist/attributions-service.d.ts +10 -0
- package/dist/attributions-service.d.ts.map +1 -0
- package/dist/attributions-service.js +28 -0
- package/dist/authorization-attributes-service.d.ts +1 -0
- package/dist/authorization-attributes-service.d.ts.map +1 -0
- package/dist/authorization-internal-service.d.ts +5 -0
- package/dist/authorization-internal-service.d.ts.map +1 -0
- package/dist/authorization-internal-service.js +26 -2
- package/dist/authorization-middleware.d.ts +1 -0
- package/dist/authorization-middleware.d.ts.map +1 -0
- package/dist/authorization-service.d.ts +1 -0
- package/dist/authorization-service.d.ts.map +1 -0
- package/dist/authorization-service.js +78 -46
- package/dist/constants/sns.d.ts +1 -0
- package/dist/constants/sns.d.ts.map +1 -0
- package/dist/esm/attributions-service.d.ts +10 -0
- package/dist/esm/attributions-service.d.ts.map +1 -0
- package/dist/esm/attributions-service.mjs +27 -1
- package/dist/esm/authorization-attributes-service.d.ts +1 -0
- package/dist/esm/authorization-attributes-service.d.ts.map +1 -0
- package/dist/esm/authorization-internal-service.d.ts +5 -0
- package/dist/esm/authorization-internal-service.d.ts.map +1 -0
- package/dist/esm/authorization-internal-service.mjs +26 -3
- package/dist/esm/authorization-middleware.d.ts +1 -0
- package/dist/esm/authorization-middleware.d.ts.map +1 -0
- package/dist/esm/authorization-service.d.ts +1 -0
- package/dist/esm/authorization-service.d.ts.map +1 -0
- package/dist/esm/authorization-service.mjs +80 -48
- package/dist/esm/constants/sns.d.ts +1 -0
- package/dist/esm/constants/sns.d.ts.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/prometheus-service.d.ts +1 -1
- package/dist/esm/prometheus-service.d.ts.map +1 -0
- package/dist/esm/prometheus-service.mjs +1 -18
- package/dist/esm/testKit/index.d.ts +1 -0
- package/dist/esm/testKit/index.d.ts.map +1 -0
- package/dist/esm/types/authorization-attributes-contracts.d.ts +1 -0
- package/dist/esm/types/authorization-attributes-contracts.d.ts.map +1 -0
- package/dist/esm/types/express.d.ts +1 -0
- package/dist/esm/types/express.d.ts.map +1 -0
- package/dist/esm/types/general.d.ts +1 -0
- package/dist/esm/types/general.d.ts.map +1 -0
- package/dist/esm/types/scoped-actions-contracts.d.ts +1 -0
- package/dist/esm/types/scoped-actions-contracts.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/prometheus-service.d.ts +1 -1
- package/dist/prometheus-service.d.ts.map +1 -0
- package/dist/prometheus-service.js +0 -18
- package/dist/testKit/index.d.ts +1 -0
- package/dist/testKit/index.d.ts.map +1 -0
- package/dist/types/authorization-attributes-contracts.d.ts +1 -0
- package/dist/types/authorization-attributes-contracts.d.ts.map +1 -0
- package/dist/types/express.d.ts +1 -0
- package/dist/types/express.d.ts.map +1 -0
- package/dist/types/general.d.ts +1 -0
- package/dist/types/general.d.ts.map +1 -0
- package/dist/types/scoped-actions-contracts.d.ts +1 -0
- package/dist/types/scoped-actions-contracts.d.ts.map +1 -0
- package/package.json +4 -3
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import { Context, ExecutionContext } from '@mondaydotcomorg/trident-backend-api';
|
|
2
|
+
declare enum PlatformProfile {
|
|
3
|
+
API_INTERNAL = "api-internal",
|
|
4
|
+
SLOW = "slow",
|
|
5
|
+
INTERNAL = "internal"
|
|
6
|
+
}
|
|
7
|
+
export declare function getProfile(): PlatformProfile;
|
|
8
|
+
export declare function getExecutionContext(context: Context): ExecutionContext;
|
|
1
9
|
export declare function getAttributionsFromApi(): {
|
|
2
10
|
[key: string]: string;
|
|
3
11
|
};
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=attributions-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attributions-service.d.ts","sourceRoot":"","sources":["../src/attributions-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAStF,aAAK,eAAe;IAClB,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,QAAQ,aAAa;CACtB;AAED,wBAAgB,UAAU,oBAiBzB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAEtE;AAED,wBAAgB,sBAAsB,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAqClE"}
|
|
@@ -7,6 +7,32 @@ const APP_NAME_VARIABLE_KEY = 'APP_NAME';
|
|
|
7
7
|
const APP_NAME_HEADER_NAME = 'x-caller-app-name-from-sdk';
|
|
8
8
|
const FROM_SDK_HEADER_SUFFIX = `-from-sdk`;
|
|
9
9
|
let didSendFailureLogOnce = false;
|
|
10
|
+
var PlatformProfile;
|
|
11
|
+
(function (PlatformProfile) {
|
|
12
|
+
PlatformProfile["API_INTERNAL"] = "api-internal";
|
|
13
|
+
PlatformProfile["SLOW"] = "slow";
|
|
14
|
+
PlatformProfile["INTERNAL"] = "internal";
|
|
15
|
+
})(PlatformProfile || (PlatformProfile = {}));
|
|
16
|
+
function getProfile() {
|
|
17
|
+
const tridentContext = tridentBackendApi.Api.getPart('context');
|
|
18
|
+
if (!tridentContext) {
|
|
19
|
+
return PlatformProfile.INTERNAL;
|
|
20
|
+
}
|
|
21
|
+
const { mondayRequestSource } = getExecutionContext(tridentContext);
|
|
22
|
+
switch (mondayRequestSource) {
|
|
23
|
+
case 'api': {
|
|
24
|
+
return PlatformProfile.API_INTERNAL;
|
|
25
|
+
}
|
|
26
|
+
case 'slow': {
|
|
27
|
+
return PlatformProfile.SLOW;
|
|
28
|
+
}
|
|
29
|
+
default:
|
|
30
|
+
return PlatformProfile.INTERNAL;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function getExecutionContext(context) {
|
|
34
|
+
return context.execution.get();
|
|
35
|
+
}
|
|
10
36
|
function getAttributionsFromApi() {
|
|
11
37
|
const callerAppNameFromSdk = {
|
|
12
38
|
[APP_NAME_HEADER_NAME]: tryJsonParse(getEnvVariable(APP_NAME_VARIABLE_KEY)),
|
|
@@ -53,3 +79,5 @@ function tryJsonParse(value) {
|
|
|
53
79
|
}
|
|
54
80
|
|
|
55
81
|
exports.getAttributionsFromApi = getAttributionsFromApi;
|
|
82
|
+
exports.getExecutionContext = getExecutionContext;
|
|
83
|
+
exports.getProfile = getProfile;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-attributes-service.d.ts","sourceRoot":"","sources":["../src/authorization-attributes-service.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,2BAA2B,EAC5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAU3C,qBAAa,8BAA8B;IACzC,OAAO,CAAC,MAAM,CAAC,OAAO,CAA8B;IACpD;;;;;;;OAOG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,4BAA4B,EAAE,2BAA2B,EAAE,GAC1D,OAAO,CAAC,yBAAyB,CAAC;IAwBrC;;;;;;;OAOG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,yBAAyB,CAAC;IAyBrC;;;;;;;UAOM;WACO,6BAA6B,CACxC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,sBAAsB,EAAE,MAAM,EAC9B,2BAA2B,EAAE,2BAA2B,EAAE,GACzD,OAAO,CAAC,2BAA2B,EAAE,CAAC;mBAYpB,oBAAoB;IA4BzC,OAAO,CAAC,MAAM,CAAC,cAAc;IAe7B,OAAO,CAAC,MAAM,CAAC,wBAAwB;IAIvC;;;;;;;OAOG;WACU,kCAAkC,IAAI,OAAO,CAAC,OAAO,CAAC;CAiBpE"}
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { fetch, MondayFetchOptions } from '@mondaydotcomorg/monday-fetch';
|
|
2
|
+
import { OnRetryCallback, RetryPolicy } from '@mondaydotcomorg/monday-fetch-api';
|
|
2
3
|
import type { Request } from 'express';
|
|
3
4
|
export declare const logger: import("bunyan");
|
|
5
|
+
export declare const onRetryCallback: OnRetryCallback;
|
|
4
6
|
export declare class AuthorizationInternalService {
|
|
5
7
|
static skipAuthorization(requset: Request): void;
|
|
6
8
|
static markAuthorized(request: Request): void;
|
|
7
9
|
static failIfNotCoveredByAuthorization(request: Request): void;
|
|
8
10
|
static throwOnHttpErrorIfNeeded(response: Awaited<ReturnType<typeof fetch>>, placement: string): void;
|
|
11
|
+
static throwOnHttpError(status: number, placement: string): void;
|
|
9
12
|
static generateInternalAuthToken(accountId: number, userId: number): string;
|
|
10
13
|
static setRequestFetchOptions(customMondayFetchOptions: MondayFetchOptions): void;
|
|
11
14
|
static getRequestFetchOptions(): MondayFetchOptions;
|
|
12
15
|
static getRequestTimeout(): 60000 | 2000;
|
|
16
|
+
static getRetriesPolicy(): RetryPolicy;
|
|
13
17
|
}
|
|
18
|
+
//# sourceMappingURL=authorization-internal-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-internal-service.d.ts","sourceRoot":"","sources":["../src/authorization-internal-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,EAAyB,eAAe,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAKvC,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAO/C,eAAO,MAAM,eAAe,EAAE,eAM7B,CAAC;AAYF,qBAAa,4BAA4B;IACvC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIhD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI7C,MAAM,CAAC,+BAA+B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAM9D,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAcrG,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAQzD,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAIlE,MAAM,CAAC,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB;IAO1E,MAAM,CAAC,sBAAsB,IAAI,kBAAkB;IAInD,MAAM,CAAC,iBAAiB;IAKxB,MAAM,CAAC,gBAAgB,IAAI,WAAW;CASvC"}
|
|
@@ -24,11 +24,21 @@ return n;
|
|
|
24
24
|
const MondayLogger__namespace = /*#__PURE__*/_interopNamespace(MondayLogger);
|
|
25
25
|
|
|
26
26
|
const INTERNAL_APP_NAME = 'internal_ms';
|
|
27
|
+
const MAX_RETRIES = 3;
|
|
28
|
+
const RETRY_DELAY_MS = 10;
|
|
29
|
+
const logger = MondayLogger__namespace.getLogger();
|
|
27
30
|
const defaultMondayFetchOptions = {
|
|
28
|
-
retries:
|
|
31
|
+
retries: MAX_RETRIES,
|
|
29
32
|
callback: logOnFetchFail,
|
|
30
33
|
};
|
|
31
|
-
const
|
|
34
|
+
const onRetryCallback = (attempt, error) => {
|
|
35
|
+
if (attempt == MAX_RETRIES) {
|
|
36
|
+
logger.error({ tag: 'authorization-service', attempt, error }, 'Authorization attempt failed');
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
logger.info({ tag: 'authorization-service', attempt, error }, 'Authorization attempt failed, trying again');
|
|
40
|
+
}
|
|
41
|
+
};
|
|
32
42
|
function logOnFetchFail(retriesLeft, error) {
|
|
33
43
|
if (retriesLeft == 0) {
|
|
34
44
|
logger.error({ retriesLeft, error }, 'Authorization attempt failed due to network issues');
|
|
@@ -58,6 +68,10 @@ class AuthorizationInternalService {
|
|
|
58
68
|
logger.error({ tag: 'authorization-service', placement, status }, 'AuthorizationService: authorization request failed');
|
|
59
69
|
throw new Error(`AuthorizationService: [${placement}] authorization request failed with status ${status}`);
|
|
60
70
|
}
|
|
71
|
+
static throwOnHttpError(status, placement) {
|
|
72
|
+
logger.error({ tag: 'authorization-service', placement, status }, 'AuthorizationService: authorization request failed');
|
|
73
|
+
throw new Error(`AuthorizationService: [${placement}] authorization request failed with status ${status}`);
|
|
74
|
+
}
|
|
61
75
|
static generateInternalAuthToken(accountId, userId) {
|
|
62
76
|
return mondayJwt.signAuthorizationHeader({ appName: INTERNAL_APP_NAME, accountId, userId });
|
|
63
77
|
}
|
|
@@ -74,7 +88,17 @@ class AuthorizationInternalService {
|
|
|
74
88
|
const isDevEnv = process.env.NODE_ENV === 'development';
|
|
75
89
|
return isDevEnv ? 60000 : 2000;
|
|
76
90
|
}
|
|
91
|
+
static getRetriesPolicy() {
|
|
92
|
+
const fetchOptions = AuthorizationInternalService.getRequestFetchOptions();
|
|
93
|
+
return {
|
|
94
|
+
useRetries: fetchOptions.retries !== undefined,
|
|
95
|
+
maxRetries: fetchOptions.retries !== undefined ? fetchOptions.retries : 0,
|
|
96
|
+
onRetry: onRetryCallback,
|
|
97
|
+
retryDelayMS: fetchOptions.retryDelay ?? RETRY_DELAY_MS,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
77
100
|
}
|
|
78
101
|
|
|
79
102
|
exports.AuthorizationInternalService = AuthorizationInternalService;
|
|
80
103
|
exports.logger = logger;
|
|
104
|
+
exports.onRetryCallback = onRetryCallback;
|
|
@@ -4,3 +4,4 @@ export declare function getAuthorizationMiddleware(action: Action, resourceGette
|
|
|
4
4
|
export declare function skipAuthorizationMiddleware(request: BaseRequest, response: BaseResponse, next: NextFunction): void;
|
|
5
5
|
export declare function authorizationCheckMiddleware(request: BaseRequest, response: BaseResponse, next: NextFunction): void;
|
|
6
6
|
export declare function defaultContextGetter(request: BaseRequest): Context;
|
|
7
|
+
//# sourceMappingURL=authorization-middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-middleware.d.ts","sourceRoot":"","sources":["../src/authorization-middleware.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC5G,OAAO,KAAK,EAAE,YAAY,EAAW,MAAM,SAAS,CAAC;AAIrD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,cAAc,EAC9B,aAAa,CAAC,EAAE,aAAa,IAG3B,SAAS,WAAW,EACpB,UAAU,YAAY,EACtB,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAAC,CAYjB;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAGlH;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CASnH;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAElE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../src/authorization-service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAuB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAQ1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAOD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IAEvD;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;WAMjB,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBA6DnB,oBAAoB;mBAUpB,oBAAoB;CA6E1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F"}
|
|
@@ -4,7 +4,8 @@ const perf_hooks = require('perf_hooks');
|
|
|
4
4
|
const snakeCase = require('lodash/snakeCase.js');
|
|
5
5
|
const camelCase = require('lodash/camelCase.js');
|
|
6
6
|
const mapKeys = require('lodash/mapKeys.js');
|
|
7
|
-
const
|
|
7
|
+
const tridentBackendApi = require('@mondaydotcomorg/trident-backend-api');
|
|
8
|
+
const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
|
|
8
9
|
const prometheusService = require('./prometheus-service.js');
|
|
9
10
|
const authorizationInternalService = require('./authorization-internal-service.js');
|
|
10
11
|
const attributionsService = require('./attributions-service.js');
|
|
@@ -16,6 +17,8 @@ const camelCase__default = /*#__PURE__*/_interopDefault(camelCase);
|
|
|
16
17
|
const mapKeys__default = /*#__PURE__*/_interopDefault(mapKeys);
|
|
17
18
|
|
|
18
19
|
const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
|
|
20
|
+
const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
|
|
21
|
+
const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
|
|
19
22
|
function setRequestFetchOptions(customMondayFetchOptions) {
|
|
20
23
|
authorizationInternalService.AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
|
|
21
24
|
}
|
|
@@ -75,30 +78,49 @@ class AuthorizationService {
|
|
|
75
78
|
return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
76
79
|
});
|
|
77
80
|
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
81
|
+
const httpClient = tridentBackendApi.Api.getPart('httpClient');
|
|
82
|
+
const profile = attributionsService.getProfile();
|
|
83
|
+
let response = [];
|
|
84
|
+
try {
|
|
85
|
+
response = await httpClient.fetch({
|
|
86
|
+
url: {
|
|
87
|
+
appName: 'platform',
|
|
88
|
+
path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
|
|
89
|
+
profile,
|
|
90
|
+
},
|
|
91
|
+
method: 'POST',
|
|
92
|
+
headers: {
|
|
93
|
+
Authorization: internalAuthToken,
|
|
94
|
+
'Content-Type': 'application/json',
|
|
95
|
+
...attributionHeaders,
|
|
96
|
+
},
|
|
97
|
+
body: JSON.stringify({
|
|
98
|
+
user_id: userId,
|
|
99
|
+
scoped_actions: scopedActionsPayload,
|
|
100
|
+
}),
|
|
101
|
+
}, {
|
|
102
|
+
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
103
|
+
retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
if (err instanceof mondayFetchApi.HttpFetcherError) {
|
|
108
|
+
authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
throw err;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function toCamelCase(obj) {
|
|
115
|
+
return mapKeys__default.default(obj, (_, key) => camelCase__default.default(key));
|
|
116
|
+
}
|
|
117
|
+
const scopedActionsResponseObjects = response.map(responseObject => {
|
|
95
118
|
const { scopedAction, permit } = responseObject;
|
|
96
119
|
const { scope } = scopedAction;
|
|
97
|
-
const transformKeys = obj => camelCaseKeys(obj);
|
|
98
120
|
return {
|
|
99
121
|
...responseObject,
|
|
100
|
-
scopedAction: { ...scopedAction, scope:
|
|
101
|
-
permit:
|
|
122
|
+
scopedAction: { ...scopedAction, scope: toCamelCase(scope) },
|
|
123
|
+
permit: toCamelCase(permit),
|
|
102
124
|
};
|
|
103
125
|
});
|
|
104
126
|
return scopedActionsResponseObjects;
|
|
@@ -111,32 +133,48 @@ class AuthorizationService {
|
|
|
111
133
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
112
134
|
const startTime = perf_hooks.performance.now();
|
|
113
135
|
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
const httpClient = tridentBackendApi.Api.getPart('httpClient');
|
|
137
|
+
const profile = attributionsService.getProfile();
|
|
138
|
+
let response = [];
|
|
139
|
+
try {
|
|
140
|
+
response = await httpClient.fetch({
|
|
141
|
+
url: {
|
|
142
|
+
appName: 'platform',
|
|
143
|
+
path: PLATFORM_AUTHORIZE_PATH,
|
|
144
|
+
profile,
|
|
145
|
+
},
|
|
146
|
+
method: 'POST',
|
|
147
|
+
headers: {
|
|
148
|
+
Authorization: internalAuthToken,
|
|
149
|
+
'Content-Type': 'application/json',
|
|
150
|
+
...attributionHeaders,
|
|
151
|
+
},
|
|
152
|
+
body: JSON.stringify({
|
|
153
|
+
user_id: userId,
|
|
154
|
+
authorize_request_objects: authorizationRequestObjects,
|
|
155
|
+
}),
|
|
156
|
+
}, {
|
|
157
|
+
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
158
|
+
retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
if (err instanceof httpClient.HttpFetcherError) {
|
|
163
|
+
authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'isAuthorizedMultiple');
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
throw err;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
127
169
|
const endTime = perf_hooks.performance.now();
|
|
128
170
|
const time = endTime - startTime;
|
|
129
|
-
const responseStatus = response.status;
|
|
130
|
-
prometheusService.sendAuthorizationChecksPerRequestMetric(responseStatus, authorizationRequestObjects.length);
|
|
131
|
-
authorizationInternalService.AuthorizationInternalService.throwOnHttpErrorIfNeeded(response, 'isAuthorizedMultiple');
|
|
132
|
-
const responseBody = await response.json();
|
|
133
171
|
const unauthorizedObjects = [];
|
|
134
|
-
|
|
172
|
+
response.forEach(function (isAuthorized, index) {
|
|
135
173
|
const authorizationObject = authorizationRequestObjects[index];
|
|
136
174
|
if (!isAuthorized) {
|
|
137
175
|
unauthorizedObjects.push(authorizationObject);
|
|
138
176
|
}
|
|
139
|
-
prometheusService.sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized,
|
|
177
|
+
prometheusService.sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, 200, time);
|
|
140
178
|
});
|
|
141
179
|
if (unauthorizedObjects.length > 0) {
|
|
142
180
|
authorizationInternalService.logger.info({
|
|
@@ -176,12 +214,6 @@ function createAuthorizationParams(resources, action) {
|
|
|
176
214
|
};
|
|
177
215
|
return params;
|
|
178
216
|
}
|
|
179
|
-
function getAuthorizeUrl() {
|
|
180
|
-
return `${process.env.MONDAY_INTERNAL_URL}/internal_ms/authorization/authorize`;
|
|
181
|
-
}
|
|
182
|
-
function getCanActionsInScopesUrl() {
|
|
183
|
-
return `${process.env.MONDAY_INTERNAL_URL}/internal_ms/authorization/can_actions_in_scopes`;
|
|
184
|
-
}
|
|
185
217
|
|
|
186
218
|
exports.AuthorizationService = AuthorizationService;
|
|
187
219
|
exports.setRedisClient = setRedisClient;
|
package/dist/constants/sns.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare const RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME = "AUTHORIZATION_RESOURCE_ATTRIBUTES_SNS_TOPIC";
|
|
2
2
|
export declare const RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND = "resourceAttributeModification";
|
|
3
3
|
export declare const ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE = 100;
|
|
4
|
+
//# sourceMappingURL=sns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sns.d.ts","sourceRoot":"","sources":["../../src/constants/sns.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uCAAuC,gDAAgD,CAAC;AACrG,eAAO,MAAM,qDAAqD,kCAAkC,CAAC;AACrG,eAAO,MAAM,oDAAoD,MAAM,CAAC"}
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import { Context, ExecutionContext } from '@mondaydotcomorg/trident-backend-api';
|
|
2
|
+
declare enum PlatformProfile {
|
|
3
|
+
API_INTERNAL = "api-internal",
|
|
4
|
+
SLOW = "slow",
|
|
5
|
+
INTERNAL = "internal"
|
|
6
|
+
}
|
|
7
|
+
export declare function getProfile(): PlatformProfile;
|
|
8
|
+
export declare function getExecutionContext(context: Context): ExecutionContext;
|
|
1
9
|
export declare function getAttributionsFromApi(): {
|
|
2
10
|
[key: string]: string;
|
|
3
11
|
};
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=attributions-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attributions-service.d.ts","sourceRoot":"","sources":["../../src/attributions-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAStF,aAAK,eAAe;IAClB,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,QAAQ,aAAa;CACtB;AAED,wBAAgB,UAAU,oBAiBzB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAEtE;AAED,wBAAgB,sBAAsB,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAqClE"}
|
|
@@ -5,6 +5,32 @@ const APP_NAME_VARIABLE_KEY = 'APP_NAME';
|
|
|
5
5
|
const APP_NAME_HEADER_NAME = 'x-caller-app-name-from-sdk';
|
|
6
6
|
const FROM_SDK_HEADER_SUFFIX = `-from-sdk`;
|
|
7
7
|
let didSendFailureLogOnce = false;
|
|
8
|
+
var PlatformProfile;
|
|
9
|
+
(function (PlatformProfile) {
|
|
10
|
+
PlatformProfile["API_INTERNAL"] = "api-internal";
|
|
11
|
+
PlatformProfile["SLOW"] = "slow";
|
|
12
|
+
PlatformProfile["INTERNAL"] = "internal";
|
|
13
|
+
})(PlatformProfile || (PlatformProfile = {}));
|
|
14
|
+
function getProfile() {
|
|
15
|
+
const tridentContext = Api.getPart('context');
|
|
16
|
+
if (!tridentContext) {
|
|
17
|
+
return PlatformProfile.INTERNAL;
|
|
18
|
+
}
|
|
19
|
+
const { mondayRequestSource } = getExecutionContext(tridentContext);
|
|
20
|
+
switch (mondayRequestSource) {
|
|
21
|
+
case 'api': {
|
|
22
|
+
return PlatformProfile.API_INTERNAL;
|
|
23
|
+
}
|
|
24
|
+
case 'slow': {
|
|
25
|
+
return PlatformProfile.SLOW;
|
|
26
|
+
}
|
|
27
|
+
default:
|
|
28
|
+
return PlatformProfile.INTERNAL;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function getExecutionContext(context) {
|
|
32
|
+
return context.execution.get();
|
|
33
|
+
}
|
|
8
34
|
function getAttributionsFromApi() {
|
|
9
35
|
const callerAppNameFromSdk = {
|
|
10
36
|
[APP_NAME_HEADER_NAME]: tryJsonParse(getEnvVariable(APP_NAME_VARIABLE_KEY)),
|
|
@@ -50,4 +76,4 @@ function tryJsonParse(value) {
|
|
|
50
76
|
}
|
|
51
77
|
}
|
|
52
78
|
|
|
53
|
-
export { getAttributionsFromApi };
|
|
79
|
+
export { getAttributionsFromApi, getExecutionContext, getProfile };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-attributes-service.d.ts","sourceRoot":"","sources":["../../src/authorization-attributes-service.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,2BAA2B,EAC5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAU3C,qBAAa,8BAA8B;IACzC,OAAO,CAAC,MAAM,CAAC,OAAO,CAA8B;IACpD;;;;;;;OAOG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,4BAA4B,EAAE,2BAA2B,EAAE,GAC1D,OAAO,CAAC,yBAAyB,CAAC;IAwBrC;;;;;;;OAOG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,yBAAyB,CAAC;IAyBrC;;;;;;;UAOM;WACO,6BAA6B,CACxC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,sBAAsB,EAAE,MAAM,EAC9B,2BAA2B,EAAE,2BAA2B,EAAE,GACzD,OAAO,CAAC,2BAA2B,EAAE,CAAC;mBAYpB,oBAAoB;IA4BzC,OAAO,CAAC,MAAM,CAAC,cAAc;IAe7B,OAAO,CAAC,MAAM,CAAC,wBAAwB;IAIvC;;;;;;;OAOG;WACU,kCAAkC,IAAI,OAAO,CAAC,OAAO,CAAC;CAiBpE"}
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { fetch, MondayFetchOptions } from '@mondaydotcomorg/monday-fetch';
|
|
2
|
+
import { OnRetryCallback, RetryPolicy } from '@mondaydotcomorg/monday-fetch-api';
|
|
2
3
|
import type { Request } from 'express';
|
|
3
4
|
export declare const logger: import("bunyan");
|
|
5
|
+
export declare const onRetryCallback: OnRetryCallback;
|
|
4
6
|
export declare class AuthorizationInternalService {
|
|
5
7
|
static skipAuthorization(requset: Request): void;
|
|
6
8
|
static markAuthorized(request: Request): void;
|
|
7
9
|
static failIfNotCoveredByAuthorization(request: Request): void;
|
|
8
10
|
static throwOnHttpErrorIfNeeded(response: Awaited<ReturnType<typeof fetch>>, placement: string): void;
|
|
11
|
+
static throwOnHttpError(status: number, placement: string): void;
|
|
9
12
|
static generateInternalAuthToken(accountId: number, userId: number): string;
|
|
10
13
|
static setRequestFetchOptions(customMondayFetchOptions: MondayFetchOptions): void;
|
|
11
14
|
static getRequestFetchOptions(): MondayFetchOptions;
|
|
12
15
|
static getRequestTimeout(): 60000 | 2000;
|
|
16
|
+
static getRetriesPolicy(): RetryPolicy;
|
|
13
17
|
}
|
|
18
|
+
//# sourceMappingURL=authorization-internal-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-internal-service.d.ts","sourceRoot":"","sources":["../../src/authorization-internal-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,EAAyB,eAAe,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAKvC,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAO/C,eAAO,MAAM,eAAe,EAAE,eAM7B,CAAC;AAYF,qBAAa,4BAA4B;IACvC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIhD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI7C,MAAM,CAAC,+BAA+B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAM9D,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAcrG,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAQzD,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAIlE,MAAM,CAAC,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB;IAO1E,MAAM,CAAC,sBAAsB,IAAI,kBAAkB;IAInD,MAAM,CAAC,iBAAiB;IAKxB,MAAM,CAAC,gBAAgB,IAAI,WAAW;CASvC"}
|
|
@@ -2,11 +2,21 @@ import { signAuthorizationHeader } from '@mondaydotcomorg/monday-jwt';
|
|
|
2
2
|
import * as MondayLogger from '@mondaydotcomorg/monday-logger';
|
|
3
3
|
|
|
4
4
|
const INTERNAL_APP_NAME = 'internal_ms';
|
|
5
|
+
const MAX_RETRIES = 3;
|
|
6
|
+
const RETRY_DELAY_MS = 10;
|
|
7
|
+
const logger = MondayLogger.getLogger();
|
|
5
8
|
const defaultMondayFetchOptions = {
|
|
6
|
-
retries:
|
|
9
|
+
retries: MAX_RETRIES,
|
|
7
10
|
callback: logOnFetchFail,
|
|
8
11
|
};
|
|
9
|
-
const
|
|
12
|
+
const onRetryCallback = (attempt, error) => {
|
|
13
|
+
if (attempt == MAX_RETRIES) {
|
|
14
|
+
logger.error({ tag: 'authorization-service', attempt, error }, 'Authorization attempt failed');
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
logger.info({ tag: 'authorization-service', attempt, error }, 'Authorization attempt failed, trying again');
|
|
18
|
+
}
|
|
19
|
+
};
|
|
10
20
|
function logOnFetchFail(retriesLeft, error) {
|
|
11
21
|
if (retriesLeft == 0) {
|
|
12
22
|
logger.error({ retriesLeft, error }, 'Authorization attempt failed due to network issues');
|
|
@@ -36,6 +46,10 @@ class AuthorizationInternalService {
|
|
|
36
46
|
logger.error({ tag: 'authorization-service', placement, status }, 'AuthorizationService: authorization request failed');
|
|
37
47
|
throw new Error(`AuthorizationService: [${placement}] authorization request failed with status ${status}`);
|
|
38
48
|
}
|
|
49
|
+
static throwOnHttpError(status, placement) {
|
|
50
|
+
logger.error({ tag: 'authorization-service', placement, status }, 'AuthorizationService: authorization request failed');
|
|
51
|
+
throw new Error(`AuthorizationService: [${placement}] authorization request failed with status ${status}`);
|
|
52
|
+
}
|
|
39
53
|
static generateInternalAuthToken(accountId, userId) {
|
|
40
54
|
return signAuthorizationHeader({ appName: INTERNAL_APP_NAME, accountId, userId });
|
|
41
55
|
}
|
|
@@ -52,6 +66,15 @@ class AuthorizationInternalService {
|
|
|
52
66
|
const isDevEnv = process.env.NODE_ENV === 'development';
|
|
53
67
|
return isDevEnv ? 60000 : 2000;
|
|
54
68
|
}
|
|
69
|
+
static getRetriesPolicy() {
|
|
70
|
+
const fetchOptions = AuthorizationInternalService.getRequestFetchOptions();
|
|
71
|
+
return {
|
|
72
|
+
useRetries: fetchOptions.retries !== undefined,
|
|
73
|
+
maxRetries: fetchOptions.retries !== undefined ? fetchOptions.retries : 0,
|
|
74
|
+
onRetry: onRetryCallback,
|
|
75
|
+
retryDelayMS: fetchOptions.retryDelay ?? RETRY_DELAY_MS,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
55
78
|
}
|
|
56
79
|
|
|
57
|
-
export { AuthorizationInternalService, logger };
|
|
80
|
+
export { AuthorizationInternalService, logger, onRetryCallback };
|
|
@@ -4,3 +4,4 @@ export declare function getAuthorizationMiddleware(action: Action, resourceGette
|
|
|
4
4
|
export declare function skipAuthorizationMiddleware(request: BaseRequest, response: BaseResponse, next: NextFunction): void;
|
|
5
5
|
export declare function authorizationCheckMiddleware(request: BaseRequest, response: BaseResponse, next: NextFunction): void;
|
|
6
6
|
export declare function defaultContextGetter(request: BaseRequest): Context;
|
|
7
|
+
//# sourceMappingURL=authorization-middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-middleware.d.ts","sourceRoot":"","sources":["../../src/authorization-middleware.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC5G,OAAO,KAAK,EAAE,YAAY,EAAW,MAAM,SAAS,CAAC;AAIrD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,cAAc,EAC9B,aAAa,CAAC,EAAE,aAAa,IAG3B,SAAS,WAAW,EACpB,UAAU,YAAY,EACtB,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAAC,CAYjB;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAGlH;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CASnH;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAElE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../../src/authorization-service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAuB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAQ1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAOD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IAEvD;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;WAMjB,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBA6DnB,oBAAoB;mBAUpB,oBAAoB;CA6E1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F"}
|
|
@@ -2,12 +2,15 @@ import { performance } from 'perf_hooks';
|
|
|
2
2
|
import snakeCase from 'lodash/snakeCase.js';
|
|
3
3
|
import camelCase from 'lodash/camelCase.js';
|
|
4
4
|
import mapKeys from 'lodash/mapKeys.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { Api } from '@mondaydotcomorg/trident-backend-api';
|
|
6
|
+
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
7
|
+
import { sendAuthorizationCheckResponseTimeMetric } from './prometheus-service.mjs';
|
|
7
8
|
import { AuthorizationInternalService, logger } from './authorization-internal-service.mjs';
|
|
8
|
-
import { getAttributionsFromApi } from './attributions-service.mjs';
|
|
9
|
+
import { getAttributionsFromApi, getProfile } from './attributions-service.mjs';
|
|
9
10
|
|
|
10
11
|
const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
|
|
12
|
+
const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
|
|
13
|
+
const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
|
|
11
14
|
function setRequestFetchOptions(customMondayFetchOptions) {
|
|
12
15
|
AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
|
|
13
16
|
}
|
|
@@ -67,30 +70,49 @@ class AuthorizationService {
|
|
|
67
70
|
return { ...scopedAction, scope: mapKeys(scopedAction.scope, (_, key) => snakeCase(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
68
71
|
});
|
|
69
72
|
const attributionHeaders = getAttributionsFromApi();
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
73
|
+
const httpClient = Api.getPart('httpClient');
|
|
74
|
+
const profile = getProfile();
|
|
75
|
+
let response = [];
|
|
76
|
+
try {
|
|
77
|
+
response = await httpClient.fetch({
|
|
78
|
+
url: {
|
|
79
|
+
appName: 'platform',
|
|
80
|
+
path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
|
|
81
|
+
profile,
|
|
82
|
+
},
|
|
83
|
+
method: 'POST',
|
|
84
|
+
headers: {
|
|
85
|
+
Authorization: internalAuthToken,
|
|
86
|
+
'Content-Type': 'application/json',
|
|
87
|
+
...attributionHeaders,
|
|
88
|
+
},
|
|
89
|
+
body: JSON.stringify({
|
|
90
|
+
user_id: userId,
|
|
91
|
+
scoped_actions: scopedActionsPayload,
|
|
92
|
+
}),
|
|
93
|
+
}, {
|
|
94
|
+
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
95
|
+
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
if (err instanceof HttpFetcherError) {
|
|
100
|
+
AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
throw err;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function toCamelCase(obj) {
|
|
107
|
+
return mapKeys(obj, (_, key) => camelCase(key));
|
|
108
|
+
}
|
|
109
|
+
const scopedActionsResponseObjects = response.map(responseObject => {
|
|
87
110
|
const { scopedAction, permit } = responseObject;
|
|
88
111
|
const { scope } = scopedAction;
|
|
89
|
-
const transformKeys = obj => camelCaseKeys(obj);
|
|
90
112
|
return {
|
|
91
113
|
...responseObject,
|
|
92
|
-
scopedAction: { ...scopedAction, scope:
|
|
93
|
-
permit:
|
|
114
|
+
scopedAction: { ...scopedAction, scope: toCamelCase(scope) },
|
|
115
|
+
permit: toCamelCase(permit),
|
|
94
116
|
};
|
|
95
117
|
});
|
|
96
118
|
return scopedActionsResponseObjects;
|
|
@@ -103,32 +125,48 @@ class AuthorizationService {
|
|
|
103
125
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
104
126
|
const startTime = performance.now();
|
|
105
127
|
const attributionHeaders = getAttributionsFromApi();
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
128
|
+
const httpClient = Api.getPart('httpClient');
|
|
129
|
+
const profile = getProfile();
|
|
130
|
+
let response = [];
|
|
131
|
+
try {
|
|
132
|
+
response = await httpClient.fetch({
|
|
133
|
+
url: {
|
|
134
|
+
appName: 'platform',
|
|
135
|
+
path: PLATFORM_AUTHORIZE_PATH,
|
|
136
|
+
profile,
|
|
137
|
+
},
|
|
138
|
+
method: 'POST',
|
|
139
|
+
headers: {
|
|
140
|
+
Authorization: internalAuthToken,
|
|
141
|
+
'Content-Type': 'application/json',
|
|
142
|
+
...attributionHeaders,
|
|
143
|
+
},
|
|
144
|
+
body: JSON.stringify({
|
|
145
|
+
user_id: userId,
|
|
146
|
+
authorize_request_objects: authorizationRequestObjects,
|
|
147
|
+
}),
|
|
148
|
+
}, {
|
|
149
|
+
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
150
|
+
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
if (err instanceof httpClient.HttpFetcherError) {
|
|
155
|
+
AuthorizationInternalService.throwOnHttpError(err.status, 'isAuthorizedMultiple');
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
throw err;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
119
161
|
const endTime = performance.now();
|
|
120
162
|
const time = endTime - startTime;
|
|
121
|
-
const responseStatus = response.status;
|
|
122
|
-
sendAuthorizationChecksPerRequestMetric(responseStatus, authorizationRequestObjects.length);
|
|
123
|
-
AuthorizationInternalService.throwOnHttpErrorIfNeeded(response, 'isAuthorizedMultiple');
|
|
124
|
-
const responseBody = await response.json();
|
|
125
163
|
const unauthorizedObjects = [];
|
|
126
|
-
|
|
164
|
+
response.forEach(function (isAuthorized, index) {
|
|
127
165
|
const authorizationObject = authorizationRequestObjects[index];
|
|
128
166
|
if (!isAuthorized) {
|
|
129
167
|
unauthorizedObjects.push(authorizationObject);
|
|
130
168
|
}
|
|
131
|
-
sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized,
|
|
169
|
+
sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, 200, time);
|
|
132
170
|
});
|
|
133
171
|
if (unauthorizedObjects.length > 0) {
|
|
134
172
|
logger.info({
|
|
@@ -168,11 +206,5 @@ function createAuthorizationParams(resources, action) {
|
|
|
168
206
|
};
|
|
169
207
|
return params;
|
|
170
208
|
}
|
|
171
|
-
function getAuthorizeUrl() {
|
|
172
|
-
return `${process.env.MONDAY_INTERNAL_URL}/internal_ms/authorization/authorize`;
|
|
173
|
-
}
|
|
174
|
-
function getCanActionsInScopesUrl() {
|
|
175
|
-
return `${process.env.MONDAY_INTERNAL_URL}/internal_ms/authorization/can_actions_in_scopes`;
|
|
176
|
-
}
|
|
177
209
|
|
|
178
210
|
export { AuthorizationService, setRedisClient, setRequestFetchOptions };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare const RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME = "AUTHORIZATION_RESOURCE_ATTRIBUTES_SNS_TOPIC";
|
|
2
2
|
export declare const RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND = "resourceAttributeModification";
|
|
3
3
|
export declare const ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE = 100;
|
|
4
|
+
//# sourceMappingURL=sns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sns.d.ts","sourceRoot":"","sources":["../../../src/constants/sns.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uCAAuC,gDAAgD,CAAC;AACrG,eAAO,MAAM,qDAAqD,kCAAkC,CAAC;AACrG,eAAO,MAAM,oDAAoD,MAAM,CAAC"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -13,3 +13,4 @@ export { AuthorizationAttributesService } from './authorization-attributes-servi
|
|
|
13
13
|
export { AuthorizationObject, Resource, BaseRequest, ResourceGetter, ContextGetter } from './types/general';
|
|
14
14
|
export { Translation, ScopedAction, ScopedActionResponseObject, ScopedActionPermit, } from './types/scoped-actions-contracts';
|
|
15
15
|
export { TestKit };
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,KAAK,OAAO,MAAM,WAAW,CAAC;AAErC,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,sCAAsC,CAAC,EAAE,MAAM,CAAC;CACjD;AAED,wBAAgB,IAAI,CAAC,OAAO,GAAE,WAAgB,QAW7C;AAED,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC5G,OAAO,EACL,WAAW,EACX,YAAY,EACZ,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
|
@@ -6,5 +6,5 @@ export declare const METRICS: {
|
|
|
6
6
|
};
|
|
7
7
|
export declare function setPrometheus(customPrometheus: any): void;
|
|
8
8
|
export declare function getMetricsManager(): any;
|
|
9
|
-
export declare function sendAuthorizationChecksPerRequestMetric(responseStatus: any, amountOfAuthorizationObjects: any): void;
|
|
10
9
|
export declare function sendAuthorizationCheckResponseTimeMetric(resourceType: string, action: Action, isAuthorized: boolean, responseStatus: number, time: number): void;
|
|
10
|
+
//# sourceMappingURL=prometheus-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prometheus-service.d.ts","sourceRoot":"","sources":["../../src/prometheus-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAKzC,eAAO,MAAM,OAAO;;;;CAInB,CAAC;AAQF,wBAAgB,aAAa,CAAC,gBAAgB,KAAA,QAU7C;AAED,wBAAgB,iBAAiB,QAEhC;AAED,wBAAgB,wCAAwC,CACtD,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,OAAO,EACrB,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,QASb"}
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
let prometheus = null;
|
|
2
|
-
let authorizationChecksPerRequestMetric = null;
|
|
3
2
|
let authorizationCheckResponseTimeMetric = null;
|
|
4
3
|
const METRICS = {
|
|
5
4
|
AUTHORIZATION_CHECK: 'authorization_check',
|
|
6
5
|
AUTHORIZATION_CHECKS_PER_REQUEST: 'authorization_checks_per_request',
|
|
7
6
|
AUTHORIZATION_CHECK_RESPONSE_TIME: 'authorization_check_response_time',
|
|
8
7
|
};
|
|
9
|
-
const authorizationChecksPerRequestMetricConfig = {
|
|
10
|
-
name: METRICS.AUTHORIZATION_CHECKS_PER_REQUEST,
|
|
11
|
-
labels: ['responseStatus'],
|
|
12
|
-
description: 'Authorization checks per request summary',
|
|
13
|
-
};
|
|
14
8
|
const authorizationCheckResponseTimeMetricConfig = {
|
|
15
9
|
name: METRICS.AUTHORIZATION_CHECK_RESPONSE_TIME,
|
|
16
10
|
labels: ['resourceType', 'action', 'isAuthorized', 'responseStatus'],
|
|
@@ -19,22 +13,11 @@ const authorizationCheckResponseTimeMetricConfig = {
|
|
|
19
13
|
function setPrometheus(customPrometheus) {
|
|
20
14
|
prometheus = customPrometheus;
|
|
21
15
|
const { METRICS_TYPES } = prometheus;
|
|
22
|
-
authorizationChecksPerRequestMetric = getMetricsManager().addMetric(METRICS_TYPES.SUMMARY, authorizationChecksPerRequestMetricConfig.name, authorizationChecksPerRequestMetricConfig.labels, authorizationChecksPerRequestMetricConfig.description);
|
|
23
16
|
authorizationCheckResponseTimeMetric = getMetricsManager().addMetric(METRICS_TYPES.SUMMARY, authorizationCheckResponseTimeMetricConfig.name, authorizationCheckResponseTimeMetricConfig.labels, authorizationCheckResponseTimeMetricConfig.description);
|
|
24
17
|
}
|
|
25
18
|
function getMetricsManager() {
|
|
26
19
|
return prometheus?.metricsManager;
|
|
27
20
|
}
|
|
28
|
-
function sendAuthorizationChecksPerRequestMetric(responseStatus, amountOfAuthorizationObjects) {
|
|
29
|
-
try {
|
|
30
|
-
if (authorizationChecksPerRequestMetric) {
|
|
31
|
-
authorizationChecksPerRequestMetric.labels(responseStatus).observe(amountOfAuthorizationObjects);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
catch (e) {
|
|
35
|
-
// ignore
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
21
|
function sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, responseStatus, time) {
|
|
39
22
|
try {
|
|
40
23
|
if (authorizationCheckResponseTimeMetric) {
|
|
@@ -46,4 +29,4 @@ function sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthor
|
|
|
46
29
|
}
|
|
47
30
|
}
|
|
48
31
|
|
|
49
|
-
export { METRICS, getMetricsManager, sendAuthorizationCheckResponseTimeMetric,
|
|
32
|
+
export { METRICS, getMetricsManager, sendAuthorizationCheckResponseTimeMetric, setPrometheus };
|
|
@@ -9,3 +9,4 @@ export type TestPermittedAction = {
|
|
|
9
9
|
export declare const addTestPermittedAction: (accountId: number, userId: number, resources: Resource[], action: Action) => void;
|
|
10
10
|
export declare const clearTestPermittedActions: () => void;
|
|
11
11
|
export declare const getTestAuthorizationMiddleware: (action: Action, resourceGetter: ResourceGetter, contextGetter?: ContextGetter) => (request: BaseRequest, response: BaseResponse, next: NextFunction) => Promise<void>;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testKit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG9G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,eAAO,MAAM,sBAAsB,GAAI,WAAW,MAAM,EAAE,QAAQ,MAAM,EAAE,WAAW,QAAQ,EAAE,EAAE,QAAQ,MAAM,SAE9G,CAAC;AAEF,eAAO,MAAM,yBAAyB,YAErC,CAAC;AAyBF,eAAO,MAAM,8BAA8B,GACzC,QAAQ,MAAM,EACd,gBAAgB,cAAc,EAC9B,gBAAgB,aAAa,MAG3B,SAAS,WAAW,EACpB,UAAU,YAAY,EACtB,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAYhB,CAAC"}
|
|
@@ -25,3 +25,4 @@ interface DeleteResourceAttributeOperation extends ResourceAttributeDelete {
|
|
|
25
25
|
}
|
|
26
26
|
export type ResourceAttributesOperation = UpsertResourceAttributeOperation | DeleteResourceAttributeOperation;
|
|
27
27
|
export {};
|
|
28
|
+
//# sourceMappingURL=authorization-attributes-contracts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-attributes-contracts.d.ts","sourceRoot":"","sources":["../../../src/types/authorization-attributes-contracts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,WAAW,2BAA2B;IAC1C,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,2BAA2B,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,8BAA8B;IACxC,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,UAAU,gCAAiC,SAAQ,2BAA2B;IAC5E,aAAa,EAAE,8BAA8B,CAAC,MAAM,CAAC;CACtD;AAED,UAAU,gCAAiC,SAAQ,uBAAuB;IACxE,aAAa,EAAE,8BAA8B,CAAC,MAAM,CAAC;CACtD;AAED,MAAM,MAAM,2BAA2B,GAAG,gCAAgC,GAAG,gCAAgC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../../src/types/express.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,OAAO,CAAC;IACxB,UAAiB,OAAO;QACtB,OAAO,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,2BAA2B,EAAE,OAAO,CAAC;QACrC,0BAA0B,EAAE,OAAO,CAAC;KACrC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"general.d.ts","sourceRoot":"","sources":["../../../src/types/general.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,WAAW,QAAQ;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAC5B,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,mBAAmB;IAClC,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,KAAK,WAAW,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC;AACzC,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAC3C,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAC7C,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAC9C,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;AAC7G,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACtD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,QAAQ,EAAE,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoped-actions-contracts.d.ts","sourceRoot":"","sources":["../../../src/types/scoped-actions-contracts.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,mBAAmB,GAAG,YAAY,CAAC;AAEzG,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED,oBAAY,qBAAqB;IAC/B,SAAS,IAAI;IACb,YAAY,IAAI;IAChB,gBAAgB,IAAI;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,eAAe,EAAE,qBAAqB,CAAC;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,kBAAkB,CAAC;CAC5B"}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,3 +13,4 @@ export { AuthorizationAttributesService } from './authorization-attributes-servi
|
|
|
13
13
|
export { AuthorizationObject, Resource, BaseRequest, ResourceGetter, ContextGetter } from './types/general';
|
|
14
14
|
export { Translation, ScopedAction, ScopedActionResponseObject, ScopedActionPermit, } from './types/scoped-actions-contracts';
|
|
15
15
|
export { TestKit };
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,KAAK,OAAO,MAAM,WAAW,CAAC;AAErC,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,sCAAsC,CAAC,EAAE,MAAM,CAAC;CACjD;AAED,wBAAgB,IAAI,CAAC,OAAO,GAAE,WAAgB,QAW7C;AAED,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC5G,OAAO,EACL,WAAW,EACX,YAAY,EACZ,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
|
@@ -6,5 +6,5 @@ export declare const METRICS: {
|
|
|
6
6
|
};
|
|
7
7
|
export declare function setPrometheus(customPrometheus: any): void;
|
|
8
8
|
export declare function getMetricsManager(): any;
|
|
9
|
-
export declare function sendAuthorizationChecksPerRequestMetric(responseStatus: any, amountOfAuthorizationObjects: any): void;
|
|
10
9
|
export declare function sendAuthorizationCheckResponseTimeMetric(resourceType: string, action: Action, isAuthorized: boolean, responseStatus: number, time: number): void;
|
|
10
|
+
//# sourceMappingURL=prometheus-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prometheus-service.d.ts","sourceRoot":"","sources":["../src/prometheus-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAKzC,eAAO,MAAM,OAAO;;;;CAInB,CAAC;AAQF,wBAAgB,aAAa,CAAC,gBAAgB,KAAA,QAU7C;AAED,wBAAgB,iBAAiB,QAEhC;AAED,wBAAgB,wCAAwC,CACtD,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,OAAO,EACrB,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,QASb"}
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
let prometheus = null;
|
|
4
|
-
let authorizationChecksPerRequestMetric = null;
|
|
5
4
|
let authorizationCheckResponseTimeMetric = null;
|
|
6
5
|
const METRICS = {
|
|
7
6
|
AUTHORIZATION_CHECK: 'authorization_check',
|
|
8
7
|
AUTHORIZATION_CHECKS_PER_REQUEST: 'authorization_checks_per_request',
|
|
9
8
|
AUTHORIZATION_CHECK_RESPONSE_TIME: 'authorization_check_response_time',
|
|
10
9
|
};
|
|
11
|
-
const authorizationChecksPerRequestMetricConfig = {
|
|
12
|
-
name: METRICS.AUTHORIZATION_CHECKS_PER_REQUEST,
|
|
13
|
-
labels: ['responseStatus'],
|
|
14
|
-
description: 'Authorization checks per request summary',
|
|
15
|
-
};
|
|
16
10
|
const authorizationCheckResponseTimeMetricConfig = {
|
|
17
11
|
name: METRICS.AUTHORIZATION_CHECK_RESPONSE_TIME,
|
|
18
12
|
labels: ['resourceType', 'action', 'isAuthorized', 'responseStatus'],
|
|
@@ -21,22 +15,11 @@ const authorizationCheckResponseTimeMetricConfig = {
|
|
|
21
15
|
function setPrometheus(customPrometheus) {
|
|
22
16
|
prometheus = customPrometheus;
|
|
23
17
|
const { METRICS_TYPES } = prometheus;
|
|
24
|
-
authorizationChecksPerRequestMetric = getMetricsManager().addMetric(METRICS_TYPES.SUMMARY, authorizationChecksPerRequestMetricConfig.name, authorizationChecksPerRequestMetricConfig.labels, authorizationChecksPerRequestMetricConfig.description);
|
|
25
18
|
authorizationCheckResponseTimeMetric = getMetricsManager().addMetric(METRICS_TYPES.SUMMARY, authorizationCheckResponseTimeMetricConfig.name, authorizationCheckResponseTimeMetricConfig.labels, authorizationCheckResponseTimeMetricConfig.description);
|
|
26
19
|
}
|
|
27
20
|
function getMetricsManager() {
|
|
28
21
|
return prometheus?.metricsManager;
|
|
29
22
|
}
|
|
30
|
-
function sendAuthorizationChecksPerRequestMetric(responseStatus, amountOfAuthorizationObjects) {
|
|
31
|
-
try {
|
|
32
|
-
if (authorizationChecksPerRequestMetric) {
|
|
33
|
-
authorizationChecksPerRequestMetric.labels(responseStatus).observe(amountOfAuthorizationObjects);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
catch (e) {
|
|
37
|
-
// ignore
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
23
|
function sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, responseStatus, time) {
|
|
41
24
|
try {
|
|
42
25
|
if (authorizationCheckResponseTimeMetric) {
|
|
@@ -51,5 +34,4 @@ function sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthor
|
|
|
51
34
|
exports.METRICS = METRICS;
|
|
52
35
|
exports.getMetricsManager = getMetricsManager;
|
|
53
36
|
exports.sendAuthorizationCheckResponseTimeMetric = sendAuthorizationCheckResponseTimeMetric;
|
|
54
|
-
exports.sendAuthorizationChecksPerRequestMetric = sendAuthorizationChecksPerRequestMetric;
|
|
55
37
|
exports.setPrometheus = setPrometheus;
|
package/dist/testKit/index.d.ts
CHANGED
|
@@ -9,3 +9,4 @@ export type TestPermittedAction = {
|
|
|
9
9
|
export declare const addTestPermittedAction: (accountId: number, userId: number, resources: Resource[], action: Action) => void;
|
|
10
10
|
export declare const clearTestPermittedActions: () => void;
|
|
11
11
|
export declare const getTestAuthorizationMiddleware: (action: Action, resourceGetter: ResourceGetter, contextGetter?: ContextGetter) => (request: BaseRequest, response: BaseResponse, next: NextFunction) => Promise<void>;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testKit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG9G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,eAAO,MAAM,sBAAsB,GAAI,WAAW,MAAM,EAAE,QAAQ,MAAM,EAAE,WAAW,QAAQ,EAAE,EAAE,QAAQ,MAAM,SAE9G,CAAC;AAEF,eAAO,MAAM,yBAAyB,YAErC,CAAC;AAyBF,eAAO,MAAM,8BAA8B,GACzC,QAAQ,MAAM,EACd,gBAAgB,cAAc,EAC9B,gBAAgB,aAAa,MAG3B,SAAS,WAAW,EACpB,UAAU,YAAY,EACtB,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAYhB,CAAC"}
|
|
@@ -25,3 +25,4 @@ interface DeleteResourceAttributeOperation extends ResourceAttributeDelete {
|
|
|
25
25
|
}
|
|
26
26
|
export type ResourceAttributesOperation = UpsertResourceAttributeOperation | DeleteResourceAttributeOperation;
|
|
27
27
|
export {};
|
|
28
|
+
//# sourceMappingURL=authorization-attributes-contracts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-attributes-contracts.d.ts","sourceRoot":"","sources":["../../src/types/authorization-attributes-contracts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,WAAW,2BAA2B;IAC1C,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,2BAA2B,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,oBAAY,8BAA8B;IACxC,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,UAAU,gCAAiC,SAAQ,2BAA2B;IAC5E,aAAa,EAAE,8BAA8B,CAAC,MAAM,CAAC;CACtD;AAED,UAAU,gCAAiC,SAAQ,uBAAuB;IACxE,aAAa,EAAE,8BAA8B,CAAC,MAAM,CAAC;CACtD;AAED,MAAM,MAAM,2BAA2B,GAAG,gCAAgC,GAAG,gCAAgC,CAAC"}
|
package/dist/types/express.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/types/express.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,OAAO,CAAC;IACxB,UAAiB,OAAO;QACtB,OAAO,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,2BAA2B,EAAE,OAAO,CAAC;QACrC,0BAA0B,EAAE,OAAO,CAAC;KACrC;CACF"}
|
package/dist/types/general.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"general.d.ts","sourceRoot":"","sources":["../../src/types/general.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,WAAW,QAAQ;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AACD,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAC5B,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,mBAAmB;IAClC,oBAAoB,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,KAAK,WAAW,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC;AACzC,MAAM,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAC3C,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAC7C,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAC9C,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;AAC7G,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AACtD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,QAAQ,EAAE,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoped-actions-contracts.d.ts","sourceRoot":"","sources":["../../src/types/scoped-actions-contracts.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,mBAAmB,GAAG,YAAY,CAAC;AAEzG,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED,oBAAY,qBAAqB;IAC/B,SAAS,IAAI;IACb,YAAY,IAAI;IAChB,gBAAgB,IAAI;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,eAAe,EAAE,qBAAqB,CAAC;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,kBAAkB,CAAC;CAC5B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mondaydotcomorg/monday-authorization",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.19-incr-moshesa-upgrade-to-httpclient-and-use-profile--stubisauthorizedfetch.1f00782",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@mondaydotcomorg/monday-fetch": "^0.0.7",
|
|
23
|
+
"@mondaydotcomorg/monday-fetch-api": "^1.0.2",
|
|
23
24
|
"@mondaydotcomorg/monday-jwt": "^3.0.14",
|
|
24
25
|
"@mondaydotcomorg/monday-logger": "^4.0.11",
|
|
25
26
|
"@mondaydotcomorg/monday-sns": "^1.0.6",
|
|
@@ -30,14 +31,14 @@
|
|
|
30
31
|
"ts-node": "^10.0.0"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
|
-
"@mondaydotcomorg/trident-library": "^
|
|
34
|
+
"@mondaydotcomorg/trident-library": "^1.1.44",
|
|
34
35
|
"@types/express": "^4.17.20",
|
|
35
36
|
"@types/lodash": "^4.17.10",
|
|
36
37
|
"@types/on-headers": "^1.0.0",
|
|
37
38
|
"@types/supertest": "^2.0.11",
|
|
38
39
|
"express": "^4.17.1",
|
|
39
40
|
"ioredis": "^5.2.4",
|
|
40
|
-
"ioredis-mock": "^8.
|
|
41
|
+
"ioredis-mock": "^8.9.0",
|
|
41
42
|
"sinon": "9.0.3",
|
|
42
43
|
"supertest": "^6.1.3",
|
|
43
44
|
"typescript": "^5.2.2"
|