@mondaydotcomorg/monday-authorization 3.1.2 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attributions-service.d.ts +1 -2
- package/dist/attributions-service.d.ts.map +1 -1
- package/dist/attributions-service.js +6 -6
- package/dist/authorization-internal-service.d.ts +4 -1
- package/dist/authorization-internal-service.d.ts.map +1 -1
- package/dist/authorization-internal-service.js +21 -1
- package/dist/authorization-service.d.ts +1 -15
- package/dist/authorization-service.d.ts.map +1 -1
- package/dist/authorization-service.js +24 -111
- package/dist/esm/attributions-service.d.ts +1 -2
- package/dist/esm/attributions-service.d.ts.map +1 -1
- package/dist/esm/attributions-service.mjs +1 -1
- package/dist/esm/authorization-internal-service.d.ts +4 -1
- package/dist/esm/authorization-internal-service.d.ts.map +1 -1
- package/dist/esm/authorization-internal-service.mjs +21 -1
- package/dist/esm/authorization-service.d.ts +1 -15
- package/dist/esm/authorization-service.d.ts.map +1 -1
- package/dist/esm/authorization-service.mjs +25 -112
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Context, ExecutionContext } from '@mondaydotcomorg/trident-backend-api';
|
|
2
|
-
declare enum PlatformProfile {
|
|
2
|
+
export declare enum PlatformProfile {
|
|
3
3
|
API_INTERNAL = "api-internal",
|
|
4
4
|
SLOW = "slow",
|
|
5
5
|
INTERNAL = "internal"
|
|
@@ -9,5 +9,4 @@ export declare function getExecutionContext(context: Context): ExecutionContext;
|
|
|
9
9
|
export declare function getAttributionsFromApi(): {
|
|
10
10
|
[key: string]: string;
|
|
11
11
|
};
|
|
12
|
-
export {};
|
|
13
12
|
//# sourceMappingURL=attributions-service.d.ts.map
|
|
@@ -1 +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,
|
|
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,oBAAY,eAAe;IACzB,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,27 +7,27 @@ 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
|
-
|
|
10
|
+
exports.PlatformProfile = void 0;
|
|
11
11
|
(function (PlatformProfile) {
|
|
12
12
|
PlatformProfile["API_INTERNAL"] = "api-internal";
|
|
13
13
|
PlatformProfile["SLOW"] = "slow";
|
|
14
14
|
PlatformProfile["INTERNAL"] = "internal";
|
|
15
|
-
})(PlatformProfile || (PlatformProfile = {}));
|
|
15
|
+
})(exports.PlatformProfile || (exports.PlatformProfile = {}));
|
|
16
16
|
function getProfile() {
|
|
17
17
|
const tridentContext = tridentBackendApi.Api.getPart('context');
|
|
18
18
|
if (!tridentContext) {
|
|
19
|
-
return PlatformProfile.INTERNAL;
|
|
19
|
+
return exports.PlatformProfile.INTERNAL;
|
|
20
20
|
}
|
|
21
21
|
const { mondayRequestSource } = getExecutionContext(tridentContext);
|
|
22
22
|
switch (mondayRequestSource) {
|
|
23
23
|
case 'api': {
|
|
24
|
-
return PlatformProfile.API_INTERNAL;
|
|
24
|
+
return exports.PlatformProfile.API_INTERNAL;
|
|
25
25
|
}
|
|
26
26
|
case 'slow': {
|
|
27
|
-
return PlatformProfile.SLOW;
|
|
27
|
+
return exports.PlatformProfile.SLOW;
|
|
28
28
|
}
|
|
29
29
|
default:
|
|
30
|
-
return PlatformProfile.INTERNAL;
|
|
30
|
+
return exports.PlatformProfile.INTERNAL;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
function getExecutionContext(context) {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { fetch, MondayFetchOptions } from '@mondaydotcomorg/monday-fetch';
|
|
2
2
|
import { OnRetryCallback, RetryPolicy } from '@mondaydotcomorg/monday-fetch-api';
|
|
3
|
+
import { IgniteClient } from '@mondaydotcomorg/ignite-sdk';
|
|
3
4
|
import { BaseRequest } from './types/general';
|
|
4
5
|
export declare const logger: import("bunyan");
|
|
5
6
|
export declare const onRetryCallback: OnRetryCallback;
|
|
6
7
|
export declare class AuthorizationInternalService {
|
|
8
|
+
static igniteClient?: IgniteClient;
|
|
7
9
|
static skipAuthorization(requset: BaseRequest): void;
|
|
8
10
|
static markAuthorized(request: BaseRequest): void;
|
|
9
11
|
static failIfNotCoveredByAuthorization(request: BaseRequest): void;
|
|
@@ -12,7 +14,8 @@ export declare class AuthorizationInternalService {
|
|
|
12
14
|
static generateInternalAuthToken(accountId: number, userId: number): string;
|
|
13
15
|
static setRequestFetchOptions(customMondayFetchOptions: MondayFetchOptions): void;
|
|
14
16
|
static getRequestFetchOptions(): MondayFetchOptions;
|
|
15
|
-
static
|
|
17
|
+
static setIgniteClient(client: IgniteClient): void;
|
|
18
|
+
static getRequestTimeout(): number;
|
|
16
19
|
static getRetriesPolicy(): RetryPolicy;
|
|
17
20
|
}
|
|
18
21
|
//# 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,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;
|
|
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,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,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,YAAY,CAAC,EAAE,YAAY,CAAC;IACnC,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,eAAe,CAAC,MAAM,EAAE,YAAY;IAI3C,MAAM,CAAC,iBAAiB;IA2BxB,MAAM,CAAC,gBAAgB,IAAI,WAAW;CASvC"}
|
|
@@ -49,6 +49,7 @@ function logOnFetchFail(retriesLeft, error) {
|
|
|
49
49
|
}
|
|
50
50
|
let mondayFetchOptions = defaultMondayFetchOptions;
|
|
51
51
|
class AuthorizationInternalService {
|
|
52
|
+
static igniteClient;
|
|
52
53
|
static skipAuthorization(requset) {
|
|
53
54
|
requset.authorizationSkipPerformed = true;
|
|
54
55
|
}
|
|
@@ -84,9 +85,28 @@ class AuthorizationInternalService {
|
|
|
84
85
|
static getRequestFetchOptions() {
|
|
85
86
|
return mondayFetchOptions;
|
|
86
87
|
}
|
|
88
|
+
static setIgniteClient(client) {
|
|
89
|
+
this.igniteClient = client;
|
|
90
|
+
}
|
|
87
91
|
static getRequestTimeout() {
|
|
88
92
|
const isDevEnv = process.env.NODE_ENV === 'development';
|
|
89
|
-
|
|
93
|
+
const defaultTimeout = isDevEnv ? 60000 : 2000;
|
|
94
|
+
if (!this.igniteClient) {
|
|
95
|
+
return defaultTimeout;
|
|
96
|
+
}
|
|
97
|
+
const overrideTimeouts = this.igniteClient.configuration.getObjectValue('override-outgoing-request-timeout-ms', {});
|
|
98
|
+
try {
|
|
99
|
+
if (process.env.APP_NAME && process.env.APP_NAME in overrideTimeouts) {
|
|
100
|
+
return overrideTimeouts[process.env.APP_NAME];
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
return this.igniteClient.configuration.getNumberValue('outgoing-request-timeout-ms', defaultTimeout);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
logger.error({ tag: 'authorization-service', error, defaultTimeout }, 'Failed to get timeout from ignite configuration, returning default timeout');
|
|
108
|
+
return defaultTimeout;
|
|
109
|
+
}
|
|
90
110
|
}
|
|
91
111
|
static getRetriesPolicy() {
|
|
92
112
|
const fetchOptions = AuthorizationInternalService.getRequestFetchOptions();
|
|
@@ -28,23 +28,9 @@ export declare class AuthorizationService {
|
|
|
28
28
|
private static fetchIsUserGrantedWithFeature;
|
|
29
29
|
private static getCachedKeyName;
|
|
30
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;
|
|
31
|
+
private static getProfile;
|
|
38
32
|
static canActionInScopeMultiple(accountId: number, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
|
|
39
33
|
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;
|
|
48
34
|
private static isAuthorizedMultiple;
|
|
49
35
|
}
|
|
50
36
|
export declare function setRedisClient(client: any, grantedFeatureRedisExpirationInSeconds?: number): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../src/authorization-service.ts"],"names":[],"mappings":"AAIA,OAAO,
|
|
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,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;AAY1C,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,OAAO,CAAC,MAAM,CAAC,UAAU;WAsBZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBAkEnB,oBAAoB;mBAUpB,oBAAoB;CAmF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
|
|
@@ -4,7 +4,6 @@ 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 mondayFetch = require('@mondaydotcomorg/monday-fetch');
|
|
8
7
|
const tridentBackendApi = require('@mondaydotcomorg/trident-backend-api');
|
|
9
8
|
const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
|
|
10
9
|
const igniteSdk = require('@mondaydotcomorg/ignite-sdk');
|
|
@@ -21,6 +20,9 @@ const mapKeys__default = /*#__PURE__*/_interopDefault(mapKeys);
|
|
|
21
20
|
const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
|
|
22
21
|
const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
|
|
23
22
|
const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
|
|
23
|
+
const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
|
|
24
|
+
const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
|
|
25
|
+
const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
|
|
24
26
|
function setRequestFetchOptions(customMondayFetchOptions) {
|
|
25
27
|
authorizationInternalService.AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
|
|
26
28
|
}
|
|
@@ -75,61 +77,31 @@ class AuthorizationService {
|
|
|
75
77
|
const scopedActionResponseObjects = await this.canActionInScopeMultiple(accountId, userId, scopedActions);
|
|
76
78
|
return scopedActionResponseObjects[0].permit;
|
|
77
79
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
* @param accountId
|
|
81
|
-
* @param userId
|
|
82
|
-
* @param scopedActions
|
|
83
|
-
*/
|
|
84
|
-
static async canActionInScopeMultiple_withoutPlatformProfile(accountId, userId, scopedActions) {
|
|
85
|
-
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
86
|
-
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
87
|
-
return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
88
|
-
});
|
|
89
|
-
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
90
|
-
const response = await mondayFetch.fetch(getCanActionsInScopesUrl(), {
|
|
91
|
-
method: 'POST',
|
|
92
|
-
headers: {
|
|
93
|
-
Authorization: internalAuthToken,
|
|
94
|
-
'Content-Type': 'application/json',
|
|
95
|
-
...attributionHeaders,
|
|
96
|
-
},
|
|
97
|
-
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
98
|
-
body: JSON.stringify({
|
|
99
|
-
user_id: userId,
|
|
100
|
-
scoped_actions: scopedActionsPayload,
|
|
101
|
-
}),
|
|
102
|
-
}, authorizationInternalService.AuthorizationInternalService.getRequestFetchOptions());
|
|
103
|
-
authorizationInternalService.AuthorizationInternalService.throwOnHttpErrorIfNeeded(response, 'canActionInScopeMultiple');
|
|
104
|
-
const responseBody = await response.json();
|
|
105
|
-
const camelCaseKeys = obj => Object.fromEntries(Object.entries(obj).map(([key, value]) => [camelCase__default.default(key), value]));
|
|
106
|
-
const scopedActionsResponseObjects = responseBody.result.map(responseObject => {
|
|
107
|
-
const { scopedAction, permit } = responseObject;
|
|
108
|
-
const { scope } = scopedAction;
|
|
109
|
-
const transformKeys = obj => camelCaseKeys(obj);
|
|
110
|
-
return {
|
|
111
|
-
...responseObject,
|
|
112
|
-
scopedAction: { ...scopedAction, scope: transformKeys(scope) },
|
|
113
|
-
permit: transformKeys(permit),
|
|
114
|
-
};
|
|
115
|
-
});
|
|
116
|
-
return scopedActionsResponseObjects;
|
|
117
|
-
}
|
|
118
|
-
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
119
|
-
// gradually release the new platform profile features
|
|
80
|
+
static getProfile(accountId, userId) {
|
|
81
|
+
const appName = process.env.APP_NAME ?? 'INVALID_APP_NAME';
|
|
120
82
|
if (!this.igniteClient) {
|
|
121
|
-
authorizationInternalService.logger.
|
|
83
|
+
authorizationInternalService.logger.error({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, failing request');
|
|
84
|
+
throw new Error('AuthorizationService: igniteClient is not set, failing request');
|
|
85
|
+
}
|
|
86
|
+
if (this.igniteClient.configuration.getObjectValue(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []).includes(appName)) {
|
|
87
|
+
return attributionsService.getProfile();
|
|
122
88
|
}
|
|
123
|
-
|
|
124
|
-
|
|
89
|
+
if (this.igniteClient.configuration
|
|
90
|
+
.getObjectValue(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, [])
|
|
91
|
+
.includes(appName) &&
|
|
92
|
+
this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId })) {
|
|
93
|
+
return attributionsService.getProfile();
|
|
125
94
|
}
|
|
95
|
+
return attributionsService.PlatformProfile.INTERNAL;
|
|
96
|
+
}
|
|
97
|
+
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
98
|
+
const profile = this.getProfile(accountId, userId);
|
|
126
99
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
127
100
|
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
128
101
|
return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
129
102
|
});
|
|
130
103
|
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
131
104
|
const httpClient = tridentBackendApi.Api.getPart('httpClient');
|
|
132
|
-
const profile = attributionsService.getProfile();
|
|
133
105
|
let response;
|
|
134
106
|
try {
|
|
135
107
|
response = await httpClient.fetch({
|
|
@@ -183,67 +155,12 @@ class AuthorizationService {
|
|
|
183
155
|
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
184
156
|
return this.isAuthorizedMultiple(accountId, userId, authorizationObjects);
|
|
185
157
|
}
|
|
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) {
|
|
194
|
-
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
195
|
-
const startTime = perf_hooks.performance.now();
|
|
196
|
-
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
197
|
-
const response = await mondayFetch.fetch(getAuthorizeUrl(), {
|
|
198
|
-
method: 'POST',
|
|
199
|
-
headers: {
|
|
200
|
-
Authorization: internalAuthToken,
|
|
201
|
-
'Content-Type': 'application/json',
|
|
202
|
-
...attributionHeaders,
|
|
203
|
-
},
|
|
204
|
-
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
205
|
-
body: JSON.stringify({
|
|
206
|
-
user_id: userId,
|
|
207
|
-
authorize_request_objects: authorizationRequestObjects,
|
|
208
|
-
}),
|
|
209
|
-
}, authorizationInternalService.AuthorizationInternalService.getRequestFetchOptions());
|
|
210
|
-
const endTime = perf_hooks.performance.now();
|
|
211
|
-
const time = endTime - startTime;
|
|
212
|
-
const responseStatus = response.status;
|
|
213
|
-
authorizationInternalService.AuthorizationInternalService.throwOnHttpErrorIfNeeded(response, 'isAuthorizedMultiple');
|
|
214
|
-
const responseBody = await response.json();
|
|
215
|
-
const unauthorizedObjects = [];
|
|
216
|
-
responseBody.result.forEach(function (isAuthorized, index) {
|
|
217
|
-
const authorizationObject = authorizationRequestObjects[index];
|
|
218
|
-
if (!isAuthorized) {
|
|
219
|
-
unauthorizedObjects.push(authorizationObject);
|
|
220
|
-
}
|
|
221
|
-
prometheusService.sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, responseStatus, time);
|
|
222
|
-
});
|
|
223
|
-
if (unauthorizedObjects.length > 0) {
|
|
224
|
-
authorizationInternalService.logger.info({
|
|
225
|
-
resources: JSON.stringify(unauthorizedObjects),
|
|
226
|
-
}, 'AuthorizationService: resource is unauthorized');
|
|
227
|
-
const unauthorizedIds = unauthorizedObjects
|
|
228
|
-
.filter(obj => !!obj.resource_id)
|
|
229
|
-
.map(obj => obj.resource_id);
|
|
230
|
-
return { isAuthorized: false, unauthorizedIds, unauthorizedObjects };
|
|
231
|
-
}
|
|
232
|
-
return { isAuthorized: true };
|
|
233
|
-
}
|
|
234
158
|
static async isAuthorizedMultiple(accountId, userId, authorizationRequestObjects) {
|
|
235
|
-
|
|
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
|
-
}
|
|
159
|
+
const profile = this.getProfile(accountId, userId);
|
|
242
160
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
243
161
|
const startTime = perf_hooks.performance.now();
|
|
244
162
|
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
245
163
|
const httpClient = tridentBackendApi.Api.getPart('httpClient');
|
|
246
|
-
const profile = attributionsService.getProfile();
|
|
247
164
|
let response;
|
|
248
165
|
try {
|
|
249
166
|
response = await httpClient.fetch({
|
|
@@ -312,9 +229,11 @@ function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED
|
|
|
312
229
|
}
|
|
313
230
|
}
|
|
314
231
|
async function setIgniteClient() {
|
|
315
|
-
|
|
316
|
-
namespace: ['authorization'],
|
|
232
|
+
const igniteClient = await igniteSdk.getIgniteClient({
|
|
233
|
+
namespace: ['authorization-sdk'],
|
|
317
234
|
});
|
|
235
|
+
AuthorizationService.igniteClient = igniteClient;
|
|
236
|
+
authorizationInternalService.AuthorizationInternalService.setIgniteClient(igniteClient);
|
|
318
237
|
}
|
|
319
238
|
function createAuthorizationParams(resources, action) {
|
|
320
239
|
const params = {
|
|
@@ -332,12 +251,6 @@ function createAuthorizationParams(resources, action) {
|
|
|
332
251
|
};
|
|
333
252
|
return params;
|
|
334
253
|
}
|
|
335
|
-
function getAuthorizeUrl() {
|
|
336
|
-
return `${process.env.MONDAY_INTERNAL_URL}/internal_ms/authorization/authorize`;
|
|
337
|
-
}
|
|
338
|
-
function getCanActionsInScopesUrl() {
|
|
339
|
-
return `${process.env.MONDAY_INTERNAL_URL}/internal_ms/authorization/can_actions_in_scopes`;
|
|
340
|
-
}
|
|
341
254
|
|
|
342
255
|
exports.AuthorizationService = AuthorizationService;
|
|
343
256
|
exports.createAuthorizationParams = createAuthorizationParams;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Context, ExecutionContext } from '@mondaydotcomorg/trident-backend-api';
|
|
2
|
-
declare enum PlatformProfile {
|
|
2
|
+
export declare enum PlatformProfile {
|
|
3
3
|
API_INTERNAL = "api-internal",
|
|
4
4
|
SLOW = "slow",
|
|
5
5
|
INTERNAL = "internal"
|
|
@@ -9,5 +9,4 @@ export declare function getExecutionContext(context: Context): ExecutionContext;
|
|
|
9
9
|
export declare function getAttributionsFromApi(): {
|
|
10
10
|
[key: string]: string;
|
|
11
11
|
};
|
|
12
|
-
export {};
|
|
13
12
|
//# sourceMappingURL=attributions-service.d.ts.map
|
|
@@ -1 +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,
|
|
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,oBAAY,eAAe;IACzB,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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { fetch, MondayFetchOptions } from '@mondaydotcomorg/monday-fetch';
|
|
2
2
|
import { OnRetryCallback, RetryPolicy } from '@mondaydotcomorg/monday-fetch-api';
|
|
3
|
+
import { IgniteClient } from '@mondaydotcomorg/ignite-sdk';
|
|
3
4
|
import { BaseRequest } from './types/general';
|
|
4
5
|
export declare const logger: import("bunyan");
|
|
5
6
|
export declare const onRetryCallback: OnRetryCallback;
|
|
6
7
|
export declare class AuthorizationInternalService {
|
|
8
|
+
static igniteClient?: IgniteClient;
|
|
7
9
|
static skipAuthorization(requset: BaseRequest): void;
|
|
8
10
|
static markAuthorized(request: BaseRequest): void;
|
|
9
11
|
static failIfNotCoveredByAuthorization(request: BaseRequest): void;
|
|
@@ -12,7 +14,8 @@ export declare class AuthorizationInternalService {
|
|
|
12
14
|
static generateInternalAuthToken(accountId: number, userId: number): string;
|
|
13
15
|
static setRequestFetchOptions(customMondayFetchOptions: MondayFetchOptions): void;
|
|
14
16
|
static getRequestFetchOptions(): MondayFetchOptions;
|
|
15
|
-
static
|
|
17
|
+
static setIgniteClient(client: IgniteClient): void;
|
|
18
|
+
static getRequestTimeout(): number;
|
|
16
19
|
static getRetriesPolicy(): RetryPolicy;
|
|
17
20
|
}
|
|
18
21
|
//# 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,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;
|
|
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,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,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,YAAY,CAAC,EAAE,YAAY,CAAC;IACnC,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,eAAe,CAAC,MAAM,EAAE,YAAY;IAI3C,MAAM,CAAC,iBAAiB;IA2BxB,MAAM,CAAC,gBAAgB,IAAI,WAAW;CASvC"}
|
|
@@ -27,6 +27,7 @@ function logOnFetchFail(retriesLeft, error) {
|
|
|
27
27
|
}
|
|
28
28
|
let mondayFetchOptions = defaultMondayFetchOptions;
|
|
29
29
|
class AuthorizationInternalService {
|
|
30
|
+
static igniteClient;
|
|
30
31
|
static skipAuthorization(requset) {
|
|
31
32
|
requset.authorizationSkipPerformed = true;
|
|
32
33
|
}
|
|
@@ -62,9 +63,28 @@ class AuthorizationInternalService {
|
|
|
62
63
|
static getRequestFetchOptions() {
|
|
63
64
|
return mondayFetchOptions;
|
|
64
65
|
}
|
|
66
|
+
static setIgniteClient(client) {
|
|
67
|
+
this.igniteClient = client;
|
|
68
|
+
}
|
|
65
69
|
static getRequestTimeout() {
|
|
66
70
|
const isDevEnv = process.env.NODE_ENV === 'development';
|
|
67
|
-
|
|
71
|
+
const defaultTimeout = isDevEnv ? 60000 : 2000;
|
|
72
|
+
if (!this.igniteClient) {
|
|
73
|
+
return defaultTimeout;
|
|
74
|
+
}
|
|
75
|
+
const overrideTimeouts = this.igniteClient.configuration.getObjectValue('override-outgoing-request-timeout-ms', {});
|
|
76
|
+
try {
|
|
77
|
+
if (process.env.APP_NAME && process.env.APP_NAME in overrideTimeouts) {
|
|
78
|
+
return overrideTimeouts[process.env.APP_NAME];
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
return this.igniteClient.configuration.getNumberValue('outgoing-request-timeout-ms', defaultTimeout);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
logger.error({ tag: 'authorization-service', error, defaultTimeout }, 'Failed to get timeout from ignite configuration, returning default timeout');
|
|
86
|
+
return defaultTimeout;
|
|
87
|
+
}
|
|
68
88
|
}
|
|
69
89
|
static getRetriesPolicy() {
|
|
70
90
|
const fetchOptions = AuthorizationInternalService.getRequestFetchOptions();
|
|
@@ -28,23 +28,9 @@ export declare class AuthorizationService {
|
|
|
28
28
|
private static fetchIsUserGrantedWithFeature;
|
|
29
29
|
private static getCachedKeyName;
|
|
30
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;
|
|
31
|
+
private static getProfile;
|
|
38
32
|
static canActionInScopeMultiple(accountId: number, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
|
|
39
33
|
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;
|
|
48
34
|
private static isAuthorizedMultiple;
|
|
49
35
|
}
|
|
50
36
|
export declare function setRedisClient(client: any, grantedFeatureRedisExpirationInSeconds?: number): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../../src/authorization-service.ts"],"names":[],"mappings":"AAIA,OAAO,
|
|
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,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;AAY1C,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,OAAO,CAAC,MAAM,CAAC,UAAU;WAsBZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBAkEnB,oBAAoB;mBAUpB,oBAAoB;CAmF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
|
|
@@ -2,17 +2,19 @@ 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 { fetch } from '@mondaydotcomorg/monday-fetch';
|
|
6
5
|
import { Api } from '@mondaydotcomorg/trident-backend-api';
|
|
7
6
|
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
8
7
|
import { getIgniteClient } from '@mondaydotcomorg/ignite-sdk';
|
|
9
8
|
import { sendAuthorizationCheckResponseTimeMetric } from './prometheus-service.mjs';
|
|
10
9
|
import { AuthorizationInternalService, logger } from './authorization-internal-service.mjs';
|
|
11
|
-
import {
|
|
10
|
+
import { getProfile, PlatformProfile, getAttributionsFromApi } from './attributions-service.mjs';
|
|
12
11
|
|
|
13
12
|
const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
|
|
14
13
|
const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
|
|
15
14
|
const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
|
|
15
|
+
const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
|
|
16
|
+
const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
|
|
17
|
+
const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
|
|
16
18
|
function setRequestFetchOptions(customMondayFetchOptions) {
|
|
17
19
|
AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
|
|
18
20
|
}
|
|
@@ -67,61 +69,31 @@ class AuthorizationService {
|
|
|
67
69
|
const scopedActionResponseObjects = await this.canActionInScopeMultiple(accountId, userId, scopedActions);
|
|
68
70
|
return scopedActionResponseObjects[0].permit;
|
|
69
71
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
* @param accountId
|
|
73
|
-
* @param userId
|
|
74
|
-
* @param scopedActions
|
|
75
|
-
*/
|
|
76
|
-
static async canActionInScopeMultiple_withoutPlatformProfile(accountId, userId, scopedActions) {
|
|
77
|
-
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
78
|
-
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
79
|
-
return { ...scopedAction, scope: mapKeys(scopedAction.scope, (_, key) => snakeCase(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
80
|
-
});
|
|
81
|
-
const attributionHeaders = getAttributionsFromApi();
|
|
82
|
-
const response = await fetch(getCanActionsInScopesUrl(), {
|
|
83
|
-
method: 'POST',
|
|
84
|
-
headers: {
|
|
85
|
-
Authorization: internalAuthToken,
|
|
86
|
-
'Content-Type': 'application/json',
|
|
87
|
-
...attributionHeaders,
|
|
88
|
-
},
|
|
89
|
-
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
90
|
-
body: JSON.stringify({
|
|
91
|
-
user_id: userId,
|
|
92
|
-
scoped_actions: scopedActionsPayload,
|
|
93
|
-
}),
|
|
94
|
-
}, AuthorizationInternalService.getRequestFetchOptions());
|
|
95
|
-
AuthorizationInternalService.throwOnHttpErrorIfNeeded(response, 'canActionInScopeMultiple');
|
|
96
|
-
const responseBody = await response.json();
|
|
97
|
-
const camelCaseKeys = obj => Object.fromEntries(Object.entries(obj).map(([key, value]) => [camelCase(key), value]));
|
|
98
|
-
const scopedActionsResponseObjects = responseBody.result.map(responseObject => {
|
|
99
|
-
const { scopedAction, permit } = responseObject;
|
|
100
|
-
const { scope } = scopedAction;
|
|
101
|
-
const transformKeys = obj => camelCaseKeys(obj);
|
|
102
|
-
return {
|
|
103
|
-
...responseObject,
|
|
104
|
-
scopedAction: { ...scopedAction, scope: transformKeys(scope) },
|
|
105
|
-
permit: transformKeys(permit),
|
|
106
|
-
};
|
|
107
|
-
});
|
|
108
|
-
return scopedActionsResponseObjects;
|
|
109
|
-
}
|
|
110
|
-
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
111
|
-
// gradually release the new platform profile features
|
|
72
|
+
static getProfile(accountId, userId) {
|
|
73
|
+
const appName = process.env.APP_NAME ?? 'INVALID_APP_NAME';
|
|
112
74
|
if (!this.igniteClient) {
|
|
113
|
-
logger.
|
|
75
|
+
logger.error({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, failing request');
|
|
76
|
+
throw new Error('AuthorizationService: igniteClient is not set, failing request');
|
|
77
|
+
}
|
|
78
|
+
if (this.igniteClient.configuration.getObjectValue(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []).includes(appName)) {
|
|
79
|
+
return getProfile();
|
|
114
80
|
}
|
|
115
|
-
|
|
116
|
-
|
|
81
|
+
if (this.igniteClient.configuration
|
|
82
|
+
.getObjectValue(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, [])
|
|
83
|
+
.includes(appName) &&
|
|
84
|
+
this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId })) {
|
|
85
|
+
return getProfile();
|
|
117
86
|
}
|
|
87
|
+
return PlatformProfile.INTERNAL;
|
|
88
|
+
}
|
|
89
|
+
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
90
|
+
const profile = this.getProfile(accountId, userId);
|
|
118
91
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
119
92
|
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
120
93
|
return { ...scopedAction, scope: mapKeys(scopedAction.scope, (_, key) => snakeCase(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
121
94
|
});
|
|
122
95
|
const attributionHeaders = getAttributionsFromApi();
|
|
123
96
|
const httpClient = Api.getPart('httpClient');
|
|
124
|
-
const profile = getProfile();
|
|
125
97
|
let response;
|
|
126
98
|
try {
|
|
127
99
|
response = await httpClient.fetch({
|
|
@@ -175,67 +147,12 @@ class AuthorizationService {
|
|
|
175
147
|
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
176
148
|
return this.isAuthorizedMultiple(accountId, userId, authorizationObjects);
|
|
177
149
|
}
|
|
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) {
|
|
186
|
-
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
187
|
-
const startTime = performance.now();
|
|
188
|
-
const attributionHeaders = getAttributionsFromApi();
|
|
189
|
-
const response = await fetch(getAuthorizeUrl(), {
|
|
190
|
-
method: 'POST',
|
|
191
|
-
headers: {
|
|
192
|
-
Authorization: internalAuthToken,
|
|
193
|
-
'Content-Type': 'application/json',
|
|
194
|
-
...attributionHeaders,
|
|
195
|
-
},
|
|
196
|
-
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
197
|
-
body: JSON.stringify({
|
|
198
|
-
user_id: userId,
|
|
199
|
-
authorize_request_objects: authorizationRequestObjects,
|
|
200
|
-
}),
|
|
201
|
-
}, AuthorizationInternalService.getRequestFetchOptions());
|
|
202
|
-
const endTime = performance.now();
|
|
203
|
-
const time = endTime - startTime;
|
|
204
|
-
const responseStatus = response.status;
|
|
205
|
-
AuthorizationInternalService.throwOnHttpErrorIfNeeded(response, 'isAuthorizedMultiple');
|
|
206
|
-
const responseBody = await response.json();
|
|
207
|
-
const unauthorizedObjects = [];
|
|
208
|
-
responseBody.result.forEach(function (isAuthorized, index) {
|
|
209
|
-
const authorizationObject = authorizationRequestObjects[index];
|
|
210
|
-
if (!isAuthorized) {
|
|
211
|
-
unauthorizedObjects.push(authorizationObject);
|
|
212
|
-
}
|
|
213
|
-
sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, responseStatus, time);
|
|
214
|
-
});
|
|
215
|
-
if (unauthorizedObjects.length > 0) {
|
|
216
|
-
logger.info({
|
|
217
|
-
resources: JSON.stringify(unauthorizedObjects),
|
|
218
|
-
}, 'AuthorizationService: resource is unauthorized');
|
|
219
|
-
const unauthorizedIds = unauthorizedObjects
|
|
220
|
-
.filter(obj => !!obj.resource_id)
|
|
221
|
-
.map(obj => obj.resource_id);
|
|
222
|
-
return { isAuthorized: false, unauthorizedIds, unauthorizedObjects };
|
|
223
|
-
}
|
|
224
|
-
return { isAuthorized: true };
|
|
225
|
-
}
|
|
226
150
|
static async isAuthorizedMultiple(accountId, userId, authorizationRequestObjects) {
|
|
227
|
-
|
|
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
|
-
}
|
|
151
|
+
const profile = this.getProfile(accountId, userId);
|
|
234
152
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
235
153
|
const startTime = performance.now();
|
|
236
154
|
const attributionHeaders = getAttributionsFromApi();
|
|
237
155
|
const httpClient = Api.getPart('httpClient');
|
|
238
|
-
const profile = getProfile();
|
|
239
156
|
let response;
|
|
240
157
|
try {
|
|
241
158
|
response = await httpClient.fetch({
|
|
@@ -304,9 +221,11 @@ function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED
|
|
|
304
221
|
}
|
|
305
222
|
}
|
|
306
223
|
async function setIgniteClient() {
|
|
307
|
-
|
|
308
|
-
namespace: ['authorization'],
|
|
224
|
+
const igniteClient = await getIgniteClient({
|
|
225
|
+
namespace: ['authorization-sdk'],
|
|
309
226
|
});
|
|
227
|
+
AuthorizationService.igniteClient = igniteClient;
|
|
228
|
+
AuthorizationInternalService.setIgniteClient(igniteClient);
|
|
310
229
|
}
|
|
311
230
|
function createAuthorizationParams(resources, action) {
|
|
312
231
|
const params = {
|
|
@@ -324,11 +243,5 @@ function createAuthorizationParams(resources, action) {
|
|
|
324
243
|
};
|
|
325
244
|
return params;
|
|
326
245
|
}
|
|
327
|
-
function getAuthorizeUrl() {
|
|
328
|
-
return `${process.env.MONDAY_INTERNAL_URL}/internal_ms/authorization/authorize`;
|
|
329
|
-
}
|
|
330
|
-
function getCanActionsInScopesUrl() {
|
|
331
|
-
return `${process.env.MONDAY_INTERNAL_URL}/internal_ms/authorization/can_actions_in_scopes`;
|
|
332
|
-
}
|
|
333
246
|
|
|
334
247
|
export { AuthorizationService, createAuthorizationParams, setIgniteClient, setRedisClient, setRequestFetchOptions };
|