@mondaydotcomorg/monday-authorization 3.1.2-feature-bashanye-enhance-profile-selection-release-process.51e4fbf → 3.1.2

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,5 +1,5 @@
1
1
  import { Context, ExecutionContext } from '@mondaydotcomorg/trident-backend-api';
2
- export declare enum PlatformProfile {
2
+ declare enum PlatformProfile {
3
3
  API_INTERNAL = "api-internal",
4
4
  SLOW = "slow",
5
5
  INTERNAL = "internal"
@@ -9,4 +9,5 @@ export declare function getExecutionContext(context: Context): ExecutionContext;
9
9
  export declare function getAttributionsFromApi(): {
10
10
  [key: string]: string;
11
11
  };
12
+ export {};
12
13
  //# sourceMappingURL=attributions-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"attributions-service.d.ts","sourceRoot":"","sources":["../src/attributions-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAStF,oBAAY,eAAe;IACzB,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,QAAQ,aAAa;CACtB;AAED,wBAAgB,UAAU,oBAiBzB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAEtE;AAED,wBAAgB,sBAAsB,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAqClE"}
1
+ {"version":3,"file":"attributions-service.d.ts","sourceRoot":"","sources":["../src/attributions-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAStF,aAAK,eAAe;IAClB,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,QAAQ,aAAa;CACtB;AAED,wBAAgB,UAAU,oBAiBzB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAEtE;AAED,wBAAgB,sBAAsB,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAqClE"}
@@ -7,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
- exports.PlatformProfile = void 0;
10
+ var PlatformProfile;
11
11
  (function (PlatformProfile) {
12
12
  PlatformProfile["API_INTERNAL"] = "api-internal";
13
13
  PlatformProfile["SLOW"] = "slow";
14
14
  PlatformProfile["INTERNAL"] = "internal";
15
- })(exports.PlatformProfile || (exports.PlatformProfile = {}));
15
+ })(PlatformProfile || (PlatformProfile = {}));
16
16
  function getProfile() {
17
17
  const tridentContext = tridentBackendApi.Api.getPart('context');
18
18
  if (!tridentContext) {
19
- return exports.PlatformProfile.INTERNAL;
19
+ return PlatformProfile.INTERNAL;
20
20
  }
21
21
  const { mondayRequestSource } = getExecutionContext(tridentContext);
22
22
  switch (mondayRequestSource) {
23
23
  case 'api': {
24
- return exports.PlatformProfile.API_INTERNAL;
24
+ return PlatformProfile.API_INTERNAL;
25
25
  }
26
26
  case 'slow': {
27
- return exports.PlatformProfile.SLOW;
27
+ return PlatformProfile.SLOW;
28
28
  }
29
29
  default:
30
- return exports.PlatformProfile.INTERNAL;
30
+ return PlatformProfile.INTERNAL;
31
31
  }
32
32
  }
33
33
  function getExecutionContext(context) {
@@ -28,9 +28,23 @@ 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
- private static getProfile;
31
+ /**
32
+ * @deprecated - gradually phasing this out
33
+ * @param accountId
34
+ * @param userId
35
+ * @param scopedActions
36
+ */
37
+ private static canActionInScopeMultiple_withoutPlatformProfile;
32
38
  static canActionInScopeMultiple(accountId: number, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
33
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;
34
48
  private static isAuthorizedMultiple;
35
49
  }
36
50
  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,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"}
1
+ {"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../src/authorization-service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAG1E,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAQ1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAeD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B;;;;;OAKG;mBACkB,+CAA+C;WAgDvD,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBA4EnB,oBAAoB;IAUzC;;;;;;OAMG;mBACkB,2CAA2C;mBAiE3C,oBAAoB;CAiG1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAIpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
@@ -4,6 +4,7 @@ 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');
9
10
  const igniteSdk = require('@mondaydotcomorg/ignite-sdk');
@@ -20,9 +21,6 @@ const mapKeys__default = /*#__PURE__*/_interopDefault(mapKeys);
20
21
  const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
21
22
  const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
22
23
  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';
26
24
  function setRequestFetchOptions(customMondayFetchOptions) {
27
25
  authorizationInternalService.AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
28
26
  }
@@ -77,33 +75,61 @@ class AuthorizationService {
77
75
  const scopedActionResponseObjects = await this.canActionInScopeMultiple(accountId, userId, scopedActions);
78
76
  return scopedActionResponseObjects[0].permit;
79
77
  }
80
- static getProfile(accountId, userId) {
81
- const appName = process.env.APP_NAME ?? 'INVALID_APP_NAME';
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
+ }
118
+ static async canActionInScopeMultiple(accountId, userId, scopedActions) {
119
+ // gradually release the new platform profile features
82
120
  if (!this.igniteClient) {
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();
121
+ authorizationInternalService.logger.warn({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, using new platform profile feature');
90
122
  }
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();
123
+ else if (!this.igniteClient.isReleased('sdk-platform-profiles', { accountId, userId })) {
124
+ return AuthorizationService.canActionInScopeMultiple_withoutPlatformProfile(accountId, userId, scopedActions);
96
125
  }
97
- return attributionsService.PlatformProfile.INTERNAL;
98
- }
99
- static async canActionInScopeMultiple(accountId, userId, scopedActions) {
100
- const profile = this.getProfile(accountId, userId);
101
126
  const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
102
127
  const scopedActionsPayload = scopedActions.map(scopedAction => {
103
128
  return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
104
129
  });
105
130
  const attributionHeaders = attributionsService.getAttributionsFromApi();
106
131
  const httpClient = tridentBackendApi.Api.getPart('httpClient');
132
+ const profile = attributionsService.getProfile();
107
133
  let response;
108
134
  try {
109
135
  response = await httpClient.fetch({
@@ -157,12 +183,67 @@ class AuthorizationService {
157
183
  const { authorizationObjects } = createAuthorizationParams(resources, action);
158
184
  return this.isAuthorizedMultiple(accountId, userId, authorizationObjects);
159
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
+ }
160
234
  static async isAuthorizedMultiple(accountId, userId, authorizationRequestObjects) {
161
- const profile = this.getProfile(accountId, userId);
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
+ }
162
242
  const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
163
243
  const startTime = perf_hooks.performance.now();
164
244
  const attributionHeaders = attributionsService.getAttributionsFromApi();
165
245
  const httpClient = tridentBackendApi.Api.getPart('httpClient');
246
+ const profile = attributionsService.getProfile();
166
247
  let response;
167
248
  try {
168
249
  response = await httpClient.fetch({
@@ -232,7 +313,7 @@ function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED
232
313
  }
233
314
  async function setIgniteClient() {
234
315
  AuthorizationService.igniteClient = await igniteSdk.getIgniteClient({
235
- namespace: ['authorization-sdk'],
316
+ namespace: ['authorization'],
236
317
  });
237
318
  }
238
319
  function createAuthorizationParams(resources, action) {
@@ -251,6 +332,12 @@ function createAuthorizationParams(resources, action) {
251
332
  };
252
333
  return params;
253
334
  }
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
+ }
254
341
 
255
342
  exports.AuthorizationService = AuthorizationService;
256
343
  exports.createAuthorizationParams = createAuthorizationParams;
@@ -1,5 +1,5 @@
1
1
  import { Context, ExecutionContext } from '@mondaydotcomorg/trident-backend-api';
2
- export declare enum PlatformProfile {
2
+ declare enum PlatformProfile {
3
3
  API_INTERNAL = "api-internal",
4
4
  SLOW = "slow",
5
5
  INTERNAL = "internal"
@@ -9,4 +9,5 @@ export declare function getExecutionContext(context: Context): ExecutionContext;
9
9
  export declare function getAttributionsFromApi(): {
10
10
  [key: string]: string;
11
11
  };
12
+ export {};
12
13
  //# sourceMappingURL=attributions-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"attributions-service.d.ts","sourceRoot":"","sources":["../../src/attributions-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAStF,oBAAY,eAAe;IACzB,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,QAAQ,aAAa;CACtB;AAED,wBAAgB,UAAU,oBAiBzB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAEtE;AAED,wBAAgB,sBAAsB,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAqClE"}
1
+ {"version":3,"file":"attributions-service.d.ts","sourceRoot":"","sources":["../../src/attributions-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAStF,aAAK,eAAe;IAClB,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,QAAQ,aAAa;CACtB;AAED,wBAAgB,UAAU,oBAiBzB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAEtE;AAED,wBAAgB,sBAAsB,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAqClE"}
@@ -76,4 +76,4 @@ function tryJsonParse(value) {
76
76
  }
77
77
  }
78
78
 
79
- export { PlatformProfile, getAttributionsFromApi, getExecutionContext, getProfile };
79
+ export { getAttributionsFromApi, getExecutionContext, getProfile };
@@ -28,9 +28,23 @@ 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
- private static getProfile;
31
+ /**
32
+ * @deprecated - gradually phasing this out
33
+ * @param accountId
34
+ * @param userId
35
+ * @param scopedActions
36
+ */
37
+ private static canActionInScopeMultiple_withoutPlatformProfile;
32
38
  static canActionInScopeMultiple(accountId: number, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
33
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;
34
48
  private static isAuthorizedMultiple;
35
49
  }
36
50
  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,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"}
1
+ {"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../../src/authorization-service.ts"],"names":[],"mappings":"AAIA,OAAO,EAAS,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAG1E,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAQ1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAeD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B;;;;;OAKG;mBACkB,+CAA+C;WAgDvD,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBA4EnB,oBAAoB;IAUzC;;;;;;OAMG;mBACkB,2CAA2C;mBAiE3C,oBAAoB;CAiG1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAIpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
@@ -2,19 +2,17 @@ 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';
7
8
  import { getIgniteClient } from '@mondaydotcomorg/ignite-sdk';
8
9
  import { sendAuthorizationCheckResponseTimeMetric } from './prometheus-service.mjs';
9
10
  import { AuthorizationInternalService, logger } from './authorization-internal-service.mjs';
10
- import { getProfile, PlatformProfile, getAttributionsFromApi } from './attributions-service.mjs';
11
+ import { getAttributionsFromApi, getProfile } from './attributions-service.mjs';
11
12
 
12
13
  const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
13
14
  const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
14
15
  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';
18
16
  function setRequestFetchOptions(customMondayFetchOptions) {
19
17
  AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
20
18
  }
@@ -69,33 +67,61 @@ class AuthorizationService {
69
67
  const scopedActionResponseObjects = await this.canActionInScopeMultiple(accountId, userId, scopedActions);
70
68
  return scopedActionResponseObjects[0].permit;
71
69
  }
72
- static getProfile(accountId, userId) {
73
- const appName = process.env.APP_NAME ?? 'INVALID_APP_NAME';
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
+ }
110
+ static async canActionInScopeMultiple(accountId, userId, scopedActions) {
111
+ // gradually release the new platform profile features
74
112
  if (!this.igniteClient) {
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();
113
+ logger.warn({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, using new platform profile feature');
82
114
  }
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();
115
+ else if (!this.igniteClient.isReleased('sdk-platform-profiles', { accountId, userId })) {
116
+ return AuthorizationService.canActionInScopeMultiple_withoutPlatformProfile(accountId, userId, scopedActions);
88
117
  }
89
- return PlatformProfile.INTERNAL;
90
- }
91
- static async canActionInScopeMultiple(accountId, userId, scopedActions) {
92
- const profile = this.getProfile(accountId, userId);
93
118
  const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
94
119
  const scopedActionsPayload = scopedActions.map(scopedAction => {
95
120
  return { ...scopedAction, scope: mapKeys(scopedAction.scope, (_, key) => snakeCase(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
96
121
  });
97
122
  const attributionHeaders = getAttributionsFromApi();
98
123
  const httpClient = Api.getPart('httpClient');
124
+ const profile = getProfile();
99
125
  let response;
100
126
  try {
101
127
  response = await httpClient.fetch({
@@ -149,12 +175,67 @@ class AuthorizationService {
149
175
  const { authorizationObjects } = createAuthorizationParams(resources, action);
150
176
  return this.isAuthorizedMultiple(accountId, userId, authorizationObjects);
151
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
+ }
152
226
  static async isAuthorizedMultiple(accountId, userId, authorizationRequestObjects) {
153
- const profile = this.getProfile(accountId, userId);
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
+ }
154
234
  const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
155
235
  const startTime = performance.now();
156
236
  const attributionHeaders = getAttributionsFromApi();
157
237
  const httpClient = Api.getPart('httpClient');
238
+ const profile = getProfile();
158
239
  let response;
159
240
  try {
160
241
  response = await httpClient.fetch({
@@ -224,7 +305,7 @@ function setRedisClient(client, grantedFeatureRedisExpirationInSeconds = GRANTED
224
305
  }
225
306
  async function setIgniteClient() {
226
307
  AuthorizationService.igniteClient = await getIgniteClient({
227
- namespace: ['authorization-sdk'],
308
+ namespace: ['authorization'],
228
309
  });
229
310
  }
230
311
  function createAuthorizationParams(resources, action) {
@@ -243,5 +324,11 @@ function createAuthorizationParams(resources, action) {
243
324
  };
244
325
  return params;
245
326
  }
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
+ }
246
333
 
247
334
  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.2-feature-bashanye-enhance-profile-selection-release-process.51e4fbf",
3
+ "version": "3.1.2",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "BSD-3-Clause",