@mondaydotcomorg/monday-authorization 1.2.19 → 2.0.0-fix-moshesa-set-basic-object-val-to-unknown--8965160254.59909b8
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 +9 -0
- package/dist/attributions-service.d.ts.map +1 -1
- package/dist/attributions-service.js +28 -0
- package/dist/authorization-internal-service.d.ts +8 -4
- package/dist/authorization-internal-service.d.ts.map +1 -1
- package/dist/authorization-internal-service.js +26 -2
- package/dist/authorization-middleware.d.ts.map +1 -1
- package/dist/authorization-middleware.js +2 -1
- package/dist/authorization-service.d.ts +20 -1
- package/dist/authorization-service.d.ts.map +1 -1
- package/dist/authorization-service.js +163 -5
- package/dist/esm/attributions-service.d.ts +9 -0
- package/dist/esm/attributions-service.d.ts.map +1 -1
- package/dist/esm/attributions-service.mjs +27 -1
- package/dist/esm/authorization-internal-service.d.ts +8 -4
- package/dist/esm/authorization-internal-service.d.ts.map +1 -1
- package/dist/esm/authorization-internal-service.mjs +26 -3
- package/dist/esm/authorization-middleware.d.ts.map +1 -1
- package/dist/esm/authorization-middleware.mjs +3 -2
- package/dist/esm/authorization-service.d.ts +20 -1
- package/dist/esm/authorization-service.d.ts.map +1 -1
- package/dist/esm/authorization-service.mjs +164 -8
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.mjs +4 -2
- package/dist/esm/prometheus-service.d.ts +0 -1
- package/dist/esm/prometheus-service.d.ts.map +1 -1
- package/dist/esm/prometheus-service.mjs +1 -18
- package/dist/esm/testKit/index.d.ts.map +1 -1
- package/dist/esm/types/general.d.ts +2 -2
- package/dist/esm/types/general.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/prometheus-service.d.ts +0 -1
- package/dist/prometheus-service.d.ts.map +1 -1
- package/dist/prometheus-service.js +0 -18
- package/dist/testKit/index.d.ts.map +1 -1
- package/dist/types/general.d.ts +2 -2
- package/dist/types/general.d.ts.map +1 -1
- package/package.json +4 -2
|
@@ -1,4 +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 {};
|
|
4
13
|
//# sourceMappingURL=attributions-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attributions-service.d.ts","sourceRoot":"","sources":["../src/attributions-service.ts"],"names":[],"mappings":"
|
|
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;
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { fetch, MondayFetchOptions } from '@mondaydotcomorg/monday-fetch';
|
|
2
|
-
import
|
|
2
|
+
import { OnRetryCallback, RetryPolicy } from '@mondaydotcomorg/monday-fetch-api';
|
|
3
|
+
import { BaseRequest } from './types/general';
|
|
3
4
|
export declare const logger: import("bunyan");
|
|
5
|
+
export declare const onRetryCallback: OnRetryCallback;
|
|
4
6
|
export declare class AuthorizationInternalService {
|
|
5
|
-
static skipAuthorization(requset:
|
|
6
|
-
static markAuthorized(request:
|
|
7
|
-
static failIfNotCoveredByAuthorization(request:
|
|
7
|
+
static skipAuthorization(requset: BaseRequest): void;
|
|
8
|
+
static markAuthorized(request: BaseRequest): void;
|
|
9
|
+
static failIfNotCoveredByAuthorization(request: BaseRequest): 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
|
}
|
|
14
18
|
//# sourceMappingURL=authorization-internal-service.d.ts.map
|
|
@@ -1 +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,
|
|
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,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAK9C,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAO/C,eAAO,MAAM,eAAe,EAAE,eAM7B,CAAC;AAYF,qBAAa,4BAA4B;IACvC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIpD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIjD,MAAM,CAAC,+BAA+B,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMlE,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;
|
|
@@ -1 +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,
|
|
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,EAAE,MAAM,SAAS,CAAC;AAI5C,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,CAajB;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"}
|
|
@@ -15,7 +15,8 @@ function getAuthorizationMiddleware(action, resourceGetter, contextGetter) {
|
|
|
15
15
|
contextGetter ||= defaultContextGetter;
|
|
16
16
|
const { userId, accountId } = contextGetter(request);
|
|
17
17
|
const resources = resourceGetter(request);
|
|
18
|
-
const {
|
|
18
|
+
const { authorizationObjects } = authorizationService.createAuthorizationParams(resources, action);
|
|
19
|
+
const { isAuthorized } = await authorizationService.AuthorizationService.isAuthorized(accountId, userId, authorizationObjects);
|
|
19
20
|
authorizationInternalService.AuthorizationInternalService.markAuthorized(request);
|
|
20
21
|
if (!isAuthorized) {
|
|
21
22
|
response.status(403).json({ message: 'Access denied' });
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MondayFetchOptions } from '@mondaydotcomorg/monday-fetch';
|
|
2
|
-
import {
|
|
2
|
+
import { IgniteClient } from '@mondaydotcomorg/ignite-sdk';
|
|
3
|
+
import { Action, AuthorizationObject, AuthorizationParams, Resource } from './types/general';
|
|
3
4
|
import { ScopedAction, ScopedActionPermit, ScopedActionResponseObject, ScopeOptions } from './types/scoped-actions-contracts';
|
|
4
5
|
export interface AuthorizeResponse {
|
|
5
6
|
isAuthorized: boolean;
|
|
@@ -10,6 +11,7 @@ export declare function setRequestFetchOptions(customMondayFetchOptions: MondayF
|
|
|
10
11
|
export declare class AuthorizationService {
|
|
11
12
|
static redisClient?: any;
|
|
12
13
|
static grantedFeatureRedisExpirationInSeconds?: number;
|
|
14
|
+
static igniteClient?: IgniteClient;
|
|
13
15
|
/**
|
|
14
16
|
* @deprecated use the second form with authorizationRequestObjects instead,
|
|
15
17
|
* support of this function will be dropped gradually
|
|
@@ -26,9 +28,26 @@ export declare class AuthorizationService {
|
|
|
26
28
|
private static fetchIsUserGrantedWithFeature;
|
|
27
29
|
private static getCachedKeyName;
|
|
28
30
|
static canActionInScope(accountId: number, userId: number, action: string, scope: ScopeOptions): Promise<ScopedActionPermit>;
|
|
31
|
+
/**
|
|
32
|
+
* @deprecated - gradually phasing this out
|
|
33
|
+
* @param accountId
|
|
34
|
+
* @param userId
|
|
35
|
+
* @param scopedActions
|
|
36
|
+
*/
|
|
37
|
+
private static canActionInScopeMultiple_withoutPlatformProfile;
|
|
29
38
|
static canActionInScopeMultiple(accountId: number, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
|
|
30
39
|
private static isAuthorizedSingular;
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated - gradually phasing this out
|
|
42
|
+
* @param accountId
|
|
43
|
+
* @param userId
|
|
44
|
+
* @param authorizationRequestObjects
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
private static isAuthorizedMultiple_withoutPlatformProfile;
|
|
31
48
|
private static isAuthorizedMultiple;
|
|
32
49
|
}
|
|
33
50
|
export declare function setRedisClient(client: any, grantedFeatureRedisExpirationInSeconds?: number): void;
|
|
51
|
+
export declare function setIgniteClient(): Promise<void>;
|
|
52
|
+
export declare function createAuthorizationParams(resources: Resource[], action: Action): AuthorizationParams;
|
|
34
53
|
//# sourceMappingURL=authorization-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../src/authorization-service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../src/authorization-service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAG1E,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,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;AAeD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;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;IAM9B;;;;;OAKG;mBACkB,+CAA+C;WAgDvD,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBA4EnB,oBAAoB;IAUzC;;;;;;OAMG;mBACkB,2CAA2C;mBAiE3C,oBAAoB;CAiG1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAIpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
|
|
@@ -5,6 +5,9 @@ const snakeCase = require('lodash/snakeCase.js');
|
|
|
5
5
|
const camelCase = require('lodash/camelCase.js');
|
|
6
6
|
const mapKeys = require('lodash/mapKeys.js');
|
|
7
7
|
const mondayFetch = require('@mondaydotcomorg/monday-fetch');
|
|
8
|
+
const tridentBackendApi = require('@mondaydotcomorg/trident-backend-api');
|
|
9
|
+
const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
|
|
10
|
+
const igniteSdk = require('@mondaydotcomorg/ignite-sdk');
|
|
8
11
|
const prometheusService = require('./prometheus-service.js');
|
|
9
12
|
const authorizationInternalService = require('./authorization-internal-service.js');
|
|
10
13
|
const attributionsService = require('./attributions-service.js');
|
|
@@ -16,12 +19,15 @@ const camelCase__default = /*#__PURE__*/_interopDefault(camelCase);
|
|
|
16
19
|
const mapKeys__default = /*#__PURE__*/_interopDefault(mapKeys);
|
|
17
20
|
|
|
18
21
|
const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
|
|
22
|
+
const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
|
|
23
|
+
const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
|
|
19
24
|
function setRequestFetchOptions(customMondayFetchOptions) {
|
|
20
25
|
authorizationInternalService.AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
|
|
21
26
|
}
|
|
22
27
|
class AuthorizationService {
|
|
23
28
|
static redisClient;
|
|
24
29
|
static grantedFeatureRedisExpirationInSeconds;
|
|
30
|
+
static igniteClient;
|
|
25
31
|
static async isAuthorized(...args) {
|
|
26
32
|
if (args.length === 3) {
|
|
27
33
|
return this.isAuthorizedMultiple(args[0], args[1], args[2]);
|
|
@@ -69,7 +75,13 @@ class AuthorizationService {
|
|
|
69
75
|
const scopedActionResponseObjects = await this.canActionInScopeMultiple(accountId, userId, scopedActions);
|
|
70
76
|
return scopedActionResponseObjects[0].permit;
|
|
71
77
|
}
|
|
72
|
-
|
|
78
|
+
/**
|
|
79
|
+
* @deprecated - gradually phasing this out
|
|
80
|
+
* @param accountId
|
|
81
|
+
* @param userId
|
|
82
|
+
* @param scopedActions
|
|
83
|
+
*/
|
|
84
|
+
static async canActionInScopeMultiple_withoutPlatformProfile(accountId, userId, scopedActions) {
|
|
73
85
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
74
86
|
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
75
87
|
return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
@@ -103,11 +115,82 @@ class AuthorizationService {
|
|
|
103
115
|
});
|
|
104
116
|
return scopedActionsResponseObjects;
|
|
105
117
|
}
|
|
118
|
+
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
119
|
+
// gradually release the new platform profile features
|
|
120
|
+
if (!this.igniteClient) {
|
|
121
|
+
authorizationInternalService.logger.warn({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, using new platform profile feature');
|
|
122
|
+
}
|
|
123
|
+
else if (!this.igniteClient.isReleased('sdk-platform-profiles', { accountId, userId })) {
|
|
124
|
+
return AuthorizationService.canActionInScopeMultiple_withoutPlatformProfile(accountId, userId, scopedActions);
|
|
125
|
+
}
|
|
126
|
+
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
127
|
+
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
128
|
+
return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
129
|
+
});
|
|
130
|
+
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
131
|
+
const httpClient = tridentBackendApi.Api.getPart('httpClient');
|
|
132
|
+
const profile = attributionsService.getProfile();
|
|
133
|
+
let response;
|
|
134
|
+
try {
|
|
135
|
+
response = await httpClient.fetch({
|
|
136
|
+
url: {
|
|
137
|
+
appName: 'platform',
|
|
138
|
+
path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
|
|
139
|
+
profile,
|
|
140
|
+
},
|
|
141
|
+
method: 'POST',
|
|
142
|
+
headers: {
|
|
143
|
+
Authorization: internalAuthToken,
|
|
144
|
+
'Content-Type': 'application/json',
|
|
145
|
+
...attributionHeaders,
|
|
146
|
+
},
|
|
147
|
+
body: JSON.stringify({
|
|
148
|
+
user_id: userId,
|
|
149
|
+
scoped_actions: scopedActionsPayload,
|
|
150
|
+
}),
|
|
151
|
+
}, {
|
|
152
|
+
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
153
|
+
retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
if (err instanceof mondayFetchApi.HttpFetcherError) {
|
|
158
|
+
authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
throw err;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function toCamelCase(obj) {
|
|
165
|
+
return mapKeys__default.default(obj, (_, key) => camelCase__default.default(key));
|
|
166
|
+
}
|
|
167
|
+
if (!response) {
|
|
168
|
+
authorizationInternalService.logger.error({ tag: 'authorization-service', response }, 'AuthorizationService: missing response');
|
|
169
|
+
throw new Error('AuthorizationService: missing response');
|
|
170
|
+
}
|
|
171
|
+
const scopedActionsResponseObjects = response.result.map(responseObject => {
|
|
172
|
+
const { scopedAction, permit } = responseObject;
|
|
173
|
+
const { scope } = scopedAction;
|
|
174
|
+
return {
|
|
175
|
+
...responseObject,
|
|
176
|
+
scopedAction: { ...scopedAction, scope: toCamelCase(scope) },
|
|
177
|
+
permit: toCamelCase(permit),
|
|
178
|
+
};
|
|
179
|
+
});
|
|
180
|
+
return scopedActionsResponseObjects;
|
|
181
|
+
}
|
|
106
182
|
static async isAuthorizedSingular(accountId, userId, resources, action) {
|
|
107
183
|
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
108
184
|
return this.isAuthorizedMultiple(accountId, userId, authorizationObjects);
|
|
109
185
|
}
|
|
110
|
-
|
|
186
|
+
/**
|
|
187
|
+
* @deprecated - gradually phasing this out
|
|
188
|
+
* @param accountId
|
|
189
|
+
* @param userId
|
|
190
|
+
* @param authorizationRequestObjects
|
|
191
|
+
* @private
|
|
192
|
+
*/
|
|
193
|
+
static async isAuthorizedMultiple_withoutPlatformProfile(accountId, userId, authorizationRequestObjects) {
|
|
111
194
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
112
195
|
const startTime = perf_hooks.performance.now();
|
|
113
196
|
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
@@ -127,7 +210,6 @@ class AuthorizationService {
|
|
|
127
210
|
const endTime = perf_hooks.performance.now();
|
|
128
211
|
const time = endTime - startTime;
|
|
129
212
|
const responseStatus = response.status;
|
|
130
|
-
prometheusService.sendAuthorizationChecksPerRequestMetric(responseStatus, authorizationRequestObjects.length);
|
|
131
213
|
authorizationInternalService.AuthorizationInternalService.throwOnHttpErrorIfNeeded(response, 'isAuthorizedMultiple');
|
|
132
214
|
const responseBody = await response.json();
|
|
133
215
|
const unauthorizedObjects = [];
|
|
@@ -149,6 +231,75 @@ class AuthorizationService {
|
|
|
149
231
|
}
|
|
150
232
|
return { isAuthorized: true };
|
|
151
233
|
}
|
|
234
|
+
static async isAuthorizedMultiple(accountId, userId, authorizationRequestObjects) {
|
|
235
|
+
// gradually release the new platform profile features
|
|
236
|
+
if (!this.igniteClient) {
|
|
237
|
+
authorizationInternalService.logger.warn({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, using new platform profile feature');
|
|
238
|
+
}
|
|
239
|
+
else if (!this.igniteClient.isReleased('sdk-platform-profiles', { accountId, userId })) {
|
|
240
|
+
return AuthorizationService.isAuthorizedMultiple_withoutPlatformProfile(accountId, userId, authorizationRequestObjects);
|
|
241
|
+
}
|
|
242
|
+
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
243
|
+
const startTime = perf_hooks.performance.now();
|
|
244
|
+
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
245
|
+
const httpClient = tridentBackendApi.Api.getPart('httpClient');
|
|
246
|
+
const profile = attributionsService.getProfile();
|
|
247
|
+
let response;
|
|
248
|
+
try {
|
|
249
|
+
response = await httpClient.fetch({
|
|
250
|
+
url: {
|
|
251
|
+
appName: 'platform',
|
|
252
|
+
path: PLATFORM_AUTHORIZE_PATH,
|
|
253
|
+
profile,
|
|
254
|
+
},
|
|
255
|
+
method: 'POST',
|
|
256
|
+
headers: {
|
|
257
|
+
Authorization: internalAuthToken,
|
|
258
|
+
'Content-Type': 'application/json',
|
|
259
|
+
...attributionHeaders,
|
|
260
|
+
},
|
|
261
|
+
body: JSON.stringify({
|
|
262
|
+
user_id: userId,
|
|
263
|
+
authorize_request_objects: authorizationRequestObjects,
|
|
264
|
+
}),
|
|
265
|
+
}, {
|
|
266
|
+
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
267
|
+
retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
catch (err) {
|
|
271
|
+
if (err instanceof httpClient.HttpFetcherError) {
|
|
272
|
+
authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'isAuthorizedMultiple');
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
throw err;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const endTime = perf_hooks.performance.now();
|
|
279
|
+
const time = endTime - startTime;
|
|
280
|
+
const unauthorizedObjects = [];
|
|
281
|
+
if (!response) {
|
|
282
|
+
authorizationInternalService.logger.error({ tag: 'authorization-service', response }, 'AuthorizationService: missing response');
|
|
283
|
+
throw new Error('AuthorizationService: missing response');
|
|
284
|
+
}
|
|
285
|
+
response.result.forEach(function (isAuthorized, index) {
|
|
286
|
+
const authorizationObject = authorizationRequestObjects[index];
|
|
287
|
+
if (!isAuthorized) {
|
|
288
|
+
unauthorizedObjects.push(authorizationObject);
|
|
289
|
+
}
|
|
290
|
+
prometheusService.sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, 200, time);
|
|
291
|
+
});
|
|
292
|
+
if (unauthorizedObjects.length > 0) {
|
|
293
|
+
authorizationInternalService.logger.info({
|
|
294
|
+
resources: JSON.stringify(unauthorizedObjects),
|
|
295
|
+
}, 'AuthorizationService: resource is unauthorized');
|
|
296
|
+
const unauthorizedIds = unauthorizedObjects
|
|
297
|
+
.filter(obj => !!obj.resource_id)
|
|
298
|
+
.map(obj => obj.resource_id);
|
|
299
|
+
return { isAuthorized: false, unauthorizedIds, unauthorizedObjects };
|
|
300
|
+
}
|
|
301
|
+
return { isAuthorized: true };
|
|
302
|
+
}
|
|
152
303
|
}
|
|
153
304
|
function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS) {
|
|
154
305
|
AuthorizationService.redisClient = client;
|
|
@@ -160,6 +311,11 @@ function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED
|
|
|
160
311
|
AuthorizationService.grantedFeatureRedisExpirationInSeconds = GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS;
|
|
161
312
|
}
|
|
162
313
|
}
|
|
314
|
+
async function setIgniteClient() {
|
|
315
|
+
AuthorizationService.igniteClient = await igniteSdk.getIgniteClient({
|
|
316
|
+
namespace: ['authorization'],
|
|
317
|
+
});
|
|
318
|
+
}
|
|
163
319
|
function createAuthorizationParams(resources, action) {
|
|
164
320
|
const params = {
|
|
165
321
|
authorizationObjects: resources.map((resource) => {
|
|
@@ -177,12 +333,14 @@ function createAuthorizationParams(resources, action) {
|
|
|
177
333
|
return params;
|
|
178
334
|
}
|
|
179
335
|
function getAuthorizeUrl() {
|
|
180
|
-
return
|
|
336
|
+
return '/internal_ms/authorization/authorize';
|
|
181
337
|
}
|
|
182
338
|
function getCanActionsInScopesUrl() {
|
|
183
|
-
return
|
|
339
|
+
return '/internal_ms/authorization/can_actions_in_scopes';
|
|
184
340
|
}
|
|
185
341
|
|
|
186
342
|
exports.AuthorizationService = AuthorizationService;
|
|
343
|
+
exports.createAuthorizationParams = createAuthorizationParams;
|
|
344
|
+
exports.setIgniteClient = setIgniteClient;
|
|
187
345
|
exports.setRedisClient = setRedisClient;
|
|
188
346
|
exports.setRequestFetchOptions = setRequestFetchOptions;
|
|
@@ -1,4 +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 {};
|
|
4
13
|
//# sourceMappingURL=attributions-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attributions-service.d.ts","sourceRoot":"","sources":["../../src/attributions-service.ts"],"names":[],"mappings":"
|
|
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 };
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { fetch, MondayFetchOptions } from '@mondaydotcomorg/monday-fetch';
|
|
2
|
-
import
|
|
2
|
+
import { OnRetryCallback, RetryPolicy } from '@mondaydotcomorg/monday-fetch-api';
|
|
3
|
+
import { BaseRequest } from './types/general';
|
|
3
4
|
export declare const logger: import("bunyan");
|
|
5
|
+
export declare const onRetryCallback: OnRetryCallback;
|
|
4
6
|
export declare class AuthorizationInternalService {
|
|
5
|
-
static skipAuthorization(requset:
|
|
6
|
-
static markAuthorized(request:
|
|
7
|
-
static failIfNotCoveredByAuthorization(request:
|
|
7
|
+
static skipAuthorization(requset: BaseRequest): void;
|
|
8
|
+
static markAuthorized(request: BaseRequest): void;
|
|
9
|
+
static failIfNotCoveredByAuthorization(request: BaseRequest): 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
|
}
|
|
14
18
|
//# sourceMappingURL=authorization-internal-service.d.ts.map
|
|
@@ -1 +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,
|
|
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,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAK9C,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAO/C,eAAO,MAAM,eAAe,EAAE,eAM7B,CAAC;AAYF,qBAAa,4BAA4B;IACvC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIpD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIjD,MAAM,CAAC,+BAA+B,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMlE,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 };
|
|
@@ -1 +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,
|
|
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,EAAE,MAAM,SAAS,CAAC;AAI5C,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,CAajB;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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import onHeaders from 'on-headers';
|
|
2
2
|
import { AuthorizationInternalService } from './authorization-internal-service.mjs';
|
|
3
|
-
import { AuthorizationService } from './authorization-service.mjs';
|
|
3
|
+
import { createAuthorizationParams, AuthorizationService } from './authorization-service.mjs';
|
|
4
4
|
|
|
5
5
|
// getAuthorizationMiddleware is duplicated in testKit/index.ts
|
|
6
6
|
// If you are making changes to this function, please make sure to update the other file as well
|
|
@@ -9,7 +9,8 @@ function getAuthorizationMiddleware(action, resourceGetter, contextGetter) {
|
|
|
9
9
|
contextGetter ||= defaultContextGetter;
|
|
10
10
|
const { userId, accountId } = contextGetter(request);
|
|
11
11
|
const resources = resourceGetter(request);
|
|
12
|
-
const {
|
|
12
|
+
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
13
|
+
const { isAuthorized } = await AuthorizationService.isAuthorized(accountId, userId, authorizationObjects);
|
|
13
14
|
AuthorizationInternalService.markAuthorized(request);
|
|
14
15
|
if (!isAuthorized) {
|
|
15
16
|
response.status(403).json({ message: 'Access denied' });
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MondayFetchOptions } from '@mondaydotcomorg/monday-fetch';
|
|
2
|
-
import {
|
|
2
|
+
import { IgniteClient } from '@mondaydotcomorg/ignite-sdk';
|
|
3
|
+
import { Action, AuthorizationObject, AuthorizationParams, Resource } from './types/general';
|
|
3
4
|
import { ScopedAction, ScopedActionPermit, ScopedActionResponseObject, ScopeOptions } from './types/scoped-actions-contracts';
|
|
4
5
|
export interface AuthorizeResponse {
|
|
5
6
|
isAuthorized: boolean;
|
|
@@ -10,6 +11,7 @@ export declare function setRequestFetchOptions(customMondayFetchOptions: MondayF
|
|
|
10
11
|
export declare class AuthorizationService {
|
|
11
12
|
static redisClient?: any;
|
|
12
13
|
static grantedFeatureRedisExpirationInSeconds?: number;
|
|
14
|
+
static igniteClient?: IgniteClient;
|
|
13
15
|
/**
|
|
14
16
|
* @deprecated use the second form with authorizationRequestObjects instead,
|
|
15
17
|
* support of this function will be dropped gradually
|
|
@@ -26,9 +28,26 @@ export declare class AuthorizationService {
|
|
|
26
28
|
private static fetchIsUserGrantedWithFeature;
|
|
27
29
|
private static getCachedKeyName;
|
|
28
30
|
static canActionInScope(accountId: number, userId: number, action: string, scope: ScopeOptions): Promise<ScopedActionPermit>;
|
|
31
|
+
/**
|
|
32
|
+
* @deprecated - gradually phasing this out
|
|
33
|
+
* @param accountId
|
|
34
|
+
* @param userId
|
|
35
|
+
* @param scopedActions
|
|
36
|
+
*/
|
|
37
|
+
private static canActionInScopeMultiple_withoutPlatformProfile;
|
|
29
38
|
static canActionInScopeMultiple(accountId: number, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
|
|
30
39
|
private static isAuthorizedSingular;
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated - gradually phasing this out
|
|
42
|
+
* @param accountId
|
|
43
|
+
* @param userId
|
|
44
|
+
* @param authorizationRequestObjects
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
private static isAuthorizedMultiple_withoutPlatformProfile;
|
|
31
48
|
private static isAuthorizedMultiple;
|
|
32
49
|
}
|
|
33
50
|
export declare function setRedisClient(client: any, grantedFeatureRedisExpirationInSeconds?: number): void;
|
|
51
|
+
export declare function setIgniteClient(): Promise<void>;
|
|
52
|
+
export declare function createAuthorizationParams(resources: Resource[], action: Action): AuthorizationParams;
|
|
34
53
|
//# sourceMappingURL=authorization-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../../src/authorization-service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../../src/authorization-service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAG1E,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,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;AAeD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;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;IAM9B;;;;;OAKG;mBACkB,+CAA+C;WAgDvD,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBA4EnB,oBAAoB;IAUzC;;;;;;OAMG;mBACkB,2CAA2C;mBAiE3C,oBAAoB;CAiG1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAIpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
|
|
@@ -3,17 +3,23 @@ import snakeCase from 'lodash/snakeCase.js';
|
|
|
3
3
|
import camelCase from 'lodash/camelCase.js';
|
|
4
4
|
import mapKeys from 'lodash/mapKeys.js';
|
|
5
5
|
import { fetch } from '@mondaydotcomorg/monday-fetch';
|
|
6
|
-
import {
|
|
6
|
+
import { Api } from '@mondaydotcomorg/trident-backend-api';
|
|
7
|
+
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
8
|
+
import { getIgniteClient } from '@mondaydotcomorg/ignite-sdk';
|
|
9
|
+
import { sendAuthorizationCheckResponseTimeMetric } from './prometheus-service.mjs';
|
|
7
10
|
import { AuthorizationInternalService, logger } from './authorization-internal-service.mjs';
|
|
8
|
-
import { getAttributionsFromApi } from './attributions-service.mjs';
|
|
11
|
+
import { getAttributionsFromApi, getProfile } from './attributions-service.mjs';
|
|
9
12
|
|
|
10
13
|
const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
|
|
14
|
+
const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
|
|
15
|
+
const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
|
|
11
16
|
function setRequestFetchOptions(customMondayFetchOptions) {
|
|
12
17
|
AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
|
|
13
18
|
}
|
|
14
19
|
class AuthorizationService {
|
|
15
20
|
static redisClient;
|
|
16
21
|
static grantedFeatureRedisExpirationInSeconds;
|
|
22
|
+
static igniteClient;
|
|
17
23
|
static async isAuthorized(...args) {
|
|
18
24
|
if (args.length === 3) {
|
|
19
25
|
return this.isAuthorizedMultiple(args[0], args[1], args[2]);
|
|
@@ -61,7 +67,13 @@ class AuthorizationService {
|
|
|
61
67
|
const scopedActionResponseObjects = await this.canActionInScopeMultiple(accountId, userId, scopedActions);
|
|
62
68
|
return scopedActionResponseObjects[0].permit;
|
|
63
69
|
}
|
|
64
|
-
|
|
70
|
+
/**
|
|
71
|
+
* @deprecated - gradually phasing this out
|
|
72
|
+
* @param accountId
|
|
73
|
+
* @param userId
|
|
74
|
+
* @param scopedActions
|
|
75
|
+
*/
|
|
76
|
+
static async canActionInScopeMultiple_withoutPlatformProfile(accountId, userId, scopedActions) {
|
|
65
77
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
66
78
|
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
67
79
|
return { ...scopedAction, scope: mapKeys(scopedAction.scope, (_, key) => snakeCase(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
@@ -95,11 +107,82 @@ class AuthorizationService {
|
|
|
95
107
|
});
|
|
96
108
|
return scopedActionsResponseObjects;
|
|
97
109
|
}
|
|
110
|
+
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
111
|
+
// gradually release the new platform profile features
|
|
112
|
+
if (!this.igniteClient) {
|
|
113
|
+
logger.warn({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, using new platform profile feature');
|
|
114
|
+
}
|
|
115
|
+
else if (!this.igniteClient.isReleased('sdk-platform-profiles', { accountId, userId })) {
|
|
116
|
+
return AuthorizationService.canActionInScopeMultiple_withoutPlatformProfile(accountId, userId, scopedActions);
|
|
117
|
+
}
|
|
118
|
+
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
119
|
+
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
120
|
+
return { ...scopedAction, scope: mapKeys(scopedAction.scope, (_, key) => snakeCase(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
121
|
+
});
|
|
122
|
+
const attributionHeaders = getAttributionsFromApi();
|
|
123
|
+
const httpClient = Api.getPart('httpClient');
|
|
124
|
+
const profile = getProfile();
|
|
125
|
+
let response;
|
|
126
|
+
try {
|
|
127
|
+
response = await httpClient.fetch({
|
|
128
|
+
url: {
|
|
129
|
+
appName: 'platform',
|
|
130
|
+
path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
|
|
131
|
+
profile,
|
|
132
|
+
},
|
|
133
|
+
method: 'POST',
|
|
134
|
+
headers: {
|
|
135
|
+
Authorization: internalAuthToken,
|
|
136
|
+
'Content-Type': 'application/json',
|
|
137
|
+
...attributionHeaders,
|
|
138
|
+
},
|
|
139
|
+
body: JSON.stringify({
|
|
140
|
+
user_id: userId,
|
|
141
|
+
scoped_actions: scopedActionsPayload,
|
|
142
|
+
}),
|
|
143
|
+
}, {
|
|
144
|
+
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
145
|
+
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
if (err instanceof HttpFetcherError) {
|
|
150
|
+
AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
throw err;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function toCamelCase(obj) {
|
|
157
|
+
return mapKeys(obj, (_, key) => camelCase(key));
|
|
158
|
+
}
|
|
159
|
+
if (!response) {
|
|
160
|
+
logger.error({ tag: 'authorization-service', response }, 'AuthorizationService: missing response');
|
|
161
|
+
throw new Error('AuthorizationService: missing response');
|
|
162
|
+
}
|
|
163
|
+
const scopedActionsResponseObjects = response.result.map(responseObject => {
|
|
164
|
+
const { scopedAction, permit } = responseObject;
|
|
165
|
+
const { scope } = scopedAction;
|
|
166
|
+
return {
|
|
167
|
+
...responseObject,
|
|
168
|
+
scopedAction: { ...scopedAction, scope: toCamelCase(scope) },
|
|
169
|
+
permit: toCamelCase(permit),
|
|
170
|
+
};
|
|
171
|
+
});
|
|
172
|
+
return scopedActionsResponseObjects;
|
|
173
|
+
}
|
|
98
174
|
static async isAuthorizedSingular(accountId, userId, resources, action) {
|
|
99
175
|
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
100
176
|
return this.isAuthorizedMultiple(accountId, userId, authorizationObjects);
|
|
101
177
|
}
|
|
102
|
-
|
|
178
|
+
/**
|
|
179
|
+
* @deprecated - gradually phasing this out
|
|
180
|
+
* @param accountId
|
|
181
|
+
* @param userId
|
|
182
|
+
* @param authorizationRequestObjects
|
|
183
|
+
* @private
|
|
184
|
+
*/
|
|
185
|
+
static async isAuthorizedMultiple_withoutPlatformProfile(accountId, userId, authorizationRequestObjects) {
|
|
103
186
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
104
187
|
const startTime = performance.now();
|
|
105
188
|
const attributionHeaders = getAttributionsFromApi();
|
|
@@ -119,7 +202,6 @@ class AuthorizationService {
|
|
|
119
202
|
const endTime = performance.now();
|
|
120
203
|
const time = endTime - startTime;
|
|
121
204
|
const responseStatus = response.status;
|
|
122
|
-
sendAuthorizationChecksPerRequestMetric(responseStatus, authorizationRequestObjects.length);
|
|
123
205
|
AuthorizationInternalService.throwOnHttpErrorIfNeeded(response, 'isAuthorizedMultiple');
|
|
124
206
|
const responseBody = await response.json();
|
|
125
207
|
const unauthorizedObjects = [];
|
|
@@ -141,6 +223,75 @@ class AuthorizationService {
|
|
|
141
223
|
}
|
|
142
224
|
return { isAuthorized: true };
|
|
143
225
|
}
|
|
226
|
+
static async isAuthorizedMultiple(accountId, userId, authorizationRequestObjects) {
|
|
227
|
+
// gradually release the new platform profile features
|
|
228
|
+
if (!this.igniteClient) {
|
|
229
|
+
logger.warn({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, using new platform profile feature');
|
|
230
|
+
}
|
|
231
|
+
else if (!this.igniteClient.isReleased('sdk-platform-profiles', { accountId, userId })) {
|
|
232
|
+
return AuthorizationService.isAuthorizedMultiple_withoutPlatformProfile(accountId, userId, authorizationRequestObjects);
|
|
233
|
+
}
|
|
234
|
+
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
235
|
+
const startTime = performance.now();
|
|
236
|
+
const attributionHeaders = getAttributionsFromApi();
|
|
237
|
+
const httpClient = Api.getPart('httpClient');
|
|
238
|
+
const profile = getProfile();
|
|
239
|
+
let response;
|
|
240
|
+
try {
|
|
241
|
+
response = await httpClient.fetch({
|
|
242
|
+
url: {
|
|
243
|
+
appName: 'platform',
|
|
244
|
+
path: PLATFORM_AUTHORIZE_PATH,
|
|
245
|
+
profile,
|
|
246
|
+
},
|
|
247
|
+
method: 'POST',
|
|
248
|
+
headers: {
|
|
249
|
+
Authorization: internalAuthToken,
|
|
250
|
+
'Content-Type': 'application/json',
|
|
251
|
+
...attributionHeaders,
|
|
252
|
+
},
|
|
253
|
+
body: JSON.stringify({
|
|
254
|
+
user_id: userId,
|
|
255
|
+
authorize_request_objects: authorizationRequestObjects,
|
|
256
|
+
}),
|
|
257
|
+
}, {
|
|
258
|
+
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
259
|
+
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
if (err instanceof httpClient.HttpFetcherError) {
|
|
264
|
+
AuthorizationInternalService.throwOnHttpError(err.status, 'isAuthorizedMultiple');
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
throw err;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const endTime = performance.now();
|
|
271
|
+
const time = endTime - startTime;
|
|
272
|
+
const unauthorizedObjects = [];
|
|
273
|
+
if (!response) {
|
|
274
|
+
logger.error({ tag: 'authorization-service', response }, 'AuthorizationService: missing response');
|
|
275
|
+
throw new Error('AuthorizationService: missing response');
|
|
276
|
+
}
|
|
277
|
+
response.result.forEach(function (isAuthorized, index) {
|
|
278
|
+
const authorizationObject = authorizationRequestObjects[index];
|
|
279
|
+
if (!isAuthorized) {
|
|
280
|
+
unauthorizedObjects.push(authorizationObject);
|
|
281
|
+
}
|
|
282
|
+
sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, 200, time);
|
|
283
|
+
});
|
|
284
|
+
if (unauthorizedObjects.length > 0) {
|
|
285
|
+
logger.info({
|
|
286
|
+
resources: JSON.stringify(unauthorizedObjects),
|
|
287
|
+
}, 'AuthorizationService: resource is unauthorized');
|
|
288
|
+
const unauthorizedIds = unauthorizedObjects
|
|
289
|
+
.filter(obj => !!obj.resource_id)
|
|
290
|
+
.map(obj => obj.resource_id);
|
|
291
|
+
return { isAuthorized: false, unauthorizedIds, unauthorizedObjects };
|
|
292
|
+
}
|
|
293
|
+
return { isAuthorized: true };
|
|
294
|
+
}
|
|
144
295
|
}
|
|
145
296
|
function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS) {
|
|
146
297
|
AuthorizationService.redisClient = client;
|
|
@@ -152,6 +303,11 @@ function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED
|
|
|
152
303
|
AuthorizationService.grantedFeatureRedisExpirationInSeconds = GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS;
|
|
153
304
|
}
|
|
154
305
|
}
|
|
306
|
+
async function setIgniteClient() {
|
|
307
|
+
AuthorizationService.igniteClient = await getIgniteClient({
|
|
308
|
+
namespace: ['authorization'],
|
|
309
|
+
});
|
|
310
|
+
}
|
|
155
311
|
function createAuthorizationParams(resources, action) {
|
|
156
312
|
const params = {
|
|
157
313
|
authorizationObjects: resources.map((resource) => {
|
|
@@ -169,10 +325,10 @@ function createAuthorizationParams(resources, action) {
|
|
|
169
325
|
return params;
|
|
170
326
|
}
|
|
171
327
|
function getAuthorizeUrl() {
|
|
172
|
-
return
|
|
328
|
+
return '/internal_ms/authorization/authorize';
|
|
173
329
|
}
|
|
174
330
|
function getCanActionsInScopesUrl() {
|
|
175
|
-
return
|
|
331
|
+
return '/internal_ms/authorization/can_actions_in_scopes';
|
|
176
332
|
}
|
|
177
333
|
|
|
178
|
-
export { AuthorizationService, setRedisClient, setRequestFetchOptions };
|
|
334
|
+
export { AuthorizationService, createAuthorizationParams, setIgniteClient, setRedisClient, setRequestFetchOptions };
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface InitOptions {
|
|
|
6
6
|
redisClient?: any;
|
|
7
7
|
grantedFeatureRedisExpirationInSeconds?: number;
|
|
8
8
|
}
|
|
9
|
-
export declare function init(options?: InitOptions): void
|
|
9
|
+
export declare function init(options?: InitOptions): Promise<void>;
|
|
10
10
|
export { authorizationCheckMiddleware, getAuthorizationMiddleware, skipAuthorizationMiddleware, } from './authorization-middleware';
|
|
11
11
|
export { AuthorizationService, AuthorizeResponse } from './authorization-service';
|
|
12
12
|
export { AuthorizationAttributesService } from './authorization-attributes-service';
|
package/dist/esm/index.d.ts.map
CHANGED
|
@@ -1 +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,
|
|
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,wBAAsB,IAAI,CAAC,OAAO,GAAE,WAAgB,iBAcnD;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"}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { setPrometheus } from './prometheus-service.mjs';
|
|
2
|
-
import { setRequestFetchOptions, setRedisClient } from './authorization-service.mjs';
|
|
2
|
+
import { setRequestFetchOptions, setRedisClient, setIgniteClient } from './authorization-service.mjs';
|
|
3
3
|
export { AuthorizationService } from './authorization-service.mjs';
|
|
4
4
|
import * as testKit_index from './testKit/index.mjs';
|
|
5
5
|
export { testKit_index as TestKit };
|
|
6
6
|
export { authorizationCheckMiddleware, getAuthorizationMiddleware, skipAuthorizationMiddleware } from './authorization-middleware.mjs';
|
|
7
7
|
export { AuthorizationAttributesService } from './authorization-attributes-service.mjs';
|
|
8
8
|
|
|
9
|
-
function init(options = {}) {
|
|
9
|
+
async function init(options = {}) {
|
|
10
10
|
if (options.prometheus) {
|
|
11
11
|
setPrometheus(options.prometheus);
|
|
12
12
|
}
|
|
@@ -16,6 +16,8 @@ function init(options = {}) {
|
|
|
16
16
|
if (options.redisClient) {
|
|
17
17
|
setRedisClient(options.redisClient, options.grantedFeatureRedisExpirationInSeconds);
|
|
18
18
|
}
|
|
19
|
+
// add an ignite client for gradual release features
|
|
20
|
+
await setIgniteClient();
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
export { init };
|
|
@@ -6,6 +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;
|
|
11
10
|
//# sourceMappingURL=prometheus-service.d.ts.map
|
|
@@ -1 +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;
|
|
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 };
|
|
@@ -1 +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,
|
|
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"}
|
|
@@ -19,13 +19,13 @@ export interface AuthorizationParams {
|
|
|
19
19
|
authorizationObjects: AuthorizationObject[];
|
|
20
20
|
}
|
|
21
21
|
type BasicObject = {
|
|
22
|
-
[key: string]:
|
|
22
|
+
[key: string]: unknown;
|
|
23
23
|
};
|
|
24
24
|
export type BaseParameters = BasicObject;
|
|
25
25
|
export type BaseResponseBody = BasicObject;
|
|
26
26
|
export type BaseBodyParameters = BasicObject;
|
|
27
27
|
export type BaseQueryParameters = BasicObject;
|
|
28
|
-
export type BaseRequest = Request<
|
|
28
|
+
export type BaseRequest = Request<Express.Request, BaseResponseBody, BaseBodyParameters, BaseQueryParameters>;
|
|
29
29
|
export type BaseResponse = Response<BaseResponseBody>;
|
|
30
30
|
export type ResourceGetter = (request: BaseRequest) => Resource[];
|
|
31
31
|
export type ContextGetter = (request: BaseRequest) => Context;
|
|
@@ -1 +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,
|
|
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,OAAO,CAAA;CAAE,CAAC;AAE9C,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,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;AAC9G,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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface InitOptions {
|
|
|
6
6
|
redisClient?: any;
|
|
7
7
|
grantedFeatureRedisExpirationInSeconds?: number;
|
|
8
8
|
}
|
|
9
|
-
export declare function init(options?: InitOptions): void
|
|
9
|
+
export declare function init(options?: InitOptions): Promise<void>;
|
|
10
10
|
export { authorizationCheckMiddleware, getAuthorizationMiddleware, skipAuthorizationMiddleware, } from './authorization-middleware';
|
|
11
11
|
export { AuthorizationService, AuthorizeResponse } from './authorization-service';
|
|
12
12
|
export { AuthorizationAttributesService } from './authorization-attributes-service';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +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,
|
|
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,wBAAsB,IAAI,CAAC,OAAO,GAAE,WAAgB,iBAcnD;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"}
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ const testKit_index = require('./testKit/index.js');
|
|
|
6
6
|
const authorizationMiddleware = require('./authorization-middleware.js');
|
|
7
7
|
const authorizationAttributesService = require('./authorization-attributes-service.js');
|
|
8
8
|
|
|
9
|
-
function init(options = {}) {
|
|
9
|
+
async function init(options = {}) {
|
|
10
10
|
if (options.prometheus) {
|
|
11
11
|
prometheusService.setPrometheus(options.prometheus);
|
|
12
12
|
}
|
|
@@ -16,6 +16,8 @@ function init(options = {}) {
|
|
|
16
16
|
if (options.redisClient) {
|
|
17
17
|
authorizationService.setRedisClient(options.redisClient, options.grantedFeatureRedisExpirationInSeconds);
|
|
18
18
|
}
|
|
19
|
+
// add an ignite client for gradual release features
|
|
20
|
+
await authorizationService.setIgniteClient();
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
exports.AuthorizationService = authorizationService.AuthorizationService;
|
|
@@ -6,6 +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;
|
|
11
10
|
//# sourceMappingURL=prometheus-service.d.ts.map
|
|
@@ -1 +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;
|
|
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;
|
|
@@ -1 +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,
|
|
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"}
|
package/dist/types/general.d.ts
CHANGED
|
@@ -19,13 +19,13 @@ export interface AuthorizationParams {
|
|
|
19
19
|
authorizationObjects: AuthorizationObject[];
|
|
20
20
|
}
|
|
21
21
|
type BasicObject = {
|
|
22
|
-
[key: string]:
|
|
22
|
+
[key: string]: unknown;
|
|
23
23
|
};
|
|
24
24
|
export type BaseParameters = BasicObject;
|
|
25
25
|
export type BaseResponseBody = BasicObject;
|
|
26
26
|
export type BaseBodyParameters = BasicObject;
|
|
27
27
|
export type BaseQueryParameters = BasicObject;
|
|
28
|
-
export type BaseRequest = Request<
|
|
28
|
+
export type BaseRequest = Request<Express.Request, BaseResponseBody, BaseBodyParameters, BaseQueryParameters>;
|
|
29
29
|
export type BaseResponse = Response<BaseResponseBody>;
|
|
30
30
|
export type ResourceGetter = (request: BaseRequest) => Resource[];
|
|
31
31
|
export type ContextGetter = (request: BaseRequest) => Context;
|
|
@@ -1 +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,
|
|
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,OAAO,CAAA;CAAE,CAAC;AAE9C,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,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;AAC9G,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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mondaydotcomorg/monday-authorization",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-fix-moshesa-set-basic-object-val-to-unknown--8965160254.59909b8",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
"watch": "trident-library build -w"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
+
"@mondaydotcomorg/ignite-sdk": "^2.0.5",
|
|
22
23
|
"@mondaydotcomorg/monday-fetch": "^0.0.7",
|
|
24
|
+
"@mondaydotcomorg/monday-fetch-api": "^1.0.2",
|
|
23
25
|
"@mondaydotcomorg/monday-jwt": "^3.0.14",
|
|
24
26
|
"@mondaydotcomorg/monday-logger": "^4.0.11",
|
|
25
27
|
"@mondaydotcomorg/monday-sns": "^1.0.6",
|
|
@@ -37,7 +39,7 @@
|
|
|
37
39
|
"@types/supertest": "^2.0.11",
|
|
38
40
|
"express": "^4.17.1",
|
|
39
41
|
"ioredis": "^5.2.4",
|
|
40
|
-
"ioredis-mock": "^8.
|
|
42
|
+
"ioredis-mock": "^8.9.0",
|
|
41
43
|
"sinon": "9.0.3",
|
|
42
44
|
"supertest": "^6.1.3",
|
|
43
45
|
"typescript": "^5.2.2"
|