@mondaydotcomorg/monday-authorization 3.3.0-feature-bashanye-navigate-can-action-in-scope-to-graph-9e68432 → 3.3.0-feature-bashanye-navigate-can-action-in-scope-to-graph-7ce3f8a

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.
Files changed (37) hide show
  1. package/dist/authorization-service.d.ts +0 -8
  2. package/dist/authorization-service.d.ts.map +1 -1
  3. package/dist/authorization-service.js +12 -160
  4. package/dist/clients/graph-api.client.d.ts +24 -0
  5. package/dist/clients/graph-api.client.d.ts.map +1 -0
  6. package/dist/clients/graph-api.client.js +102 -0
  7. package/dist/clients/platform-api.client.d.ts +31 -0
  8. package/dist/clients/platform-api.client.d.ts.map +1 -0
  9. package/dist/clients/platform-api.client.js +86 -0
  10. package/dist/esm/authorization-service.d.ts +0 -8
  11. package/dist/esm/authorization-service.d.ts.map +1 -1
  12. package/dist/esm/authorization-service.mjs +13 -155
  13. package/dist/esm/clients/graph-api.client.d.ts +24 -0
  14. package/dist/esm/clients/graph-api.client.d.ts.map +1 -0
  15. package/dist/esm/clients/graph-api.client.mjs +100 -0
  16. package/dist/esm/clients/platform-api.client.d.ts +31 -0
  17. package/dist/esm/clients/platform-api.client.d.ts.map +1 -0
  18. package/dist/esm/clients/platform-api.client.mjs +84 -0
  19. package/dist/esm/prometheus-service.d.ts +3 -3
  20. package/dist/esm/prometheus-service.d.ts.map +1 -1
  21. package/dist/esm/prometheus-service.mjs +65 -3
  22. package/dist/esm/types/graph-api.types.d.ts +11 -0
  23. package/dist/esm/types/graph-api.types.d.ts.map +1 -0
  24. package/dist/esm/types/graph-api.types.mjs +1 -0
  25. package/dist/esm/utils/authorization.utils.d.ts +22 -0
  26. package/dist/esm/utils/authorization.utils.d.ts.map +1 -0
  27. package/dist/esm/utils/authorization.utils.mjs +39 -0
  28. package/dist/prometheus-service.d.ts +3 -3
  29. package/dist/prometheus-service.d.ts.map +1 -1
  30. package/dist/prometheus-service.js +65 -3
  31. package/dist/types/graph-api.types.d.ts +11 -0
  32. package/dist/types/graph-api.types.d.ts.map +1 -0
  33. package/dist/types/graph-api.types.js +1 -0
  34. package/dist/utils/authorization.utils.d.ts +22 -0
  35. package/dist/utils/authorization.utils.d.ts.map +1 -0
  36. package/dist/utils/authorization.utils.js +49 -0
  37. package/package.json +1 -1
