@mondaydotcomorg/monday-authorization 1.2.19-incr-moshesa-upgrade-to-httpclient-and-use-profile--stubisauthorizedfetch.b83da61 → 1.2.19-incr-moshesa-upgrade-to-httpclient-and-use-profile--stubisauthorizedfetch.f3e1b8f
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/authorization-service.d.ts +18 -0
- package/dist/authorization-service.d.ts.map +1 -1
- package/dist/authorization-service.js +117 -0
- package/dist/esm/authorization-service.d.ts +18 -0
- package/dist/esm/authorization-service.d.ts.map +1 -1
- package/dist/esm/authorization-service.mjs +117 -1
- 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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/package.json +2 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MondayFetchOptions } from '@mondaydotcomorg/monday-fetch';
|
|
2
|
+
import { IgniteClient } from '@mondaydotcomorg/ignite-sdk';
|
|
2
3
|
import { Action, AuthorizationObject, Resource } from './types/general';
|
|
3
4
|
import { ScopedAction, ScopedActionPermit, ScopedActionResponseObject, ScopeOptions } from './types/scoped-actions-contracts';
|
|
4
5
|
export interface AuthorizeResponse {
|
|
@@ -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,25 @@ 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>;
|
|
34
52
|
//# 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,
|
|
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,EAAuB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAQ1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;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"}
|
|
@@ -4,8 +4,10 @@ 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');
|
|
7
8
|
const tridentBackendApi = require('@mondaydotcomorg/trident-backend-api');
|
|
8
9
|
const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
|
|
10
|
+
const igniteSdk = require('@mondaydotcomorg/ignite-sdk');
|
|
9
11
|
const prometheusService = require('./prometheus-service.js');
|
|
10
12
|
const authorizationInternalService = require('./authorization-internal-service.js');
|
|
11
13
|
const attributionsService = require('./attributions-service.js');
|
|
@@ -25,6 +27,7 @@ function setRequestFetchOptions(customMondayFetchOptions) {
|
|
|
25
27
|
class AuthorizationService {
|
|
26
28
|
static redisClient;
|
|
27
29
|
static grantedFeatureRedisExpirationInSeconds;
|
|
30
|
+
static igniteClient;
|
|
28
31
|
static async isAuthorized(...args) {
|
|
29
32
|
if (args.length === 3) {
|
|
30
33
|
return this.isAuthorizedMultiple(args[0], args[1], args[2]);
|
|
@@ -72,7 +75,54 @@ class AuthorizationService {
|
|
|
72
75
|
const scopedActionResponseObjects = await this.canActionInScopeMultiple(accountId, userId, scopedActions);
|
|
73
76
|
return scopedActionResponseObjects[0].permit;
|
|
74
77
|
}
|
|
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) {
|
|
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
|
+
}
|
|
75
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
|
+
}
|
|
76
126
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
77
127
|
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
78
128
|
return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
@@ -133,7 +183,62 @@ class AuthorizationService {
|
|
|
133
183
|
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
134
184
|
return this.isAuthorizedMultiple(accountId, userId, authorizationObjects);
|
|
135
185
|
}
|
|
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
|
+
}
|
|
136
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
|
+
}
|
|
137
242
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
138
243
|
const startTime = perf_hooks.performance.now();
|
|
139
244
|
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
@@ -206,6 +311,11 @@ function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED
|
|
|
206
311
|
AuthorizationService.grantedFeatureRedisExpirationInSeconds = GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS;
|
|
207
312
|
}
|
|
208
313
|
}
|
|
314
|
+
async function setIgniteClient() {
|
|
315
|
+
AuthorizationService.igniteClient = await igniteSdk.getIgniteClient({
|
|
316
|
+
namespace: ['authorization'],
|
|
317
|
+
});
|
|
318
|
+
}
|
|
209
319
|
function createAuthorizationParams(resources, action) {
|
|
210
320
|
const params = {
|
|
211
321
|
authorizationObjects: resources.map((resource) => {
|
|
@@ -222,7 +332,14 @@ function createAuthorizationParams(resources, action) {
|
|
|
222
332
|
};
|
|
223
333
|
return params;
|
|
224
334
|
}
|
|
335
|
+
function getAuthorizeUrl() {
|
|
336
|
+
return '/internal_ms/authorization/authorize';
|
|
337
|
+
}
|
|
338
|
+
function getCanActionsInScopesUrl() {
|
|
339
|
+
return '/internal_ms/authorization/can_actions_in_scopes';
|
|
340
|
+
}
|
|
225
341
|
|
|
226
342
|
exports.AuthorizationService = AuthorizationService;
|
|
343
|
+
exports.setIgniteClient = setIgniteClient;
|
|
227
344
|
exports.setRedisClient = setRedisClient;
|
|
228
345
|
exports.setRequestFetchOptions = setRequestFetchOptions;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MondayFetchOptions } from '@mondaydotcomorg/monday-fetch';
|
|
2
|
+
import { IgniteClient } from '@mondaydotcomorg/ignite-sdk';
|
|
2
3
|
import { Action, AuthorizationObject, Resource } from './types/general';
|
|
3
4
|
import { ScopedAction, ScopedActionPermit, ScopedActionResponseObject, ScopeOptions } from './types/scoped-actions-contracts';
|
|
4
5
|
export interface AuthorizeResponse {
|
|
@@ -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,25 @@ 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>;
|
|
34
52
|
//# 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,
|
|
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,EAAuB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAQ1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;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"}
|
|
@@ -2,8 +2,10 @@ 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';
|
|
5
6
|
import { Api } from '@mondaydotcomorg/trident-backend-api';
|
|
6
7
|
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
8
|
+
import { getIgniteClient } from '@mondaydotcomorg/ignite-sdk';
|
|
7
9
|
import { sendAuthorizationCheckResponseTimeMetric } from './prometheus-service.mjs';
|
|
8
10
|
import { AuthorizationInternalService, logger } from './authorization-internal-service.mjs';
|
|
9
11
|
import { getAttributionsFromApi, getProfile } from './attributions-service.mjs';
|
|
@@ -17,6 +19,7 @@ function setRequestFetchOptions(customMondayFetchOptions) {
|
|
|
17
19
|
class AuthorizationService {
|
|
18
20
|
static redisClient;
|
|
19
21
|
static grantedFeatureRedisExpirationInSeconds;
|
|
22
|
+
static igniteClient;
|
|
20
23
|
static async isAuthorized(...args) {
|
|
21
24
|
if (args.length === 3) {
|
|
22
25
|
return this.isAuthorizedMultiple(args[0], args[1], args[2]);
|
|
@@ -64,7 +67,54 @@ class AuthorizationService {
|
|
|
64
67
|
const scopedActionResponseObjects = await this.canActionInScopeMultiple(accountId, userId, scopedActions);
|
|
65
68
|
return scopedActionResponseObjects[0].permit;
|
|
66
69
|
}
|
|
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) {
|
|
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
|
+
}
|
|
67
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
|
+
}
|
|
68
118
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
69
119
|
const scopedActionsPayload = scopedActions.map(scopedAction => {
|
|
70
120
|
return { ...scopedAction, scope: mapKeys(scopedAction.scope, (_, key) => snakeCase(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
|
|
@@ -125,7 +175,62 @@ class AuthorizationService {
|
|
|
125
175
|
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
126
176
|
return this.isAuthorizedMultiple(accountId, userId, authorizationObjects);
|
|
127
177
|
}
|
|
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
|
+
}
|
|
128
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
|
+
}
|
|
129
234
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
130
235
|
const startTime = performance.now();
|
|
131
236
|
const attributionHeaders = getAttributionsFromApi();
|
|
@@ -198,6 +303,11 @@ function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED
|
|
|
198
303
|
AuthorizationService.grantedFeatureRedisExpirationInSeconds = GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS;
|
|
199
304
|
}
|
|
200
305
|
}
|
|
306
|
+
async function setIgniteClient() {
|
|
307
|
+
AuthorizationService.igniteClient = await getIgniteClient({
|
|
308
|
+
namespace: ['authorization'],
|
|
309
|
+
});
|
|
310
|
+
}
|
|
201
311
|
function createAuthorizationParams(resources, action) {
|
|
202
312
|
const params = {
|
|
203
313
|
authorizationObjects: resources.map((resource) => {
|
|
@@ -214,5 +324,11 @@ function createAuthorizationParams(resources, action) {
|
|
|
214
324
|
};
|
|
215
325
|
return params;
|
|
216
326
|
}
|
|
327
|
+
function getAuthorizeUrl() {
|
|
328
|
+
return '/internal_ms/authorization/authorize';
|
|
329
|
+
}
|
|
330
|
+
function getCanActionsInScopesUrl() {
|
|
331
|
+
return '/internal_ms/authorization/can_actions_in_scopes';
|
|
332
|
+
}
|
|
217
333
|
|
|
218
|
-
export { AuthorizationService, setRedisClient, setRequestFetchOptions };
|
|
334
|
+
export { AuthorizationService, 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 };
|
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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mondaydotcomorg/monday-authorization",
|
|
3
|
-
"version": "1.2.19-incr-moshesa-upgrade-to-httpclient-and-use-profile--stubisauthorizedfetch.
|
|
3
|
+
"version": "1.2.19-incr-moshesa-upgrade-to-httpclient-and-use-profile--stubisauthorizedfetch.f3e1b8f",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -19,6 +19,7 @@
|
|
|
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",
|
|
23
24
|
"@mondaydotcomorg/monday-fetch-api": "^1.0.2",
|
|
24
25
|
"@mondaydotcomorg/monday-jwt": "^3.0.14",
|