@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.
@@ -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,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAuB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAQ1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAeD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IAEvD;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;WAMjB,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBAkEnB,oBAAoB;mBAUpB,oBAAoB;CAmF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F"}
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,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAuB,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAQ1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAeD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IAEvD;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;WAMjB,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBAkEnB,oBAAoB;mBAUpB,oBAAoB;CAmF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F"}
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 };
@@ -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';
@@ -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,wBAAgB,IAAI,CAAC,OAAO,GAAE,WAAgB,QAW7C;AAED,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC5G,OAAO,EACL,WAAW,EACX,YAAY,EACZ,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,CAAC"}
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"}
@@ -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';
@@ -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,wBAAgB,IAAI,CAAC,OAAO,GAAE,WAAgB,QAW7C;AAED,OAAO,EACL,4BAA4B,EAC5B,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC5G,OAAO,EACL,WAAW,EACX,YAAY,EACZ,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,CAAC"}
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.b83da61",
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",