@@ -30,14 +30,6 @@ export declare class AuthorizationService {
30
30
  static canActionInScope(accountId: number, userId: number, action: string, scope: ScopeOptions): Promise<ScopedActionPermit>;
31
31
  private static getProfile;
32
32
  static canActionInScopeMultiple(accountId: number, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
33
- private static buildScopedActionsPayload;
34
- private static scopeToResource;
35
- private static buildGraphRequestBody;
36
- private static fetchGraphIsAllowed;
37
- private static mapGraphResponse;
38
- private static fetchPlatformCanActions;
39
- private static toCamelCase;
40
- private static mapPlatformResponse;
41
33
  private static isAuthorizedSingular;
42
34
  private static isAuthorizedMultiple;
43
35
  }
@@ -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;AAO7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAc1C,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;AAsCD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;WAsBZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAyCxC,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAMxC,OAAO,CAAC,MAAM,CAAC,eAAe;IAmB9B,OAAO,CAAC,MAAM,CAAC,qBAAqB;mBAyBf,mBAAmB;IAwCxC,OAAO,CAAC,MAAM,CAAC,gBAAgB;mBAoBV,uBAAuB;IA2C5C,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO,CAAC,MAAM,CAAC,mBAAmB;mBAiBb,oBAAoB;mBAUpB,oBAAoB;CAoF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
1
+ {"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../src/authorization-service.ts"],"names":[],"mappings":"AACA,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;AAe1C,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;AAMD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;WAsBZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBAuCnB,oBAAoB;mBAUpB,oBAAoB;CAoF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
@@ -1,26 +1,18 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const perf_hooks = require('perf_hooks');
4
- const snakeCase = require('lodash/snakeCase.js');
5
- const camelCase = require('lodash/camelCase.js');
6
- const mapKeys = require('lodash/mapKeys.js');
7
4
  const tridentBackendApi = require('@mondaydotcomorg/trident-backend-api');
8
5
  const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
9
6
  const igniteSdk = require('@mondaydotcomorg/ignite-sdk');
10
7
  const prometheusService = require('./prometheus-service.js');
11
8
  const authorizationInternalService = require('./authorization-internal-service.js');
12
9
  const attributionsService = require('./attributions-service.js');
13
-
14
- const _interopDefault = e => e && e.__esModule ? e : { default: e };
15
-
16
- const snakeCase__default = /*#__PURE__*/_interopDefault(snakeCase);
17
- const camelCase__default = /*#__PURE__*/_interopDefault(camelCase);
18
- const mapKeys__default = /*#__PURE__*/_interopDefault(mapKeys);
10
+ const clients_graphApi_client = require('./clients/graph-api.client.js');
11
+ const clients_platformApi_client = require('./clients/platform-api.client.js');
12
+ const utils_authorization_utils = require('./utils/authorization.utils.js');
19
13
 
20
14
  const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
21
15
  const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
22
- const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
23
- const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
24
16
  const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
25
17
  const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
26
18
  const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
@@ -102,166 +94,26 @@ class AuthorizationService {
102
94
  const startTime = perf_hooks.performance.now();
103
95
  let scopedActionResponseObjects;
104
96
  if (shouldNavigateToGraph) {
105
- const response = await this.fetchGraphIsAllowed(internalAuthToken, scopedActions);
106
- scopedActionResponseObjects = this.mapGraphResponse(scopedActions, userId, response);
97
+ scopedActionResponseObjects = await clients_graphApi_client.GraphApiClient.checkPermissions(internalAuthToken, scopedActions);
107
98
  }
108
99
  else {
109
100
  const profile = this.getProfile(accountId, userId);
110
- const scopedActionsPayload = this.buildScopedActionsPayload(scopedActions);
111
- const platformResponse = await this.fetchPlatformCanActions(profile, internalAuthToken, userId, scopedActionsPayload);
112
- scopedActionResponseObjects = this.mapPlatformResponse(platformResponse);
101
+ scopedActionResponseObjects = await clients_platformApi_client.PlatformApiClient.checkPermissions(profile, internalAuthToken, userId, scopedActions);
113
102
  }
114
103
  const endTime = perf_hooks.performance.now();
115
104
  const time = endTime - startTime;
116
105
  const apiType = shouldNavigateToGraph ? 'graph' : 'platform';
106
+ // Record metrics for each authorization check
117
107
  for (const obj of scopedActionResponseObjects) {
118
- const { action } = obj.scopedAction;
119
- const resource_type = this.scopeToResource(obj.scopedAction.scope).resourceType;
108
+ const { action, scope } = obj.scopedAction;
109
+ const { resourceType } = utils_authorization_utils.scopeToResource(scope);
120
110
  const isAuthorized = obj.permit.can;
121
- prometheusService.sendAuthorizationCheckResponseTimeMetric(resource_type, action, isAuthorized, 200, time, apiType);
122
- if (obj.permit.can) ;
123
- }
124
- return scopedActionResponseObjects;
125
- }
126
- static buildScopedActionsPayload(scopedActions) {
127
- return scopedActions.map(scopedAction => {
128
- return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) };
129
- });
130
- }
131
- static scopeToResource(scope) {
132
- if ('workspaceId' in scope) {
133
- return { resourceType: 'workspace', resourceId: scope.workspaceId };
134
- }
135
- if ('boardId' in scope) {
136
- return { resourceType: 'board', resourceId: scope.boardId };
137
- }
138
- if ('pulseId' in scope) {
139
- return { resourceType: 'pulse', resourceId: scope.pulseId };
140
- }
141
- if ('accountProductId' in scope) {
142
- return { resourceType: 'account_product', resourceId: scope.accountProductId };
143
- }
144
- if ('accountId' in scope) {
145
- return { resourceType: 'account', resourceId: scope.accountId };
146
- }
147
- throw new Error('Unsupported scope provided');
148
- }
149
- static buildGraphRequestBody(scopedActions) {
150
- const resourcesAccumulator = {};
151
- for (const { action, scope } of scopedActions) {
152
- const { resourceType, resourceId } = this.scopeToResource(scope);
153
- if (!resourcesAccumulator[resourceType]) {
154
- resourcesAccumulator[resourceType] = {};
155
- }
156
- if (!resourcesAccumulator[resourceType][resourceId]) {
157
- resourcesAccumulator[resourceType][resourceId] = new Set();
158
- }
159
- resourcesAccumulator[resourceType][resourceId].add(action);
160
- }
161
- const resourcesPayload = {};
162
- for (const [resourceType, idMap] of Object.entries(resourcesAccumulator)) {
163
- resourcesPayload[resourceType] = {};
164
- for (const [idStr, actionsSet] of Object.entries(idMap)) {
165
- const idNum = Number(idStr);
166
- resourcesPayload[resourceType][idNum] = Array.from(actionsSet);
167
- }
168
- }
169
- return resourcesPayload;
170
- }
171
- static async fetchGraphIsAllowed(internalAuthToken, scopedActions) {
172
- const httpClient = tridentBackendApi.Api.getPart('httpClient');
173
- const attributionHeaders = attributionsService.getAttributionsFromApi();
174
- const bodyPayload = this.buildGraphRequestBody(scopedActions);
175
- try {
176
- const response = await httpClient.fetch({
177
- url: {
178
- appName: 'authorization-graph',
179
- path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
180
- },
181
- method: 'POST',
182
- headers: {
183
- Authorization: internalAuthToken,
184
- 'Content-Type': 'application/json',
185
- ...attributionHeaders,
186
- },
187
- body: JSON.stringify(bodyPayload),
188
- }, {
189
- timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
190
- retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
191
- });
192
- prometheusService.setGraphAvailability(true);
193
- return response;
194
- }
195
- catch (err) {
196
- if (err instanceof mondayFetchApi.HttpFetcherError) {
197
- authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
198
- prometheusService.incrementAuthorizationError(this.scopeToResource(scopedActions[0].scope).resourceType, scopedActions[0].action, err.status);
199
- }
200
- throw err;
201
- }
202
- }
203
- static mapGraphResponse(scopedActions, userId, graphResponse) {
204
- const resources = graphResponse ?? {};
205
- return scopedActions.map(scopedAction => {
206
- const { action, scope } = scopedAction;
207
- const { resourceType, resourceId } = this.scopeToResource(scope);
208
- const permissionResult = resources?.[resourceType]?.[String(resourceId)]?.[action];
209
- const permit = {
210
- can: permissionResult?.can ?? false,
211
- reason: { key: permissionResult?.reason ?? 'unknown' },
212
- technicalReason: 0,
213
- };
214
- return { scopedAction, permit };
215
- });
216
- }
217
- static async fetchPlatformCanActions(profile, internalAuthToken, userId, scopedActionsPayload) {
218
- const attributionHeaders = attributionsService.getAttributionsFromApi();
219
- const httpClient = tridentBackendApi.Api.getPart('httpClient');
220
- try {
221
- const response = await httpClient.fetch({
222
- url: {
223
- appName: 'platform',
224
- path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
225
- profile,
226
- },
227
- method: 'POST',
228
- headers: {
229
- Authorization: internalAuthToken,
230
- 'Content-Type': 'application/json',
231
- ...attributionHeaders,
232
- },
233
- body: JSON.stringify({ user_id: userId, scoped_actions: scopedActionsPayload }),
234
- }, {
235
- timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
236
- retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
237
- });
238
- return response;
239
- }
240
- catch (err) {
241
- if (err instanceof mondayFetchApi.HttpFetcherError) {
242
- authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
243
- prometheusService.incrementAuthorizationError(this.scopeToResource(this.toCamelCase(scopedActionsPayload[0].scope)).resourceType, scopedActionsPayload[0].action, err.status);
111
+ prometheusService.sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time, apiType);
112
+ if (obj.permit.can) {
113
+ prometheusService.incrementAuthorizationSuccess(resourceType, action);
244
114
  }
245
- throw err;
246
115
  }
247
- }
248
- static toCamelCase(obj) {
249
- return mapKeys__default.default(obj, (_, key) => camelCase__default.default(key));
250
- }
251
- static mapPlatformResponse(response) {
252
- if (!response) {
253
- authorizationInternalService.logger.error({ tag: 'authorization-service', response }, 'AuthorizationService: missing response');
254
- throw new Error('AuthorizationService: missing response');
255
- }
256
- return response.result.map(responseObject => {
257
- const { scopedAction, permit } = responseObject;
258
- const { scope } = scopedAction;
259
- return {
260
- ...responseObject,
261
- scopedAction: { ...scopedAction, scope: this.toCamelCase(scope) },
262
- permit: this.toCamelCase(permit),
263
- };
264
- });
116
+ return scopedActionResponseObjects;
265
117
  }
