@mondaydotcomorg/monday-authorization 3.2.3-feature-bashanye-navigate-can-action-in-scope-to-graph-af77c6b → 3.3.0-feature-bashanye-navigate-can-action-in-scope-to-graph-8132586
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/README.md +12 -0
- package/dist/authorization-service.d.ts.map +1 -1
- package/dist/authorization-service.js +27 -9
- package/dist/esm/authorization-service.d.ts.map +1 -1
- package/dist/esm/authorization-service.mjs +28 -10
- package/dist/esm/prometheus-service.d.ts +4 -1
- package/dist/esm/prometheus-service.d.ts.map +1 -1
- package/dist/esm/prometheus-service.mjs +17 -5
- package/dist/prometheus-service.d.ts +4 -1
- package/dist/prometheus-service.d.ts.map +1 -1
- package/dist/prometheus-service.js +19 -4
- package/package.json +2 -2
- package/CHANGELOG.md +0 -46
package/README.md
CHANGED
|
@@ -137,6 +137,18 @@ const canActionInScopeMultipleResponse: ScopedActionResponseObject[] =
|
|
|
137
137
|
* /
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
+
**Graph API Routing (v3.3.0+):**
|
|
141
|
+
|
|
142
|
+
Starting from version 3.3.0, `canActionInScope` and `canActionInScopeMultiple` can route authorization checks to the Graph API (`authorization-graph` service) instead of the Platform API. This routing is controlled by the Ignite feature flag `navigate-can-action-in-scope-to-graph`.
|
|
143
|
+
|
|
144
|
+
- **Feature Flag**: `navigate-can-action-in-scope-to-graph`
|
|
145
|
+
- **Default Behavior**: When the feature flag is disabled (default), the SDK routes to Platform API (backward compatible)
|
|
146
|
+
- **Graph Routing**: When enabled, authorization checks are routed to the Graph API endpoint `/permissions/is-allowed`
|
|
147
|
+
- **Automatic Fallback**: The SDK automatically falls back to Platform API if the feature flag is disabled
|
|
148
|
+
- **No Code Changes Required**: The routing is transparent - your code doesn't need to change. Simply upgrade to v3.3.0+ and the feature flag controls the routing behavior
|
|
149
|
+
|
|
150
|
+
The Graph API provides the same authorization results with improved performance and scalability. The feature flag allows for gradual rollout and easy rollback if needed.
|
|
151
|
+
|
|
140
152
|
### Authorization Attributes API
|
|
141
153
|
|
|
142
154
|
Authorization attributes have 2 options to get called: sync (http request) and async (send to SNS and consumed asynchronously).
|
|
@@ -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;
|
|
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;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;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;IAoCxC,OAAO,CAAC,MAAM,CAAC,gBAAgB;mBAoBV,uBAAuB;IAuC5C,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"}
|
|
@@ -20,11 +20,11 @@ const mapKeys__default = /*#__PURE__*/_interopDefault(mapKeys);
|
|
|
20
20
|
const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
|
|
21
21
|
const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
|
|
22
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';
|
|
23
24
|
const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
|
|
24
25
|
const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
|
|
25
26
|
const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
|
|
26
27
|
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';
|
|
28
28
|
function setRequestFetchOptions(customMondayFetchOptions) {
|
|
29
29
|
authorizationInternalService.AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
|
|
30
30
|
}
|
|
@@ -99,14 +99,29 @@ class AuthorizationService {
|
|
|
99
99
|
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
100
100
|
const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
|
|
101
101
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
102
|
+
const startTime = perf_hooks.performance.now();
|
|
103
|
+
let scopedActionResponseObjects;
|
|
102
104
|
if (shouldNavigateToGraph) {
|
|
103
105
|
const response = await this.fetchGraphIsAllowed(internalAuthToken, scopedActions);
|
|
104
|
-
|
|
106
|
+
scopedActionResponseObjects = this.mapGraphResponse(scopedActions, userId, response);
|
|
105
107
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
else {
|
|
109
|
+
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);
|
|
113
|
+
}
|
|
114
|
+
const endTime = perf_hooks.performance.now();
|
|
115
|
+
const time = endTime - startTime;
|
|
116
|
+
const apiType = shouldNavigateToGraph ? 'graph' : 'platform';
|
|
117
|
+
for (const obj of scopedActionResponseObjects) {
|
|
118
|
+
const { action } = obj.scopedAction;
|
|
119
|
+
const resource_type = this.scopeToResource(obj.scopedAction.scope).resourceType;
|
|
120
|
+
const isAuthorized = obj.permit.can;
|
|
121
|
+
prometheusService.sendAuthorizationCheckResponseTimeMetric(resource_type, action, isAuthorized, 200, time, apiType);
|
|
122
|
+
if (obj.permit.can) ;
|
|
123
|
+
}
|
|
124
|
+
return scopedActionResponseObjects;
|
|
110
125
|
}
|
|
111
126
|
static buildScopedActionsPayload(scopedActions) {
|
|
112
127
|
return scopedActions.map(scopedAction => {
|
|
@@ -161,7 +176,7 @@ class AuthorizationService {
|
|
|
161
176
|
const response = await httpClient.fetch({
|
|
162
177
|
url: {
|
|
163
178
|
appName: 'authorization-graph',
|
|
164
|
-
path:
|
|
179
|
+
path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
|
|
165
180
|
},
|
|
166
181
|
method: 'POST',
|
|
167
182
|
headers: {
|
|
@@ -174,11 +189,13 @@ class AuthorizationService {
|
|
|
174
189
|
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
175
190
|
retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
|
|
176
191
|
});
|
|
192
|
+
prometheusService.setGraphAvailability(true);
|
|
177
193
|
return response;
|
|
178
194
|
}
|
|
179
195
|
catch (err) {
|
|
180
196
|
if (err instanceof mondayFetchApi.HttpFetcherError) {
|
|
181
197
|
authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
198
|
+
prometheusService.incrementAuthorizationError(this.scopeToResource(scopedActions[0].scope).resourceType, scopedActions[0].action, err.status);
|
|
182
199
|
}
|
|
183
200
|
throw err;
|
|
184
201
|
}
|
|
@@ -223,6 +240,7 @@ class AuthorizationService {
|
|
|
223
240
|
catch (err) {
|
|
224
241
|
if (err instanceof mondayFetchApi.HttpFetcherError) {
|
|
225
242
|
authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
243
|
+
prometheusService.incrementAuthorizationError(this.scopeToResource(this.toCamelCase(scopedActionsPayload[0].scope)).resourceType, scopedActionsPayload[0].action, err.status);
|
|
226
244
|
}
|
|
227
245
|
throw err;
|
|
228
246
|
}
|
|
@@ -279,7 +297,7 @@ class AuthorizationService {
|
|
|
279
297
|
});
|
|
280
298
|
}
|
|
281
299
|
catch (err) {
|
|
282
|
-
if (err instanceof
|
|
300
|
+
if (err instanceof mondayFetchApi.HttpFetcherError) {
|
|
283
301
|
authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'isAuthorizedMultiple');
|
|
284
302
|
}
|
|
285
303
|
else {
|
|
@@ -298,7 +316,7 @@ class AuthorizationService {
|
|
|
298
316
|
if (!isAuthorized) {
|
|
299
317
|
unauthorizedObjects.push(authorizationObject);
|
|
300
318
|
}
|
|
301
|
-
prometheusService.sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, 200, time);
|
|
319
|
+
prometheusService.sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, 200, time, 'platform');
|
|
302
320
|
});
|
|
303
321
|
if (unauthorizedObjects.length > 0) {
|
|
304
322
|
authorizationInternalService.logger.info({
|
|
@@ -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;
|
|
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;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;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;IAoCxC,OAAO,CAAC,MAAM,CAAC,gBAAgB;mBAoBV,uBAAuB;IAuC5C,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"}
|
|
@@ -5,18 +5,18 @@ import mapKeys from 'lodash/mapKeys.js';
|
|
|
5
5
|
import { Api } from '@mondaydotcomorg/trident-backend-api';
|
|
6
6
|
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
7
7
|
import { getIgniteClient } from '@mondaydotcomorg/ignite-sdk';
|
|
8
|
-
import { sendAuthorizationCheckResponseTimeMetric } from './prometheus-service.mjs';
|
|
8
|
+
import { sendAuthorizationCheckResponseTimeMetric, setGraphAvailability, incrementAuthorizationError } from './prometheus-service.mjs';
|
|
9
9
|
import { AuthorizationInternalService, logger } from './authorization-internal-service.mjs';
|
|
10
10
|
import { getProfile, PlatformProfile, getAttributionsFromApi } from './attributions-service.mjs';
|
|
11
11
|
|
|
12
12
|
const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
|
|
13
13
|
const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
|
|
14
14
|
const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
|
|
15
|
+
const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
|
|
15
16
|
const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
|
|
16
17
|
const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
|
|
17
18
|
const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
|
|
18
19
|
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';
|
|
20
20
|
function setRequestFetchOptions(customMondayFetchOptions) {
|
|
21
21
|
AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
|
|
22
22
|
}
|
|
@@ -91,14 +91,29 @@ class AuthorizationService {
|
|
|
91
91
|
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
92
92
|
const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
|
|
93
93
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
94
|
+
const startTime = performance.now();
|
|
95
|
+
let scopedActionResponseObjects;
|
|
94
96
|
if (shouldNavigateToGraph) {
|
|
95
97
|
const response = await this.fetchGraphIsAllowed(internalAuthToken, scopedActions);
|
|
96
|
-
|
|
98
|
+
scopedActionResponseObjects = this.mapGraphResponse(scopedActions, userId, response);
|
|
97
99
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
else {
|
|
101
|
+
const profile = this.getProfile(accountId, userId);
|
|
102
|
+
const scopedActionsPayload = this.buildScopedActionsPayload(scopedActions);
|
|
103
|
+
const platformResponse = await this.fetchPlatformCanActions(profile, internalAuthToken, userId, scopedActionsPayload);
|
|
104
|
+
scopedActionResponseObjects = this.mapPlatformResponse(platformResponse);
|
|
105
|
+
}
|
|
106
|
+
const endTime = performance.now();
|
|
107
|
+
const time = endTime - startTime;
|
|
108
|
+
const apiType = shouldNavigateToGraph ? 'graph' : 'platform';
|
|
109
|
+
for (const obj of scopedActionResponseObjects) {
|
|
110
|
+
const { action } = obj.scopedAction;
|
|
111
|
+
const resource_type = this.scopeToResource(obj.scopedAction.scope).resourceType;
|
|
112
|
+
const isAuthorized = obj.permit.can;
|
|
113
|
+
sendAuthorizationCheckResponseTimeMetric(resource_type, action, isAuthorized, 200, time, apiType);
|
|
114
|
+
if (obj.permit.can) ;
|
|
115
|
+
}
|
|
116
|
+
return scopedActionResponseObjects;
|
|
102
117
|
}
|
|
103
118
|
static buildScopedActionsPayload(scopedActions) {
|
|
104
119
|
return scopedActions.map(scopedAction => {
|
|
@@ -153,7 +168,7 @@ class AuthorizationService {
|
|
|
153
168
|
const response = await httpClient.fetch({
|
|
154
169
|
url: {
|
|
155
170
|
appName: 'authorization-graph',
|
|
156
|
-
path:
|
|
171
|
+
path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
|
|
157
172
|
},
|
|
158
173
|
method: 'POST',
|
|
159
174
|
headers: {
|
|
@@ -166,11 +181,13 @@ class AuthorizationService {
|
|
|
166
181
|
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
167
182
|
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
168
183
|
});
|
|
184
|
+
setGraphAvailability(true);
|
|
169
185
|
return response;
|
|
170
186
|
}
|
|
171
187
|
catch (err) {
|
|
172
188
|
if (err instanceof HttpFetcherError) {
|
|
173
189
|
AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
190
|
+
incrementAuthorizationError(this.scopeToResource(scopedActions[0].scope).resourceType, scopedActions[0].action, err.status);
|
|
174
191
|
}
|
|
175
192
|
throw err;
|
|
176
193
|
}
|
|
@@ -215,6 +232,7 @@ class AuthorizationService {
|
|
|
215
232
|
catch (err) {
|
|
216
233
|
if (err instanceof HttpFetcherError) {
|
|
217
234
|
AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
235
|
+
incrementAuthorizationError(this.scopeToResource(this.toCamelCase(scopedActionsPayload[0].scope)).resourceType, scopedActionsPayload[0].action, err.status);
|
|
218
236
|
}
|
|
219
237
|
throw err;
|
|
220
238
|
}
|
|
@@ -271,7 +289,7 @@ class AuthorizationService {
|
|
|
271
289
|
});
|
|
272
290
|
}
|
|
273
291
|
catch (err) {
|
|
274
|
-
if (err instanceof
|
|
292
|
+
if (err instanceof HttpFetcherError) {
|
|
275
293
|
AuthorizationInternalService.throwOnHttpError(err.status, 'isAuthorizedMultiple');
|
|
276
294
|
}
|
|
277
295
|
else {
|
|
@@ -290,7 +308,7 @@ class AuthorizationService {
|
|
|
290
308
|
if (!isAuthorized) {
|
|
291
309
|
unauthorizedObjects.push(authorizationObject);
|
|
292
310
|
}
|
|
293
|
-
sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, 200, time);
|
|
311
|
+
sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, 200, time, 'platform');
|
|
294
312
|
});
|
|
295
313
|
if (unauthorizedObjects.length > 0) {
|
|
296
314
|
logger.info({
|
|
@@ -6,5 +6,8 @@ export declare const METRICS: {
|
|
|
6
6
|
};
|
|
7
7
|
export declare function setPrometheus(customPrometheus: any): void;
|
|
8
8
|
export declare function getMetricsManager(): any;
|
|
9
|
-
export declare function sendAuthorizationCheckResponseTimeMetric(resourceType: string, action: Action, isAuthorized: boolean, responseStatus: number, time: number): void;
|
|
9
|
+
export declare function sendAuthorizationCheckResponseTimeMetric(resourceType: string, action: Action, isAuthorized: boolean, responseStatus: number, time: number, apiType?: 'platform' | 'graph'): void;
|
|
10
|
+
export declare function incrementAuthorizationSuccess(resourceType: string, action: Action): void;
|
|
11
|
+
export declare function incrementAuthorizationError(resourceType: string, action: Action, statusCode: number): void;
|
|
12
|
+
export declare function setGraphAvailability(isAvailable: boolean): void;
|
|
10
13
|
//# sourceMappingURL=prometheus-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prometheus-service.d.ts","sourceRoot":"","sources":["../../src/prometheus-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAKzC,eAAO,MAAM,OAAO;;;;CAInB,CAAC;AAQF,wBAAgB,aAAa,CAAC,gBAAgB,KAAA,
|
|
1
|
+
{"version":3,"file":"prometheus-service.d.ts","sourceRoot":"","sources":["../../src/prometheus-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAKzC,eAAO,MAAM,OAAO;;;;CAInB,CAAC;AAQF,wBAAgB,aAAa,CAAC,gBAAgB,KAAA,QAiB7C;AAED,wBAAgB,iBAAiB,QAEhC;AAED,wBAAgB,wCAAwC,CACtD,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,OAAO,EACrB,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,UAAU,GAAG,OAAoB,QAW3C;AAED,wBAAgB,6BAA6B,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAI;AAEtF,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAI;AAExG,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,OAAO,QAAI"}
|
|
@@ -7,26 +7,38 @@ const METRICS = {
|
|
|
7
7
|
};
|
|
8
8
|
const authorizationCheckResponseTimeMetricConfig = {
|
|
9
9
|
name: METRICS.AUTHORIZATION_CHECK_RESPONSE_TIME,
|
|
10
|
-
labels: ['resourceType', 'action', 'isAuthorized', 'responseStatus'],
|
|
10
|
+
labels: ['resourceType', 'action', 'isAuthorized', 'responseStatus', 'apiType'],
|
|
11
11
|
description: 'Authorization check response time summary',
|
|
12
12
|
};
|
|
13
13
|
function setPrometheus(customPrometheus) {
|
|
14
14
|
prometheus = customPrometheus;
|
|
15
|
+
if (!prometheus) {
|
|
16
|
+
authorizationCheckResponseTimeMetric = null;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
15
19
|
const { METRICS_TYPES } = prometheus;
|
|
16
|
-
|
|
20
|
+
const metricsManager = getMetricsManager();
|
|
21
|
+
if (metricsManager) {
|
|
22
|
+
authorizationCheckResponseTimeMetric = metricsManager.addMetric(METRICS_TYPES.SUMMARY, authorizationCheckResponseTimeMetricConfig.name, authorizationCheckResponseTimeMetricConfig.labels, authorizationCheckResponseTimeMetricConfig.description);
|
|
23
|
+
}
|
|
17
24
|
}
|
|
18
25
|
function getMetricsManager() {
|
|
19
26
|
return prometheus?.metricsManager;
|
|
20
27
|
}
|
|
21
|
-
function sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, responseStatus, time) {
|
|
28
|
+
function sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, responseStatus, time, apiType = 'platform') {
|
|
22
29
|
try {
|
|
23
30
|
if (authorizationCheckResponseTimeMetric) {
|
|
24
|
-
authorizationCheckResponseTimeMetric
|
|
31
|
+
authorizationCheckResponseTimeMetric
|
|
32
|
+
.labels(resourceType, action, isAuthorized, responseStatus, apiType)
|
|
33
|
+
.observe(time);
|
|
25
34
|
}
|
|
26
35
|
}
|
|
27
36
|
catch (e) {
|
|
28
37
|
// ignore
|
|
29
38
|
}
|
|
30
39
|
}
|
|
40
|
+
function incrementAuthorizationSuccess(resourceType, action) { }
|
|
41
|
+
function incrementAuthorizationError(resourceType, action, statusCode) { }
|
|
42
|
+
function setGraphAvailability(isAvailable) { }
|
|
31
43
|
|
|
32
|
-
export { METRICS, getMetricsManager, sendAuthorizationCheckResponseTimeMetric, setPrometheus };
|
|
44
|
+
export { METRICS, getMetricsManager, incrementAuthorizationError, incrementAuthorizationSuccess, sendAuthorizationCheckResponseTimeMetric, setGraphAvailability, setPrometheus };
|
|
@@ -6,5 +6,8 @@ export declare const METRICS: {
|
|
|
6
6
|
};
|
|
7
7
|
export declare function setPrometheus(customPrometheus: any): void;
|
|
8
8
|
export declare function getMetricsManager(): any;
|
|
9
|
-
export declare function sendAuthorizationCheckResponseTimeMetric(resourceType: string, action: Action, isAuthorized: boolean, responseStatus: number, time: number): void;
|
|
9
|
+
export declare function sendAuthorizationCheckResponseTimeMetric(resourceType: string, action: Action, isAuthorized: boolean, responseStatus: number, time: number, apiType?: 'platform' | 'graph'): void;
|
|
10
|
+
export declare function incrementAuthorizationSuccess(resourceType: string, action: Action): void;
|
|
11
|
+
export declare function incrementAuthorizationError(resourceType: string, action: Action, statusCode: number): void;
|
|
12
|
+
export declare function setGraphAvailability(isAvailable: boolean): void;
|
|
10
13
|
//# sourceMappingURL=prometheus-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prometheus-service.d.ts","sourceRoot":"","sources":["../src/prometheus-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAKzC,eAAO,MAAM,OAAO;;;;CAInB,CAAC;AAQF,wBAAgB,aAAa,CAAC,gBAAgB,KAAA,
|
|
1
|
+
{"version":3,"file":"prometheus-service.d.ts","sourceRoot":"","sources":["../src/prometheus-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAKzC,eAAO,MAAM,OAAO;;;;CAInB,CAAC;AAQF,wBAAgB,aAAa,CAAC,gBAAgB,KAAA,QAiB7C;AAED,wBAAgB,iBAAiB,QAEhC;AAED,wBAAgB,wCAAwC,CACtD,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,OAAO,EACrB,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,UAAU,GAAG,OAAoB,QAW3C;AAED,wBAAgB,6BAA6B,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAI;AAEtF,wBAAgB,2BAA2B,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAI;AAExG,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,OAAO,QAAI"}
|
|
@@ -9,29 +9,44 @@ const METRICS = {
|
|
|
9
9
|
};
|
|
10
10
|
const authorizationCheckResponseTimeMetricConfig = {
|
|
11
11
|
name: METRICS.AUTHORIZATION_CHECK_RESPONSE_TIME,
|
|
12
|
-
labels: ['resourceType', 'action', 'isAuthorized', 'responseStatus'],
|
|
12
|
+
labels: ['resourceType', 'action', 'isAuthorized', 'responseStatus', 'apiType'],
|
|
13
13
|
description: 'Authorization check response time summary',
|
|
14
14
|
};
|
|
15
15
|
function setPrometheus(customPrometheus) {
|
|
16
16
|
prometheus = customPrometheus;
|
|
17
|
+
if (!prometheus) {
|
|
18
|
+
authorizationCheckResponseTimeMetric = null;
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
17
21
|
const { METRICS_TYPES } = prometheus;
|
|
18
|
-
|
|
22
|
+
const metricsManager = getMetricsManager();
|
|
23
|
+
if (metricsManager) {
|
|
24
|
+
authorizationCheckResponseTimeMetric = metricsManager.addMetric(METRICS_TYPES.SUMMARY, authorizationCheckResponseTimeMetricConfig.name, authorizationCheckResponseTimeMetricConfig.labels, authorizationCheckResponseTimeMetricConfig.description);
|
|
25
|
+
}
|
|
19
26
|
}
|
|
20
27
|
function getMetricsManager() {
|
|
21
28
|
return prometheus?.metricsManager;
|
|
22
29
|
}
|
|
23
|
-
function sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, responseStatus, time) {
|
|
30
|
+
function sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, responseStatus, time, apiType = 'platform') {
|
|
24
31
|
try {
|
|
25
32
|
if (authorizationCheckResponseTimeMetric) {
|
|
26
|
-
authorizationCheckResponseTimeMetric
|
|
33
|
+
authorizationCheckResponseTimeMetric
|
|
34
|
+
.labels(resourceType, action, isAuthorized, responseStatus, apiType)
|
|
35
|
+
.observe(time);
|
|
27
36
|
}
|
|
28
37
|
}
|
|
29
38
|
catch (e) {
|
|
30
39
|
// ignore
|
|
31
40
|
}
|
|
32
41
|
}
|
|
42
|
+
function incrementAuthorizationSuccess(resourceType, action) { }
|
|
43
|
+
function incrementAuthorizationError(resourceType, action, statusCode) { }
|
|
44
|
+
function setGraphAvailability(isAvailable) { }
|
|
33
45
|
|
|
34
46
|
exports.METRICS = METRICS;
|
|
35
47
|
exports.getMetricsManager = getMetricsManager;
|
|
48
|
+
exports.incrementAuthorizationError = incrementAuthorizationError;
|
|
49
|
+
exports.incrementAuthorizationSuccess = incrementAuthorizationSuccess;
|
|
36
50
|
exports.sendAuthorizationCheckResponseTimeMetric = sendAuthorizationCheckResponseTimeMetric;
|
|
51
|
+
exports.setGraphAvailability = setGraphAvailability;
|
|
37
52
|
exports.setPrometheus = setPrometheus;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mondaydotcomorg/monday-authorization",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0-feature-bashanye-navigate-can-action-in-scope-to-graph-8132586",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -62,4 +62,4 @@
|
|
|
62
62
|
"url": "https://github.com/DaPulse/authorization-domain.git",
|
|
63
63
|
"directory": "packages/monday-authorization"
|
|
64
64
|
}
|
|
65
|
-
}
|
|
65
|
+
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
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)
|