@mondaydotcomorg/monday-authorization 3.2.1 → 3.2.3-feature-bashanye-navigate-can-action-in-scope-to-graph-af77c6b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,46 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
+ and this project adheres to [Semantic Versioning](http://semver.org/).
7
+
8
+ ## [2.0.0] - 2025-04-07
9
+
10
+ ### ⚠ MAJOR CHANGE - PLEASE READ
11
+
12
+ ### Fixed
13
+
14
+ - Calls to the monolith will be spread across the different profiles - `api-internal`, `slow` and `internal` (originally, all the calls to the platform went directly to `monday-app`)
15
+
16
+ ## [1.2.9] - 2024-10-06
17
+
18
+ ### Added
19
+
20
+ - [`authz/bashanye/add-async-resource-attributes-support`](https://github.com/DaPulse/monday-npm-packages/pull/6859)
21
+ - `AuthorizationAttributesService` - now supports async upsert and delete - requests sent through SNS-SQS).
22
+
23
+ ## [1.2.3] - 2024-06-10
24
+
25
+ ### Added
26
+
27
+ - [`feature/yarden/resource-attributes-api-support-authz-sdk (#5826)`](https://github.com/DaPulse/monday-npm-packages/pull/5826)
28
+ - `AuthorizationAttributesService` - now supports upsert (`upsertResourceAttributesSync`) and delete (`deleteResourceAttributesSync`) resource attributes in the authorization MS
29
+
30
+ ## [1.2.0] - 2024-01-05
31
+
32
+ ### Added
33
+
34
+ - `isAuthorized` now return the unauthorized objects - regardless to the unauthorized ids (which may be missing resource ids if resource has no id, like `feature` e.g.)
35
+
36
+ ## [1.1.0] - 2023-08-09
37
+
38
+ ### ⚠ BREAKING CHANGES
39
+
40
+ - `canActionInScope` now returns an object of type `{ can: boolean; reason: string; }` instead of `boolean`.
41
+ This version is considered minor because no one uses this function yet.
42
+
43
+ ### Changed
44
+
45
+ - [`feature/idan/can-action-in-scope/change-behavior-on-error (#3689)`](https://github.com/DaPulse/monday-npm-packages/pull/3689)
46
+ - `canActionInScope`, `canActionInScopeMultiple` and `isAuthorized` are now throwing an error instead of returning `false` when an error occurs as part of the authorization http request (status code is not 2XX)
@@ -1 +1 @@
1
- {"version":3,"file":"authorization-attributes-service.d.ts","sourceRoot":"","sources":["../src/authorization-attributes-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,aAAa,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAEtF,OAAO,EAAoB,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,2BAA2B,EAC5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAW3C,qBAAa,8BAA8B;IACzC,OAAO,CAAC,MAAM,CAAC,OAAO,CAA8B;IACpD,OAAO,CAAC,MAAM,CAAC,SAAS,CAGb;IACX,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,MAAM,CAAS;IAEvB;;;;OAIG;gBACS,UAAU,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,gBAAgB,CAAC,aAAa,CAAC;IAqBnF;;;;;;OAMG;IACG,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,4BAA4B,EAAE,2BAA2B,EAAE,GAC1D,OAAO,CAAC,yBAAyB,CAAC;IA6BrC;;;;;;OAMG;IACG,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,yBAAyB,CAAC;IAkCrC;;;;;;;UAOM;IACA,6BAA6B,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,sBAAsB,EAAE,MAAM,EAC9B,2BAA2B,EAAE,2BAA2B,EAAE,GACzD,OAAO,CAAC,2BAA2B,EAAE,CAAC;YAY3B,oBAAoB;IA4BlC,OAAO,CAAC,MAAM,CAAC,cAAc;IAe7B;;;;;;;OAOG;IACG,kCAAkC,IAAI,OAAO,CAAC,OAAO,CAAC;CAoB7D"}
1
+ {"version":3,"file":"authorization-attributes-service.d.ts","sourceRoot":"","sources":["../src/authorization-attributes-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,aAAa,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAEtF,OAAO,EAAoB,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,2BAA2B,EAC5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAY3C,qBAAa,8BAA8B;IACzC,OAAO,CAAC,MAAM,CAAC,OAAO,CAA8B;IACpD,OAAO,CAAC,MAAM,CAAC,SAAS,CAGb;IACX,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,MAAM,CAAS;IAEvB;;;;OAIG;gBACS,UAAU,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,gBAAgB,CAAC,aAAa,CAAC;IAqBnF;;;;;;OAMG;IACG,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,4BAA4B,EAAE,2BAA2B,EAAE,GAC1D,OAAO,CAAC,yBAAyB,CAAC;IA6BrC;;;;;;OAMG;IACG,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,yBAAyB,CAAC;IAkCrC;;;;;;;UAOM;IACA,6BAA6B,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,sBAAsB,EAAE,MAAM,EAC9B,2BAA2B,EAAE,2BAA2B,EAAE,GACzD,OAAO,CAAC,2BAA2B,EAAE,CAAC;YAY3B,oBAAoB;IA4BlC,OAAO,CAAC,MAAM,CAAC,cAAc;IAW7B;;;;;;;OAOG;IACG,kCAAkC,IAAI,OAAO,CAAC,OAAO,CAAC;CAoB7D"}
@@ -149,15 +149,13 @@ class AuthorizationAttributesService {
149
149
  }
150
150
  }
151
151
  static getSnsTopicArn() {
152
- const arnFromApi = tridentBackendApi.Api.getPart('configurationVariables')?.get(constants_sns.RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME).arn;
153
- if (arnFromApi) {
154
- return arnFromApi;
155
- }
156
- const jsonArnFromEnv = process.env[constants_sns.RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME];
157
- const arnFromEnv = JSON.parse(jsonArnFromEnv).arn;
152
+ const arnFromEnv = process.env[constants_sns.SNS_ARN_ENV_VAR_NAME];
158
153
  if (arnFromEnv) {
159
154
  return arnFromEnv;
160
155
  }
156
+ if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
157
+ return constants_sns.SNS_DEV_TEST_NAME;
158
+ }
161
159
  throw new Error('Unable to get sns topic arn from env variable');
162
160
  }
163
161
  /**
@@ -30,6 +30,14 @@ 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;
33
41
  private static isAuthorizedSingular;
34
42
  private static isAuthorizedMultiple;
35
43
  }
@@ -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;WAsBZ,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,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":"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;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;AA6BD,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;IAsBxC,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAMxC,OAAO,CAAC,MAAM,CAAC,eAAe;IAmB9B,OAAO,CAAC,MAAM,CAAC,qBAAqB;mBAyBf,mBAAmB;IAoCxC,OAAO,CAAC,MAAM,CAAC,gBAAgB;mBAoBV,uBAAuB;IAsC5C,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO,CAAC,MAAM,CAAC,mBAAmB;mBAiBb,oBAAoB;mBAUpB,oBAAoB;CAmF1C;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"}
@@ -23,6 +23,8 @@ const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_acti
23
23
  const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
24
24
  const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
25
25
  const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
26
+ const NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF = 'navigate-can-action-in-scope-to-graph';
27
+ const GRAPH_IS_ALLOWED_PATH = '/permissions/is-allowed';
26
28
  function setRequestFetchOptions(customMondayFetchOptions) {
27
29
  authorizationInternalService.AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
28
30
  }
@@ -95,16 +97,111 @@ class AuthorizationService {
95
97
  return attributionsService.PlatformProfile.INTERNAL;
96
98
  }
97
99
  static async canActionInScopeMultiple(accountId, userId, scopedActions) {
98
- const profile = this.getProfile(accountId, userId);
100
+ const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
99
101
  const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
100
- const scopedActionsPayload = scopedActions.map(scopedAction => {
101
- return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
102
+ if (shouldNavigateToGraph) {
103
+ const response = await this.fetchGraphIsAllowed(internalAuthToken, scopedActions);
104
+ return this.mapGraphResponse(scopedActions, userId, response);
105
+ }
106
+ const profile = this.getProfile(accountId, userId);
107
+ const scopedActionsPayload = this.buildScopedActionsPayload(scopedActions);
108
+ const platformResponse = await this.fetchPlatformCanActions(profile, internalAuthToken, userId, scopedActionsPayload);
109
+ return this.mapPlatformResponse(platformResponse);
110
+ }
111
+ static buildScopedActionsPayload(scopedActions) {
112
+ return scopedActions.map(scopedAction => {
113
+ return { ...scopedAction, scope: mapKeys__default.default(scopedAction.scope, (_, key) => snakeCase__default.default(key)) };
102
114
  });
115
+ }
116
+ static scopeToResource(scope) {
117
+ if ('workspaceId' in scope) {
118
+ return { resourceType: 'workspace', resourceId: scope.workspaceId };
119
+ }
120
+ if ('boardId' in scope) {
121
+ return { resourceType: 'board', resourceId: scope.boardId };
122
+ }
123
+ if ('pulseId' in scope) {
124
+ return { resourceType: 'pulse', resourceId: scope.pulseId };
125
+ }
126
+ if ('accountProductId' in scope) {
127
+ return { resourceType: 'account_product', resourceId: scope.accountProductId };
128
+ }
129
+ if ('accountId' in scope) {
130
+ return { resourceType: 'account', resourceId: scope.accountId };
131
+ }
132
+ throw new Error('Unsupported scope provided');
133
+ }
134
+ static buildGraphRequestBody(scopedActions) {
135
+ const resourcesAccumulator = {};
136
+ for (const { action, scope } of scopedActions) {
137
+ const { resourceType, resourceId } = this.scopeToResource(scope);
138
+ if (!resourcesAccumulator[resourceType]) {
139
+ resourcesAccumulator[resourceType] = {};
140
+ }
141
+ if (!resourcesAccumulator[resourceType][resourceId]) {
142
+ resourcesAccumulator[resourceType][resourceId] = new Set();
143
+ }
144
+ resourcesAccumulator[resourceType][resourceId].add(action);
145
+ }
146
+ const resourcesPayload = {};
147
+ for (const [resourceType, idMap] of Object.entries(resourcesAccumulator)) {
148
+ resourcesPayload[resourceType] = {};
149
+ for (const [idStr, actionsSet] of Object.entries(idMap)) {
150
+ const idNum = Number(idStr);
151
+ resourcesPayload[resourceType][idNum] = Array.from(actionsSet);
152
+ }
153
+ }
154
+ return resourcesPayload;
155
+ }
156
+ static async fetchGraphIsAllowed(internalAuthToken, scopedActions) {
157
+ const httpClient = tridentBackendApi.Api.getPart('httpClient');
158
+ const attributionHeaders = attributionsService.getAttributionsFromApi();
159
+ const bodyPayload = this.buildGraphRequestBody(scopedActions);
160
+ try {
161
+ const response = await httpClient.fetch({
162
+ url: {
163
+ appName: 'authorization-graph',
164
+ path: GRAPH_IS_ALLOWED_PATH,
165
+ },
166
+ method: 'POST',
167
+ headers: {
168
+ Authorization: internalAuthToken,
169
+ 'Content-Type': 'application/json',
170
+ ...attributionHeaders,
171
+ },
172
+ body: JSON.stringify(bodyPayload),
173
+ }, {
174
+ timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
175
+ retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
176
+ });
177
+ return response;
178
+ }
179
+ catch (err) {
180
+ if (err instanceof mondayFetchApi.HttpFetcherError) {
181
+ authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
182
+ }
183
+ throw err;
184
+ }
185
+ }
186
+ static mapGraphResponse(scopedActions, userId, graphResponse) {
187
+ const resources = graphResponse ?? {};
188
+ return scopedActions.map(scopedAction => {
189
+ const { action, scope } = scopedAction;
190
+ const { resourceType, resourceId } = this.scopeToResource(scope);
191
+ const permissionResult = resources?.[resourceType]?.[String(resourceId)]?.[action];
192
+ const permit = {
193
+ can: permissionResult?.can ?? false,
194
+ reason: { key: permissionResult?.reason ?? 'unknown' },
195
+ technicalReason: 0,
196
+ };
197
+ return { scopedAction, permit };
198
+ });
199
+ }
200
+ static async fetchPlatformCanActions(profile, internalAuthToken, userId, scopedActionsPayload) {
103
201
  const attributionHeaders = attributionsService.getAttributionsFromApi();
104
202
  const httpClient = tridentBackendApi.Api.getPart('httpClient');
105
- let response;
106
203
  try {
107
- response = await httpClient.fetch({
204
+ const response = await httpClient.fetch({
108
205
  url: {
109
206
  appName: 'platform',
110
207
  path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
@@ -116,40 +213,37 @@ class AuthorizationService {
116
213
  'Content-Type': 'application/json',
117
214
  ...attributionHeaders,
118
215
  },
119
- body: JSON.stringify({
120
- user_id: userId,
121
- scoped_actions: scopedActionsPayload,
122
- }),
216
+ body: JSON.stringify({ user_id: userId, scoped_actions: scopedActionsPayload }),
123
217
  }, {
124
218
  timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
125
219
  retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
126
220
  });
221
+ return response;
127
222
  }
128
223
  catch (err) {
129
224
  if (err instanceof mondayFetchApi.HttpFetcherError) {
130
225
  authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
131
226
  }
132
- else {
133
- throw err;
134
- }
135
- }
136
- function toCamelCase(obj) {
137
- return mapKeys__default.default(obj, (_, key) => camelCase__default.default(key));
227
+ throw err;
138
228
  }
229
+ }
230
+ static toCamelCase(obj) {
231
+ return mapKeys__default.default(obj, (_, key) => camelCase__default.default(key));
232
+ }
233
+ static mapPlatformResponse(response) {
139
234
  if (!response) {
140
235
  authorizationInternalService.logger.error({ tag: 'authorization-service', response }, 'AuthorizationService: missing response');
141
236
  throw new Error('AuthorizationService: missing response');
142
237
  }
143
- const scopedActionsResponseObjects = response.result.map(responseObject => {
238
+ return response.result.map(responseObject => {
144
239
  const { scopedAction, permit } = responseObject;
145
240
  const { scope } = scopedAction;
146
241
  return {
147
242
  ...responseObject,
148
- scopedAction: { ...scopedAction, scope: toCamelCase(scope) },
149
- permit: toCamelCase(permit),
243
+ scopedAction: { ...scopedAction, scope: this.toCamelCase(scope) },
244
+ permit: this.toCamelCase(permit),
150
245
  };
151
246
  });
152
- return scopedActionsResponseObjects;
153
247
  }
154
248
  static async isAuthorizedSingular(accountId, userId, resources, action) {
155
249
  const { authorizationObjects } = createAuthorizationParams(resources, action);
@@ -1,4 +1,5 @@
1
- export declare const RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME = "AUTHORIZATION_RESOURCE_ATTRIBUTES_SNS_TOPIC";
1
+ export declare const SNS_ARN_ENV_VAR_NAME = "SHARED_AUTHORIZATION_SNS_ENDPOINT_RESOURCE_ATTRIBUTES";
2
+ export declare const SNS_DEV_TEST_NAME = "arn:aws:sns:us-east-1:000000000000:monday-authorization-resource-attributes-sns-local";
2
3
  export declare const RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND = "resourceAttributeModification";
3
4
  export declare const ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE = 100;
4
5
  //# sourceMappingURL=sns.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sns.d.ts","sourceRoot":"","sources":["../../src/constants/sns.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uCAAuC,gDAAgD,CAAC;AACrG,eAAO,MAAM,qDAAqD,kCAAkC,CAAC;AACrG,eAAO,MAAM,oDAAoD,MAAM,CAAC"}
1
+ {"version":3,"file":"sns.d.ts","sourceRoot":"","sources":["../../src/constants/sns.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,0DAA0D,CAAC;AAC5F,eAAO,MAAM,iBAAiB,0FAC2D,CAAC;AAC1F,eAAO,MAAM,qDAAqD,kCAAkC,CAAC;AACrG,eAAO,MAAM,oDAAoD,MAAM,CAAC"}
@@ -1,9 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
- const RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME = 'AUTHORIZATION_RESOURCE_ATTRIBUTES_SNS_TOPIC';
3
+ const SNS_ARN_ENV_VAR_NAME = 'SHARED_AUTHORIZATION_SNS_ENDPOINT_RESOURCE_ATTRIBUTES';
4
+ const SNS_DEV_TEST_NAME = 'arn:aws:sns:us-east-1:000000000000:monday-authorization-resource-attributes-sns-local';
4
5
  const RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND = 'resourceAttributeModification';
5
6
  const ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE = 100;
6
7
 
7
8
  exports.ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE = ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE;
8
- exports.RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME = RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME;
9
9
  exports.RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND = RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND;
10
+ exports.SNS_ARN_ENV_VAR_NAME = SNS_ARN_ENV_VAR_NAME;
11
+ exports.SNS_DEV_TEST_NAME = SNS_DEV_TEST_NAME;
@@ -1 +1 @@
1
- {"version":3,"file":"authorization-attributes-service.d.ts","sourceRoot":"","sources":["../../src/authorization-attributes-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,aAAa,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAEtF,OAAO,EAAoB,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,2BAA2B,EAC5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAW3C,qBAAa,8BAA8B;IACzC,OAAO,CAAC,MAAM,CAAC,OAAO,CAA8B;IACpD,OAAO,CAAC,MAAM,CAAC,SAAS,CAGb;IACX,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,MAAM,CAAS;IAEvB;;;;OAIG;gBACS,UAAU,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,gBAAgB,CAAC,aAAa,CAAC;IAqBnF;;;;;;OAMG;IACG,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,4BAA4B,EAAE,2BAA2B,EAAE,GAC1D,OAAO,CAAC,yBAAyB,CAAC;IA6BrC;;;;;;OAMG;IACG,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,yBAAyB,CAAC;IAkCrC;;;;;;;UAOM;IACA,6BAA6B,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,sBAAsB,EAAE,MAAM,EAC9B,2BAA2B,EAAE,2BAA2B,EAAE,GACzD,OAAO,CAAC,2BAA2B,EAAE,CAAC;YAY3B,oBAAoB;IA4BlC,OAAO,CAAC,MAAM,CAAC,cAAc;IAe7B;;;;;;;OAOG;IACG,kCAAkC,IAAI,OAAO,CAAC,OAAO,CAAC;CAoB7D"}
1
+ {"version":3,"file":"authorization-attributes-service.d.ts","sourceRoot":"","sources":["../../src/authorization-attributes-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,aAAa,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAEtF,OAAO,EAAoB,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,2BAA2B,EAC5B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAY3C,qBAAa,8BAA8B;IACzC,OAAO,CAAC,MAAM,CAAC,OAAO,CAA8B;IACpD,OAAO,CAAC,MAAM,CAAC,SAAS,CAGb;IACX,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,MAAM,CAAS;IAEvB;;;;OAIG;gBACS,UAAU,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,EAAE,gBAAgB,CAAC,aAAa,CAAC;IAqBnF;;;;;;OAMG;IACG,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,4BAA4B,EAAE,2BAA2B,EAAE,GAC1D,OAAO,CAAC,yBAAyB,CAAC;IA6BrC;;;;;;OAMG;IACG,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,yBAAyB,CAAC;IAkCrC;;;;;;;UAOM;IACA,6BAA6B,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,sBAAsB,EAAE,MAAM,EAC9B,2BAA2B,EAAE,2BAA2B,EAAE,GACzD,OAAO,CAAC,2BAA2B,EAAE,CAAC;YAY3B,oBAAoB;IA4BlC,OAAO,CAAC,MAAM,CAAC,cAAc;IAW7B;;;;;;;OAOG;IACG,kCAAkC,IAAI,OAAO,CAAC,OAAO,CAAC;CAoB7D"}
@@ -4,7 +4,7 @@ import { sendToSns, getTopicAttributes } from '@mondaydotcomorg/monday-sns';
4
4
  import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
5
5
  import { logger } from './authorization-internal-service.mjs';
6
6
  import { getAttributionsFromApi } from './attributions-service.mjs';
7
- import { ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE, RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME, RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND } from './constants/sns.mjs';
7
+ import { ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE, SNS_ARN_ENV_VAR_NAME, SNS_DEV_TEST_NAME, RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND } from './constants/sns.mjs';
8
8
  import { ERROR_MESSAGES, DEFAULT_FETCH_OPTIONS, APP_NAME } from './constants.mjs';
9
9
 
10
10
  class AuthorizationAttributesService {
@@ -143,15 +143,13 @@ class AuthorizationAttributesService {
143
143
  }
144
144
  }
145
145
  static getSnsTopicArn() {
146
- const arnFromApi = Api.getPart('configurationVariables')?.get(RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME).arn;
147
- if (arnFromApi) {
148
- return arnFromApi;
149
- }
150
- const jsonArnFromEnv = process.env[RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME];
151
- const arnFromEnv = JSON.parse(jsonArnFromEnv).arn;
146
+ const arnFromEnv = process.env[SNS_ARN_ENV_VAR_NAME];
152
147
  if (arnFromEnv) {
153
148
  return arnFromEnv;
154
149
  }
150
+ if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
151
+ return SNS_DEV_TEST_NAME;
152
+ }
155
153
  throw new Error('Unable to get sns topic arn from env variable');
156
154
  }
157
155
  /**
@@ -30,6 +30,14 @@ 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;
33
41
  private static isAuthorizedSingular;
34
42
  private static isAuthorizedMultiple;
35
43
  }
@@ -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;WAsBZ,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,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":"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;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;AA6BD,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;IAsBxC,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAMxC,OAAO,CAAC,MAAM,CAAC,eAAe;IAmB9B,OAAO,CAAC,MAAM,CAAC,qBAAqB;mBAyBf,mBAAmB;IAoCxC,OAAO,CAAC,MAAM,CAAC,gBAAgB;mBAoBV,uBAAuB;IAsC5C,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO,CAAC,MAAM,CAAC,mBAAmB;mBAiBb,oBAAoB;mBAUpB,oBAAoB;CAmF1C;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"}
@@ -15,6 +15,8 @@ const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_acti
15
15
  const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
16
16
  const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
17
17
  const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
18
+ const NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF = 'navigate-can-action-in-scope-to-graph';
19
+ const GRAPH_IS_ALLOWED_PATH = '/permissions/is-allowed';
18
20
  function setRequestFetchOptions(customMondayFetchOptions) {
19
21
  AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
20
22
  }
@@ -87,16 +89,111 @@ class AuthorizationService {
87
89
  return PlatformProfile.INTERNAL;
88
90
  }
89
91
  static async canActionInScopeMultiple(accountId, userId, scopedActions) {
90
- const profile = this.getProfile(accountId, userId);
92
+ const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
91
93
  const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
92
- const scopedActionsPayload = scopedActions.map(scopedAction => {
93
- return { ...scopedAction, scope: mapKeys(scopedAction.scope, (_, key) => snakeCase(key)) }; // for example: { workspaceId: 1 } => { workspace_id: 1 }
94
+ if (shouldNavigateToGraph) {
95
+ const response = await this.fetchGraphIsAllowed(internalAuthToken, scopedActions);
96
+ return this.mapGraphResponse(scopedActions, userId, response);
97
+ }
98
+ const profile = this.getProfile(accountId, userId);
99
+ const scopedActionsPayload = this.buildScopedActionsPayload(scopedActions);
100
+ const platformResponse = await this.fetchPlatformCanActions(profile, internalAuthToken, userId, scopedActionsPayload);
101
+ return this.mapPlatformResponse(platformResponse);
102
+ }
103
+ static buildScopedActionsPayload(scopedActions) {
104
+ return scopedActions.map(scopedAction => {
105
+ return { ...scopedAction, scope: mapKeys(scopedAction.scope, (_, key) => snakeCase(key)) };
94
106
  });
107
+ }
108
+ static scopeToResource(scope) {
109
+ if ('workspaceId' in scope) {
110
+ return { resourceType: 'workspace', resourceId: scope.workspaceId };
111
+ }
112
+ if ('boardId' in scope) {
113
+ return { resourceType: 'board', resourceId: scope.boardId };
114
+ }
115
+ if ('pulseId' in scope) {
116
+ return { resourceType: 'pulse', resourceId: scope.pulseId };
117
+ }
118
+ if ('accountProductId' in scope) {
119
+ return { resourceType: 'account_product', resourceId: scope.accountProductId };
120
+ }
121
+ if ('accountId' in scope) {
122
+ return { resourceType: 'account', resourceId: scope.accountId };
123
+ }
124
+ throw new Error('Unsupported scope provided');
125
+ }
126
+ static buildGraphRequestBody(scopedActions) {
127
+ const resourcesAccumulator = {};
128
+ for (const { action, scope } of scopedActions) {
129
+ const { resourceType, resourceId } = this.scopeToResource(scope);
130
+ if (!resourcesAccumulator[resourceType]) {
131
+ resourcesAccumulator[resourceType] = {};
132
+ }
133
+ if (!resourcesAccumulator[resourceType][resourceId]) {
134
+ resourcesAccumulator[resourceType][resourceId] = new Set();
135
+ }
136
+ resourcesAccumulator[resourceType][resourceId].add(action);
137
+ }
138
+ const resourcesPayload = {};
139
+ for (const [resourceType, idMap] of Object.entries(resourcesAccumulator)) {
140
+ resourcesPayload[resourceType] = {};
141
+ for (const [idStr, actionsSet] of Object.entries(idMap)) {
142
+ const idNum = Number(idStr);
143
+ resourcesPayload[resourceType][idNum] = Array.from(actionsSet);
144
+ }
145
+ }
146
+ return resourcesPayload;
147
+ }
148
+ static async fetchGraphIsAllowed(internalAuthToken, scopedActions) {
149
+ const httpClient = Api.getPart('httpClient');
150
+ const attributionHeaders = getAttributionsFromApi();
151
+ const bodyPayload = this.buildGraphRequestBody(scopedActions);
152
+ try {
153
+ const response = await httpClient.fetch({
154
+ url: {
155
+ appName: 'authorization-graph',
156
+ path: GRAPH_IS_ALLOWED_PATH,
157
+ },
158
+ method: 'POST',
159
+ headers: {
160
+ Authorization: internalAuthToken,
161
+ 'Content-Type': 'application/json',
162
+ ...attributionHeaders,
163
+ },
164
+ body: JSON.stringify(bodyPayload),
165
+ }, {
166
+ timeout: AuthorizationInternalService.getRequestTimeout(),
167
+ retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
168
+ });
169
+ return response;
170
+ }
171
+ catch (err) {
172
+ if (err instanceof HttpFetcherError) {
173
+ AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
174
+ }
175
+ throw err;
176
+ }
177
+ }
178
+ static mapGraphResponse(scopedActions, userId, graphResponse) {
179
+ const resources = graphResponse ?? {};
180
+ return scopedActions.map(scopedAction => {
181
+ const { action, scope } = scopedAction;
182
+ const { resourceType, resourceId } = this.scopeToResource(scope);
183
+ const permissionResult = resources?.[resourceType]?.[String(resourceId)]?.[action];
184
+ const permit = {
185
+ can: permissionResult?.can ?? false,
186
+ reason: { key: permissionResult?.reason ?? 'unknown' },
187
+ technicalReason: 0,
188
+ };
189
+ return { scopedAction, permit };
190
+ });
191
+ }
192
+ static async fetchPlatformCanActions(profile, internalAuthToken, userId, scopedActionsPayload) {
95
193
  const attributionHeaders = getAttributionsFromApi();
96
194
  const httpClient = Api.getPart('httpClient');
97
- let response;
98
195
  try {
99
- response = await httpClient.fetch({
196
+ const response = await httpClient.fetch({
100
197
  url: {
101
198
  appName: 'platform',
102
199
  path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
@@ -108,40 +205,37 @@ class AuthorizationService {
108
205
  'Content-Type': 'application/json',
109
206
  ...attributionHeaders,
110
207
  },
111
- body: JSON.stringify({
112
- user_id: userId,
113
- scoped_actions: scopedActionsPayload,
114
- }),
208
+ body: JSON.stringify({ user_id: userId, scoped_actions: scopedActionsPayload }),
115
209
  }, {
116
210
  timeout: AuthorizationInternalService.getRequestTimeout(),
117
211
  retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
118
212
  });
213
+ return response;
119
214
  }
120
215
  catch (err) {
121
216
  if (err instanceof HttpFetcherError) {
122
217
  AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
123
218
  }
124
- else {
125
- throw err;
126
- }
127
- }
128
- function toCamelCase(obj) {
129
- return mapKeys(obj, (_, key) => camelCase(key));
219
+ throw err;
130
220
  }
221
+ }
222
+ static toCamelCase(obj) {
223
+ return mapKeys(obj, (_, key) => camelCase(key));
224
+ }
225
+ static mapPlatformResponse(response) {
131
226
  if (!response) {
132
227
  logger.error({ tag: 'authorization-service', response }, 'AuthorizationService: missing response');
133
228
  throw new Error('AuthorizationService: missing response');
134
229
  }
135
- const scopedActionsResponseObjects = response.result.map(responseObject => {
230
+ return response.result.map(responseObject => {
136
231
  const { scopedAction, permit } = responseObject;
137
232
  const { scope } = scopedAction;
138
233
  return {
139
234
  ...responseObject,
140
- scopedAction: { ...scopedAction, scope: toCamelCase(scope) },
141
- permit: toCamelCase(permit),
235
+ scopedAction: { ...scopedAction, scope: this.toCamelCase(scope) },
236
+ permit: this.toCamelCase(permit),
142
237
  };
143
238
  });
144
- return scopedActionsResponseObjects;
145
239
  }
146
240
  static async isAuthorizedSingular(accountId, userId, resources, action) {
147
241
  const { authorizationObjects } = createAuthorizationParams(resources, action);
@@ -1,4 +1,5 @@
1
- export declare const RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME = "AUTHORIZATION_RESOURCE_ATTRIBUTES_SNS_TOPIC";
1
+ export declare const SNS_ARN_ENV_VAR_NAME = "SHARED_AUTHORIZATION_SNS_ENDPOINT_RESOURCE_ATTRIBUTES";
2
+ export declare const SNS_DEV_TEST_NAME = "arn:aws:sns:us-east-1:000000000000:monday-authorization-resource-attributes-sns-local";
2
3
  export declare const RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND = "resourceAttributeModification";
3
4
  export declare const ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE = 100;
4
5
  //# sourceMappingURL=sns.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sns.d.ts","sourceRoot":"","sources":["../../../src/constants/sns.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uCAAuC,gDAAgD,CAAC;AACrG,eAAO,MAAM,qDAAqD,kCAAkC,CAAC;AACrG,eAAO,MAAM,oDAAoD,MAAM,CAAC"}
1
+ {"version":3,"file":"sns.d.ts","sourceRoot":"","sources":["../../../src/constants/sns.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,0DAA0D,CAAC;AAC5F,eAAO,MAAM,iBAAiB,0FAC2D,CAAC;AAC1F,eAAO,MAAM,qDAAqD,kCAAkC,CAAC;AACrG,eAAO,MAAM,oDAAoD,MAAM,CAAC"}
@@ -1,5 +1,6 @@
1
- const RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME = 'AUTHORIZATION_RESOURCE_ATTRIBUTES_SNS_TOPIC';
1
+ const SNS_ARN_ENV_VAR_NAME = 'SHARED_AUTHORIZATION_SNS_ENDPOINT_RESOURCE_ATTRIBUTES';
2
+ const SNS_DEV_TEST_NAME = 'arn:aws:sns:us-east-1:000000000000:monday-authorization-resource-attributes-sns-local';
2
3
  const RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND = 'resourceAttributeModification';
3
4
  const ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE = 100;
4
5
 
5
- export { ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE, RESOURCE_ATTRIBUTES_SNS_ARN_SECRET_NAME, RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND };
6
+ export { ASYNC_RESOURCE_ATTRIBUTES_MAX_OPERATIONS_PER_MESSAGE, RESOURCE_ATTRIBUTES_SNS_UPDATE_OPERATION_MESSAGE_KIND, SNS_ARN_ENV_VAR_NAME, SNS_DEV_TEST_NAME };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mondaydotcomorg/monday-authorization",
3
- "version": "3.2.1",
3
+ "version": "3.2.3-feature-bashanye-navigate-can-action-in-scope-to-graph-af77c6b",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "BSD-3-Clause",
@@ -15,6 +15,7 @@
15
15
  "scripts": {
16
16
  "test": "trident-library test",
17
17
  "lint": "trident-library lint",
18
+ "lint:fix": "trident-library lint --fix",
18
19
  "build": "trident-library build",
19
20
  "watch": "trident-library build -w"
20
21
  },
@@ -61,4 +62,4 @@
61
62
  "url": "https://github.com/DaPulse/authorization-domain.git",
62
63
  "directory": "packages/monday-authorization"
63
64
  }
64
- }
65
+ }