266
118
  static async isAuthorizedSingular(accountId, userId, resources, action) {
267
119
  const { authorizationObjects } = createAuthorizationParams(resources, action);
@@ -0,0 +1,24 @@
1
+ import { ScopedAction, ScopedActionResponseObject } from '../types/scoped-actions-contracts';
2
+ import { GraphIsAllowedDto, GraphIsAllowedResponse } from '../types/graph-api.types';
3
+ /**
4
+ * Client for handling Graph API authorization operations
5
+ */
6
+ export declare class GraphApiClient {
7
+ /**
8
+ * Builds the request body for Graph API calls
9
+ */
10
+ static buildRequestBody(scopedActions: ScopedAction[]): GraphIsAllowedDto;
11
+ /**
12
+ * Fetches authorization data from the Graph API
13
+ */
14
+ static fetchPermissions(internalAuthToken: string, scopedActions: ScopedAction[]): Promise<GraphIsAllowedResponse>;
15
+ /**
16
+ * Maps Graph API response to the expected format
17
+ */
18
+ static mapResponse(scopedActions: ScopedAction[], graphResponse: GraphIsAllowedResponse): ScopedActionResponseObject[];
19
+ /**
20
+ * Performs a complete authorization check using the Graph API
21
+ */
22
+ static checkPermissions(internalAuthToken: string, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
23
+ }
24
+ //# sourceMappingURL=graph-api.client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-api.client.d.ts","sourceRoot":"","sources":["../../src/clients/graph-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAsB,MAAM,mCAAmC,CAAC;AAGjH,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EAIvB,MAAM,0BAA0B,CAAC;AAMlC;;GAEG;AACH,qBAAa,cAAc;IACzB;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,iBAAiB;IAyBzE;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,sBAAsB,CAAC;IAyClC;;OAEG;IACH,MAAM,CAAC,WAAW,CAChB,aAAa,EAAE,YAAY,EAAE,EAC7B,aAAa,EAAE,sBAAsB,GACpC,0BAA0B,EAAE;IAkB/B;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAIzC"}
@@ -0,0 +1,102 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const tridentBackendApi = require('@mondaydotcomorg/trident-backend-api');
4
+ const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
5
+ const authorizationInternalService = require('../authorization-internal-service.js');
6
+ const attributionsService = require('../attributions-service.js');
7
+ const utils_authorization_utils = require('../utils/authorization.utils.js');
8
+ const prometheusService = require('../prometheus-service.js');
9
+
10
+ const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
11
+ /**
12
+ * Client for handling Graph API authorization operations
13
+ */
14
+ class GraphApiClient {
15
+ /**
16
+ * Builds the request body for Graph API calls
17
+ */
18
+ static buildRequestBody(scopedActions) {
19
+ const resourcesAccumulator = {};
20
+ for (const { action, scope } of scopedActions) {
21
+ const { resourceType, resourceId } = utils_authorization_utils.scopeToResource(scope);
22
+ if (!resourcesAccumulator[resourceType]) {
23
+ resourcesAccumulator[resourceType] = {};
24
+ }
25
+ if (!resourcesAccumulator[resourceType][resourceId]) {
26
+ resourcesAccumulator[resourceType][resourceId] = new Set();
27
+ }
28
+ resourcesAccumulator[resourceType][resourceId].add(action);
29
+ }
30
+ const resourcesPayload = {};
31
+ for (const [resourceType, idMap] of Object.entries(resourcesAccumulator)) {
32
+ resourcesPayload[resourceType] = {};
33
+ for (const [idStr, actionsSet] of Object.entries(idMap)) {
34
+ const idNum = Number(idStr);
35
+ resourcesPayload[resourceType][idNum] = Array.from(actionsSet);
36
+ }
37
+ }
38
+ return resourcesPayload;
39
+ }
40
+ /**
41
+ * Fetches authorization data from the Graph API
42
+ */
43
+ static async fetchPermissions(internalAuthToken, scopedActions) {
44
+ const httpClient = tridentBackendApi.Api.getPart('httpClient');
45
+ const attributionHeaders = attributionsService.getAttributionsFromApi();
46
+ const bodyPayload = this.buildRequestBody(scopedActions);
47
+ try {
48
+ const response = await httpClient.fetch({
49
+ url: {
50
+ appName: 'authorization-graph',
51
+ path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
52
+ },
53
+ method: 'POST',
54
+ headers: {
55
+ Authorization: internalAuthToken,
56
+ 'Content-Type': 'application/json',
57
+ ...attributionHeaders,
58
+ },
59
+ body: JSON.stringify(bodyPayload),
60
+ }, {
61
+ timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
62
+ retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
63
+ });
64
+ prometheusService.setGraphAvailability(true);
65
+ return response;
66
+ }
67
+ catch (err) {
68
+ prometheusService.setGraphAvailability(false);
69
+ if (err instanceof mondayFetchApi.HttpFetcherError) {
70
+ authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
71
+ prometheusService.incrementAuthorizationError(utils_authorization_utils.scopeToResource(scopedActions[0].scope).resourceType, scopedActions[0].action, err.status);
72
+ }
73
+ throw err;
74
+ }
75
+ }
76
+ /**
77
+ * Maps Graph API response to the expected format
78
+ */
79
+ static mapResponse(scopedActions, graphResponse) {
80
+ const resources = graphResponse ?? {};
81
+ return scopedActions.map(scopedAction => {
82
+ const { action, scope } = scopedAction;
83
+ const { resourceType, resourceId } = utils_authorization_utils.scopeToResource(scope);
84
+ const permissionResult = resources?.[resourceType]?.[String(resourceId)]?.[action];
85
+ const permit = {
86
+ can: permissionResult?.can ?? false,
87
+ reason: { key: permissionResult?.reason ?? 'unknown' },
88
+ technicalReason: 0,
89
+ };
90
+ return { scopedAction, permit };
91
+ });
92
+ }
93
+ /**
94
+ * Performs a complete authorization check using the Graph API
95
+ */
96
+ static async checkPermissions(internalAuthToken, scopedActions) {
97
+ const response = await this.fetchPermissions(internalAuthToken, scopedActions);
98
+ return this.mapResponse(scopedActions, response);
99
+ }
100
+ }
101
+
102
+ exports.GraphApiClient = GraphApiClient;
@@ -0,0 +1,31 @@
1
+ import { ScopedAction, ScopedActionResponseObject } from '../types/scoped-actions-contracts';
2
+ import { PlatformProfile } from '../attributions-service';
3
+ type ScopedActionPlatformPayload = Omit<ScopedAction, 'scope'> & {
4
+ scope: Record<string, number>;
5
+ };
6
+ interface CanActionsInScopesResponse {
7
+ result: ScopedActionResponseObject[];
8
+ }
9
+ /**
10
+ * Client for handling Platform API authorization operations
11
+ */
12
+ export declare class PlatformApiClient {
13
+ /**
14
+ * Builds the request payload for Platform API calls
15
+ */
16
+ static buildRequestPayload(scopedActions: ScopedAction[]): ScopedActionPlatformPayload[];
17
+ /**
18
+ * Fetches authorization data from the Platform API
19
+ */
20
+ static fetchPermissions(profile: PlatformProfile, internalAuthToken: string, userId: number, scopedActionsPayload: ScopedActionPlatformPayload[]): Promise<CanActionsInScopesResponse>;
21
+ /**
22
+ * Maps Platform API response to the expected format
23
+ */
24
+ static mapResponse(response: CanActionsInScopesResponse): ScopedActionResponseObject[];
25
+ /**
26
+ * Performs a complete authorization check using the Platform API
27
+ */
28
+ static checkPermissions(profile: PlatformProfile, internalAuthToken: string, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
29
+ }
30
+ export {};
31
+ //# sourceMappingURL=platform-api.client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-api.client.d.ts","sourceRoot":"","sources":["../../src/clients/platform-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAE7F,OAAO,EAA0B,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAOlF,KAAK,2BAA2B,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF,UAAU,0BAA0B;IAClC,MAAM,EAAE,0BAA0B,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,2BAA2B,EAAE;IAOxF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,oBAAoB,EAAE,2BAA2B,EAAE,GAClD,OAAO,CAAC,0BAA0B,CAAC;IAuCtC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,0BAA0B,GAAG,0BAA0B,EAAE;IAkBtF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAKzC"}
@@ -0,0 +1,86 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const tridentBackendApi = require('@mondaydotcomorg/trident-backend-api');
4
+ const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
5
+ const authorizationInternalService = require('../authorization-internal-service.js');
6
+ const attributionsService = require('../attributions-service.js');
7
+ const utils_authorization_utils = require('../utils/authorization.utils.js');
8
+ const prometheusService = require('../prometheus-service.js');
9
+
10
+ const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
11
+ /**
12
+ * Client for handling Platform API authorization operations
13
+ */
14
+ class PlatformApiClient {
15
+ /**
16
+ * Builds the request payload for Platform API calls
17
+ */
18
+ static buildRequestPayload(scopedActions) {
19
+ return scopedActions.map(scopedAction => ({
20
+ ...scopedAction,
21
+ scope: utils_authorization_utils.toSnakeCase(scopedAction.scope),
22
+ }));
23
+ }
24
+ /**
25
+ * Fetches authorization data from the Platform API
26
+ */
27
+ static async fetchPermissions(profile, internalAuthToken, userId, scopedActionsPayload) {
28
+ const attributionHeaders = attributionsService.getAttributionsFromApi();
29
+ const httpClient = tridentBackendApi.Api.getPart('httpClient');
30
+ try {
31
+ const response = await httpClient.fetch({
32
+ url: {
33
+ appName: 'platform',
34
+ path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
35
+ profile,
36
+ },
37
+ method: 'POST',
38
+ headers: {
39
+ Authorization: internalAuthToken,
40
+ 'Content-Type': 'application/json',
41
+ ...attributionHeaders,
42
+ },
43
+ body: JSON.stringify({ user_id: userId, scoped_actions: scopedActionsPayload }),
44
+ }, {
45
+ timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
46
+ retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
47
+ });
48
+ return response;
49
+ }
50
+ catch (err) {
51
+ if (err instanceof mondayFetchApi.HttpFetcherError) {
52
+ authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
53
+ prometheusService.incrementAuthorizationError(utils_authorization_utils.scopeToResource(utils_authorization_utils.toCamelCase(scopedActionsPayload[0].scope)).resourceType, scopedActionsPayload[0].action, err.status);
54
+ }
55
+ throw err;
56
+ }
57
+ }
58
+ /**
59
+ * Maps Platform API response to the expected format
60
+ */
61
+ static mapResponse(response) {
62
+ if (!response) {
63
+ authorizationInternalService.logger.error({ tag: 'platform-api-client', response }, 'PlatformApiClient: missing response');
64
+ throw new Error('PlatformApiClient: missing response');
65
+ }
66
+ return response.result.map(responseObject => {
67
+ const { scopedAction, permit } = responseObject;
68
+ const { scope } = scopedAction;
69
+ return {
70
+ ...responseObject,
71
+ scopedAction: { ...scopedAction, scope: utils_authorization_utils.toCamelCase(scope) },
72
+ permit: utils_authorization_utils.toCamelCase(permit),
73
+ };
74
+ });
75
+ }
76
+ /**
77
+ * Performs a complete authorization check using the Platform API
78
+ */
79
+ static async checkPermissions(profile, internalAuthToken, userId, scopedActions) {
80
+ const scopedActionsPayload = this.buildRequestPayload(scopedActions);
81
+ const platformResponse = await this.fetchPermissions(profile, internalAuthToken, userId, scopedActionsPayload);
82
+ return this.mapResponse(platformResponse);
83
+ }
84
+ }
85
+
86
+ exports.PlatformApiClient = PlatformApiClient;
@@ -30,14 +30,6 @@ export declare class AuthorizationService {
30
30
  static canActionInScope(accountId: number, userId: number, action: string, scope: ScopeOptions): Promise<ScopedActionPermit>;
31
31
  private static getProfile;
32
32
  static canActionInScopeMultiple(accountId: number, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
33
- private static buildScopedActionsPayload;
34
- private static scopeToResource;
35
- private static buildGraphRequestBody;
36
- private static fetchGraphIsAllowed;
37
- private static mapGraphResponse;
38
- private static fetchPlatformCanActions;
39
- private static toCamelCase;
40
- private static mapPlatformResponse;
41
33
  private static isAuthorizedSingular;
42
34
  private static isAuthorizedMultiple;
43
35
  }
@@ -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;AAO7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAc1C,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;AAsCD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;WAsBZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAyCxC,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAMxC,OAAO,CAAC,MAAM,CAAC,eAAe;IAmB9B,OAAO,CAAC,MAAM,CAAC,qBAAqB;mBAyBf,mBAAmB;IAwCxC,OAAO,CAAC,MAAM,CAAC,gBAAgB;mBAoBV,uBAAuB;IA2C5C,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO,CAAC,MAAM,CAAC,mBAAmB;mBAiBb,oBAAoB;mBAUpB,oBAAoB;CAoF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
1
+ {"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../../src/authorization-service.ts"],"names":[],"mappings":"AACA,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;AAe1C,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;AAMD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;WAsBZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBAuCnB,oBAAoB;mBAUpB,oBAAoB;CAoF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}