@mondaydotcomorg/monday-authorization 3.1.1-feature-bashanye-fix-platform-url.d268e4c → 3.1.2-feature-bashanye-enhance-profile-selection-release-process.51e4fbf
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-service.d.ts +1 -15
- package/dist/authorization-service.d.ts.map +1 -1
- package/dist/authorization-service.js +23 -110
- 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-service.d.ts +1 -15
- package/dist/esm/authorization-service.d.ts.map +1 -1
- package/dist/esm/authorization-service.mjs +24 -111
- 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) {
|
|
@@ -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;WAwBZ,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,kBAIpC;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,33 @@ 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
|
|
87
|
+
.getObjectValue(ALLOWED_SDK_PLATFORM_PROFILES_KEY, [])
|
|
88
|
+
.includes(appName)) {
|
|
89
|
+
return attributionsService.getProfile();
|
|
122
90
|
}
|
|
123
|
-
|
|
124
|
-
|
|
91
|
+
if (this.igniteClient.configuration
|
|
92
|
+
.getObjectValue(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, [])
|
|
93
|
+
.includes(appName) &&
|
|
94
|
+
this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId })) {
|
|
95
|
+
return attributionsService.getProfile();
|
|
125
96
|
}
|
|
97
|
+
return attributionsService.PlatformProfile.INTERNAL;
|
|
98
|
+
}
|
|
99
|
+
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
100
|
+
const profile = this.getProfile(accountId, userId);
|
|
126
101
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
127
102
|
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
128
103
|
return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
129
104
|
});
|
|
130
105
|
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
131
106
|
const httpClient = tridentBackendApi.Api.getPart('httpClient');
|
|
132
|
-
const profile = attributionsService.getProfile();
|
|
133
107
|
let response;
|
|
134
108
|
try {
|
|
135
109
|
response = await httpClient.fetch({
|
|
@@ -183,67 +157,12 @@ class AuthorizationService {
|
|
|
183
157
|
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
184
158
|
return this.isAuthorizedMultiple(accountId, userId, authorizationObjects);
|
|
185
159
|
}
|
|
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
160
|
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
|
-
}
|
|
161
|
+
const profile = this.getProfile(accountId, userId);
|
|
242
162
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
243
163
|
const startTime = perf_hooks.performance.now();
|
|
244
164
|
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
245
165
|
const httpClient = tridentBackendApi.Api.getPart('httpClient');
|
|
246
|
-
const profile = attributionsService.getProfile();
|
|
247
166
|
let response;
|
|
248
167
|
try {
|
|
249
168
|
response = await httpClient.fetch({
|
|
@@ -313,7 +232,7 @@ function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED
|
|
|
313
232
|
}
|
|
314
233
|
async function setIgniteClient() {
|
|
315
234
|
AuthorizationService.igniteClient = await igniteSdk.getIgniteClient({
|
|
316
|
-
namespace: ['authorization'],
|
|
235
|
+
namespace: ['authorization-sdk'],
|
|
317
236
|
});
|
|
318
237
|
}
|
|
319
238
|
function createAuthorizationParams(resources, action) {
|
|
@@ -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"}
|
|
@@ -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;WAwBZ,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,kBAIpC;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,33 @@ 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
|
|
79
|
+
.getObjectValue(ALLOWED_SDK_PLATFORM_PROFILES_KEY, [])
|
|
80
|
+
.includes(appName)) {
|
|
81
|
+
return getProfile();
|
|
114
82
|
}
|
|
115
|
-
|
|
116
|
-
|
|
83
|
+
if (this.igniteClient.configuration
|
|
84
|
+
.getObjectValue(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, [])
|
|
85
|
+
.includes(appName) &&
|
|
86
|
+
this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId })) {
|
|
87
|
+
return getProfile();
|
|
117
88
|
}
|
|
89
|
+
return PlatformProfile.INTERNAL;
|
|
90
|
+
}
|
|
91
|
+
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
92
|
+
const profile = this.getProfile(accountId, userId);
|
|
118
93
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
119
94
|
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
120
95
|
return { ...scopedAction, scope: mapKeys(scopedAction.scope, (_, key) => snakeCase(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
121
96
|
});
|
|
122
97
|
const attributionHeaders = getAttributionsFromApi();
|
|
123
98
|
const httpClient = Api.getPart('httpClient');
|
|
124
|
-
const profile = getProfile();
|
|
125
99
|
let response;
|
|
126
100
|
try {
|
|
127
101
|
response = await httpClient.fetch({
|
|
@@ -175,67 +149,12 @@ class AuthorizationService {
|
|
|
175
149
|
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
176
150
|
return this.isAuthorizedMultiple(accountId, userId, authorizationObjects);
|
|
177
151
|
}
|
|
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
152
|
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
|
-
}
|
|
153
|
+
const profile = this.getProfile(accountId, userId);
|
|
234
154
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
235
155
|
const startTime = performance.now();
|
|
236
156
|
const attributionHeaders = getAttributionsFromApi();
|
|
237
157
|
const httpClient = Api.getPart('httpClient');
|
|
238
|
-
const profile = getProfile();
|
|
239
158
|
let response;
|
|
240
159
|
try {
|
|
241
160
|
response = await httpClient.fetch({
|
|
@@ -305,7 +224,7 @@ function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED
|
|
|
305
224
|
}
|
|
306
225
|
async function setIgniteClient() {
|
|
307
226
|
AuthorizationService.igniteClient = await getIgniteClient({
|
|
308
|
-
namespace: ['authorization'],
|
|
227
|
+
namespace: ['authorization-sdk'],
|
|
309
228
|
});
|
|
310
229
|
}
|
|
311
230
|
function createAuthorizationParams(resources, action) {
|
|
@@ -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 };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mondaydotcomorg/monday-authorization",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.2-feature-bashanye-enhance-profile-selection-release-process.51e4fbf",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "BSD-3-Clause",
|