@mondaydotcomorg/monday-authorization 3.3.0-feat-add-graph-api-routing-support-c17713e → 3.3.0-feat-add-graph-api-routing-support-5c7bcd4
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 +15 -10
- package/dist/authorization-internal-service.d.ts +1 -1
- package/dist/authorization-internal-service.d.ts.map +1 -1
- package/dist/authorization-service.d.ts.map +1 -1
- package/dist/authorization-service.js +1 -14
- package/dist/clients/graph-api.d.ts.map +1 -1
- package/dist/clients/graph-api.js +3 -9
- package/dist/clients/platform-api.d.ts.map +1 -1
- package/dist/clients/platform-api.js +3 -9
- package/dist/esm/authorization-internal-service.d.ts +1 -1
- package/dist/esm/authorization-internal-service.d.ts.map +1 -1
- package/dist/esm/authorization-service.d.ts.map +1 -1
- package/dist/esm/authorization-service.mjs +1 -14
- package/dist/esm/clients/graph-api.d.ts.map +1 -1
- package/dist/esm/clients/graph-api.mjs +3 -9
- package/dist/esm/clients/platform-api.d.ts.map +1 -1
- package/dist/esm/clients/platform-api.mjs +3 -9
- package/dist/esm/metrics-service.mjs +5 -5
- package/dist/esm/utils/api-error-handler.d.ts +2 -0
- package/dist/esm/utils/api-error-handler.d.ts.map +1 -0
- package/dist/esm/utils/api-error-handler.mjs +18 -0
- package/dist/metrics-service.js +5 -5
- package/dist/utils/api-error-handler.d.ts +2 -0
- package/dist/utils/api-error-handler.d.ts.map +1 -0
- package/dist/utils/api-error-handler.js +20 -0
- package/package.json +1 -1
- package/src/authorization-internal-service.ts +1 -1
- package/src/authorization-service.ts +1 -17
- package/src/clients/graph-api.ts +3 -9
- package/src/clients/platform-api.ts +3 -9
- package/src/metrics-service.ts +5 -5
- package/src/utils/api-error-handler.ts +21 -0
package/README.md
CHANGED
|
@@ -41,6 +41,15 @@ startServer(...)
|
|
|
41
41
|
- grantedFeatureRedisExpirationInSeconds - (optional), redis TTL for cached granted features, default set to 5 minutes
|
|
42
42
|
- metrics - (optional), configure internal DataDog/observability integration. Defaults to `process.env.APP_NAME` as the service name, uses the standard StatsD endpoint (`localhost:8125`) when host/port are not provided, and disables emission automatically in test/development environments (override with `disabled`).
|
|
43
43
|
|
|
44
|
+
### Metrics & Observability
|
|
45
|
+
|
|
46
|
+
- `prometheus` (optional) enables the legacy Prometheus summary `authorization_check_response_time` with labels `resourceType`, `action`, `isAuthorized`, and `responseStatus`.
|
|
47
|
+
- `metrics` (optional) enables StatsD emission through `@mondaydotcomorg/monday-observability-kit` with:
|
|
48
|
+
- `authorization.authorizationCheck.platform.duration` / `.graph.duration` (distributions per API path)
|
|
49
|
+
- `authorization.authorizationCheck.platform.error` / `.graph.error` counters (with `statusCode` tag)
|
|
50
|
+
- When `metrics.disabled` is omitted, the SDK automatically disables StatsD in `test`/`development` environments.
|
|
51
|
+
- StatsD requires `DOGSTATSD_HOST` / `DOGSTATSD_PORT` (or the defaults `localhost:8125`). Errors are logged and skipped if the client is unavailable.
|
|
52
|
+
|
|
44
53
|
## Usage
|
|
45
54
|
|
|
46
55
|
### Use as Middleware
|
|
@@ -141,17 +150,13 @@ const canActionInScopeMultipleResponse: ScopedActionResponseObject[] =
|
|
|
141
150
|
* /
|
|
142
151
|
```
|
|
143
152
|
|
|
144
|
-
**Graph API Routing (v3.3.0+)
|
|
145
|
-
|
|
146
|
-
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`.
|
|
147
|
-
|
|
148
|
-
- **Feature Flag**: `navigate-can-action-in-scope-to-graph`
|
|
149
|
-
- **Default Behavior**: When the feature flag is disabled (default), the SDK routes to Platform API (backward compatible)
|
|
150
|
-
- **Graph Routing**: When enabled, authorization checks are routed to the Graph API endpoint `/permissions/is-allowed`
|
|
151
|
-
- **Automatic Fallback**: The SDK automatically falls back to Platform API if the feature flag is disabled
|
|
152
|
-
- **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
|
|
153
|
+
**Graph API Routing (v3.3.0+)**
|
|
153
154
|
|
|
154
|
-
|
|
155
|
+
- **Feature Flag**: `navigate-can-action-in-scope-to-graph` must be enabled in Ignite for the specific account/user.
|
|
156
|
+
- **Environment Variable**: `APP_NAME` must be defined (Graph API uses it to sign JWTs). Missing `APP_NAME` throws `GraphApi: APP_NAME environment variable is required for Graph API authentication`.
|
|
157
|
+
- **Routing Logic**: when the flag is released, `canActionInScope` / `canActionInScopeMultiple` call `authorization-graph` (`/permissions/is-allowed`). Otherwise they continue to call Platform API.
|
|
158
|
+
- **Fallback**: If Graph responses are missing permissions, the SDK defaults to `can=false` with `reason.key = 'unknown'`. HTTP errors propagate and are counted in the StatsD error metric.
|
|
159
|
+
- **Migration**: upgrade to v3.3.0+, set `APP_NAME`, and roll out the feature flag gradually—no code changes required for consumers.
|
|
155
160
|
|
|
156
161
|
### Authorization Attributes API
|
|
157
162
|
|
|
@@ -10,7 +10,7 @@ export declare class AuthorizationInternalService {
|
|
|
10
10
|
static markAuthorized(request: BaseRequest): void;
|
|
11
11
|
static failIfNotCoveredByAuthorization(request: BaseRequest): void;
|
|
12
12
|
static throwOnHttpErrorIfNeeded(response: Awaited<ReturnType<typeof fetch>>, placement: string): void;
|
|
13
|
-
static throwOnHttpError(status: number, placement: string):
|
|
13
|
+
static throwOnHttpError(status: number, placement: string): never;
|
|
14
14
|
static generateInternalAuthToken(accountId: number, userId: number): string;
|
|
15
15
|
static setRequestFetchOptions(customMondayFetchOptions: MondayFetchOptions): void;
|
|
16
16
|
static getRequestFetchOptions(): MondayFetchOptions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-internal-service.d.ts","sourceRoot":"","sources":["../src/authorization-internal-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,EAAyB,eAAe,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAK9C,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAO/C,eAAO,MAAM,eAAe,EAAE,eAM7B,CAAC;AAYF,qBAAa,4BAA4B;IACvC,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACnC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIpD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIjD,MAAM,CAAC,+BAA+B,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMlE,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAcrG,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"authorization-internal-service.d.ts","sourceRoot":"","sources":["../src/authorization-internal-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,EAAyB,eAAe,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAK9C,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAO/C,eAAO,MAAM,eAAe,EAAE,eAM7B,CAAC;AAYF,qBAAa,4BAA4B;IACvC,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACnC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIpD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIjD,MAAM,CAAC,+BAA+B,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMlE,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAcrG,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK;IAQjE,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAIlE,MAAM,CAAC,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB;IAO1E,MAAM,CAAC,sBAAsB,IAAI,kBAAkB;IAInD,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,YAAY;IAI3C,MAAM,CAAC,iBAAiB;IA2BxB,MAAM,CAAC,gBAAgB,IAAI,WAAW;CASvC"}
|
|
@@ -1 +1 @@
|
|
|
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;AAG7F,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,OAAO,CAAC,MAAM,KAAK,QAAQ,GAK1B;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAW;IAEpC,OAAO,CAAC,MAAM,KAAK,WAAW,GAK7B;IACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAc;IAE1C,MAAM,CAAC,eAAe,IAAI,IAAI;IAK9B,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;
|
|
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;AAG7F,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,OAAO,CAAC,MAAM,KAAK,QAAQ,GAK1B;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAW;IAEpC,OAAO,CAAC,MAAM,KAAK,WAAW,GAK7B;IACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAc;IAE1C,MAAM,CAAC,eAAe,IAAI,IAAI;IAK9B,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;mBA4CnB,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"}
|
|
@@ -117,20 +117,7 @@ class AuthorizationService {
|
|
|
117
117
|
let apiType;
|
|
118
118
|
if (shouldNavigateToGraph) {
|
|
119
119
|
apiType = 'graph';
|
|
120
|
-
|
|
121
|
-
scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
|
|
122
|
-
}
|
|
123
|
-
catch (error) {
|
|
124
|
-
const status = error instanceof mondayFetchApi.HttpFetcherError ? error.status : undefined;
|
|
125
|
-
authorizationInternalService.logger.warn({
|
|
126
|
-
tag: 'authorization-service',
|
|
127
|
-
error: error instanceof Error ? error.message : String(error),
|
|
128
|
-
accountId,
|
|
129
|
-
userId,
|
|
130
|
-
status,
|
|
131
|
-
}, 'Graph API authorization failed');
|
|
132
|
-
throw error;
|
|
133
|
-
}
|
|
120
|
+
scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
|
|
134
121
|
}
|
|
135
122
|
else {
|
|
136
123
|
apiType = 'platform';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-api.d.ts","sourceRoot":"","sources":["../../src/clients/graph-api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"graph-api.d.ts","sourceRoot":"","sources":["../../src/clients/graph-api.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEL,sBAAsB,EAMvB,MAAM,0BAA0B,CAAC;AASlC;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;;IAezC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAyB/B;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAgCzG;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAiC1B;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAMxC,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAWjC"}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const tridentBackendApi = require('@mondaydotcomorg/trident-backend-api');
|
|
4
|
-
const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
|
|
5
4
|
const types_scopedActionsContracts = require('../types/scoped-actions-contracts.js');
|
|
6
5
|
const authorizationInternalService = require('../authorization-internal-service.js');
|
|
7
6
|
const attributionsService = require('../attributions-service.js');
|
|
8
7
|
const utils_authorization_utils = require('../utils/authorization.utils.js');
|
|
9
|
-
const metricsService = require('../metrics-service.js');
|
|
10
8
|
const mondayJwt = require('@mondaydotcomorg/monday-jwt');
|
|
11
9
|
const constants = require('../constants.js');
|
|
10
|
+
const utils_apiErrorHandler = require('../utils/api-error-handler.js');
|
|
12
11
|
|
|
13
12
|
const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
|
|
14
13
|
const APP_NAME_REQUIRED_ERROR = 'GraphApi: APP_NAME environment variable is required for Graph API authentication';
|
|
@@ -81,13 +80,8 @@ class GraphApi {
|
|
|
81
80
|
return response;
|
|
82
81
|
}
|
|
83
82
|
catch (err) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (scopedActions.length > 0) {
|
|
87
|
-
metricsService.recordAuthorizationError('graph', err.status);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
throw err;
|
|
83
|
+
// handleApiError never returns (throws)
|
|
84
|
+
return utils_apiErrorHandler.handleApiError(err, 'graph', 'canActionInScopeMultiple');
|
|
91
85
|
}
|
|
92
86
|
}
|
|
93
87
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-api.d.ts","sourceRoot":"","sources":["../../src/clients/platform-api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"platform-api.d.ts","sourceRoot":"","sources":["../../src/clients/platform-api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAE7F,OAAO,EAA0B,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAelF;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;;IAUxC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAOlC;;OAEG;YACW,gBAAgB;IAqC9B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAkB1B;;OAEG;IACG,gBAAgB,CACpB,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAKzC"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const tridentBackendApi = require('@mondaydotcomorg/trident-backend-api');
|
|
4
|
-
const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
|
|
5
4
|
const authorizationInternalService = require('../authorization-internal-service.js');
|
|
6
5
|
const attributionsService = require('../attributions-service.js');
|
|
7
6
|
const utils_authorization_utils = require('../utils/authorization.utils.js');
|
|
8
|
-
const
|
|
7
|
+
const utils_apiErrorHandler = require('../utils/api-error-handler.js');
|
|
9
8
|
|
|
10
9
|
const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
|
|
11
10
|
/**
|
|
@@ -55,13 +54,8 @@ class PlatformApi {
|
|
|
55
54
|
return response;
|
|
56
55
|
}
|
|
57
56
|
catch (err) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (scopedActionsPayload.length > 0) {
|
|
61
|
-
metricsService.recordAuthorizationError('platform', err.status);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
throw err;
|
|
57
|
+
// handleApiError never returns (throws)
|
|
58
|
+
return utils_apiErrorHandler.handleApiError(err, 'platform', 'canActionInScopeMultiple');
|
|
65
59
|
}
|
|
66
60
|
}
|
|
67
61
|
/**
|
|
@@ -10,7 +10,7 @@ export declare class AuthorizationInternalService {
|
|
|
10
10
|
static markAuthorized(request: BaseRequest): void;
|
|
11
11
|
static failIfNotCoveredByAuthorization(request: BaseRequest): void;
|
|
12
12
|
static throwOnHttpErrorIfNeeded(response: Awaited<ReturnType<typeof fetch>>, placement: string): void;
|
|
13
|
-
static throwOnHttpError(status: number, placement: string):
|
|
13
|
+
static throwOnHttpError(status: number, placement: string): never;
|
|
14
14
|
static generateInternalAuthToken(accountId: number, userId: number): string;
|
|
15
15
|
static setRequestFetchOptions(customMondayFetchOptions: MondayFetchOptions): void;
|
|
16
16
|
static getRequestFetchOptions(): MondayFetchOptions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-internal-service.d.ts","sourceRoot":"","sources":["../../src/authorization-internal-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,EAAyB,eAAe,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAK9C,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAO/C,eAAO,MAAM,eAAe,EAAE,eAM7B,CAAC;AAYF,qBAAa,4BAA4B;IACvC,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACnC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIpD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIjD,MAAM,CAAC,+BAA+B,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMlE,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAcrG,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"authorization-internal-service.d.ts","sourceRoot":"","sources":["../../src/authorization-internal-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,EAAyB,eAAe,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAK9C,eAAO,MAAM,MAAM,kBAA2B,CAAC;AAO/C,eAAO,MAAM,eAAe,EAAE,eAM7B,CAAC;AAYF,qBAAa,4BAA4B;IACvC,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACnC,MAAM,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIpD,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAIjD,MAAM,CAAC,+BAA+B,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAMlE,MAAM,CAAC,wBAAwB,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAcrG,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK;IAQjE,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAIlE,MAAM,CAAC,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB;IAO1E,MAAM,CAAC,sBAAsB,IAAI,kBAAkB;IAInD,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,YAAY;IAI3C,MAAM,CAAC,iBAAiB;IA2BxB,MAAM,CAAC,gBAAgB,IAAI,WAAW;CASvC"}
|
|
@@ -1 +1 @@
|
|
|
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;AAG7F,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,OAAO,CAAC,MAAM,KAAK,QAAQ,GAK1B;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAW;IAEpC,OAAO,CAAC,MAAM,KAAK,WAAW,GAK7B;IACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAc;IAE1C,MAAM,CAAC,eAAe,IAAI,IAAI;IAK9B,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;
|
|
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;AAG7F,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,OAAO,CAAC,MAAM,KAAK,QAAQ,GAK1B;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAW;IAEpC,OAAO,CAAC,MAAM,KAAK,WAAW,GAK7B;IACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAc;IAE1C,MAAM,CAAC,eAAe,IAAI,IAAI;IAK9B,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;mBA4CnB,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"}
|
|
@@ -115,20 +115,7 @@ class AuthorizationService {
|
|
|
115
115
|
let apiType;
|
|
116
116
|
if (shouldNavigateToGraph) {
|
|
117
117
|
apiType = 'graph';
|
|
118
|
-
|
|
119
|
-
scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
|
|
120
|
-
}
|
|
121
|
-
catch (error) {
|
|
122
|
-
const status = error instanceof HttpFetcherError ? error.status : undefined;
|
|
123
|
-
logger.warn({
|
|
124
|
-
tag: 'authorization-service',
|
|
125
|
-
error: error instanceof Error ? error.message : String(error),
|
|
126
|
-
accountId,
|
|
127
|
-
userId,
|
|
128
|
-
status,
|
|
129
|
-
}, 'Graph API authorization failed');
|
|
130
|
-
throw error;
|
|
131
|
-
}
|
|
118
|
+
scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
|
|
132
119
|
}
|
|
133
120
|
else {
|
|
134
121
|
apiType = 'platform';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-api.d.ts","sourceRoot":"","sources":["../../../src/clients/graph-api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"graph-api.d.ts","sourceRoot":"","sources":["../../../src/clients/graph-api.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEL,sBAAsB,EAMvB,MAAM,0BAA0B,CAAC;AASlC;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;;IAezC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAyB/B;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAgCzG;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAiC1B;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAMxC,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAWjC"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Api } from '@mondaydotcomorg/trident-backend-api';
|
|
2
|
-
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
3
2
|
import { PermitTechnicalReason } from '../types/scoped-actions-contracts.mjs';
|
|
4
3
|
import { AuthorizationInternalService } from '../authorization-internal-service.mjs';
|
|
5
4
|
import { getAttributionsFromApi } from '../attributions-service.mjs';
|
|
6
5
|
import { scopeToResource } from '../utils/authorization.utils.mjs';
|
|
7
|
-
import { recordAuthorizationError } from '../metrics-service.mjs';
|
|
8
6
|
import { signAuthorizationHeader } from '@mondaydotcomorg/monday-jwt';
|
|
9
7
|
import { GRAPH_APP_NAME } from '../constants.mjs';
|
|
8
|
+
import { handleApiError } from '../utils/api-error-handler.mjs';
|
|
10
9
|
|
|
11
10
|
const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
|
|
12
11
|
const APP_NAME_REQUIRED_ERROR = 'GraphApi: APP_NAME environment variable is required for Graph API authentication';
|
|
@@ -79,13 +78,8 @@ class GraphApi {
|
|
|
79
78
|
return response;
|
|
80
79
|
}
|
|
81
80
|
catch (err) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (scopedActions.length > 0) {
|
|
85
|
-
recordAuthorizationError('graph', err.status);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
throw err;
|
|
81
|
+
// handleApiError never returns (throws)
|
|
82
|
+
return handleApiError(err, 'graph', 'canActionInScopeMultiple');
|
|
89
83
|
}
|
|
90
84
|
}
|
|
91
85
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-api.d.ts","sourceRoot":"","sources":["../../../src/clients/platform-api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"platform-api.d.ts","sourceRoot":"","sources":["../../../src/clients/platform-api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAE7F,OAAO,EAA0B,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAelF;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;;IAUxC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAOlC;;OAEG;YACW,gBAAgB;IAqC9B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAkB1B;;OAEG;IACG,gBAAgB,CACpB,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAKzC"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Api } from '@mondaydotcomorg/trident-backend-api';
|
|
2
|
-
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
3
2
|
import { AuthorizationInternalService, logger } from '../authorization-internal-service.mjs';
|
|
4
3
|
import { getAttributionsFromApi } from '../attributions-service.mjs';
|
|
5
4
|
import { toSnakeCase, toCamelCase } from '../utils/authorization.utils.mjs';
|
|
6
|
-
import {
|
|
5
|
+
import { handleApiError } from '../utils/api-error-handler.mjs';
|
|
7
6
|
|
|
8
7
|
const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
|
|
9
8
|
/**
|
|
@@ -53,13 +52,8 @@ class PlatformApi {
|
|
|
53
52
|
return response;
|
|
54
53
|
}
|
|
55
54
|
catch (err) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (scopedActionsPayload.length > 0) {
|
|
59
|
-
recordAuthorizationError('platform', err.status);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
throw err;
|
|
55
|
+
// handleApiError never returns (throws)
|
|
56
|
+
return handleApiError(err, 'platform', 'canActionInScopeMultiple');
|
|
63
57
|
}
|
|
64
58
|
}
|
|
65
59
|
/**
|
|
@@ -35,8 +35,8 @@ function recordAuthorizationTiming(apiType, duration) {
|
|
|
35
35
|
try {
|
|
36
36
|
Metric.distribution(`authorization.authorizationCheck.${apiType}.duration`, duration);
|
|
37
37
|
}
|
|
38
|
-
catch
|
|
39
|
-
|
|
38
|
+
catch {
|
|
39
|
+
// ignore metric emission failures
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
function recordAuthorizationError(apiType, statusCode) {
|
|
@@ -44,10 +44,10 @@ function recordAuthorizationError(apiType, statusCode) {
|
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
46
|
try {
|
|
47
|
-
Metric.increment(`authorization.authorizationCheck.${apiType}.error
|
|
47
|
+
Metric.increment(`authorization.authorizationCheck.${apiType}.error`, { statusCode: String(statusCode) }, 1);
|
|
48
48
|
}
|
|
49
|
-
catch
|
|
50
|
-
|
|
49
|
+
catch {
|
|
50
|
+
// ignore metric emission failures
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-error-handler.d.ts","sourceRoot":"","sources":["../../../src/utils/api-error-handler.ts"],"names":[],"mappings":"AAIA,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK,CAgBpG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
2
|
+
import { logger, AuthorizationInternalService } from '../authorization-internal-service.mjs';
|
|
3
|
+
import { recordAuthorizationError } from '../metrics-service.mjs';
|
|
4
|
+
|
|
5
|
+
function handleApiError(err, apiType, placement) {
|
|
6
|
+
if (err instanceof HttpFetcherError) {
|
|
7
|
+
logger.error({ tag: `${apiType}-api`, status: err.status, error: err.message }, `${apiType.charAt(0).toUpperCase() + apiType.slice(1)} API authorization request failed`);
|
|
8
|
+
recordAuthorizationError(apiType, err.status);
|
|
9
|
+
AuthorizationInternalService.throwOnHttpError(err.status, placement);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
logger.error({ tag: `${apiType}-api`, error: err instanceof Error ? err.message : String(err) }, `${apiType.charAt(0).toUpperCase() + apiType.slice(1)} API authorization request failed`);
|
|
13
|
+
recordAuthorizationError(apiType, 500);
|
|
14
|
+
throw err;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { handleApiError };
|
package/dist/metrics-service.js
CHANGED
|
@@ -37,8 +37,8 @@ function recordAuthorizationTiming(apiType, duration) {
|
|
|
37
37
|
try {
|
|
38
38
|
mondayObservabilityKit.Metric.distribution(`authorization.authorizationCheck.${apiType}.duration`, duration);
|
|
39
39
|
}
|
|
40
|
-
catch
|
|
41
|
-
|
|
40
|
+
catch {
|
|
41
|
+
// ignore metric emission failures
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
function recordAuthorizationError(apiType, statusCode) {
|
|
@@ -46,10 +46,10 @@ function recordAuthorizationError(apiType, statusCode) {
|
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
48
|
try {
|
|
49
|
-
mondayObservabilityKit.Metric.increment(`authorization.authorizationCheck.${apiType}.error
|
|
49
|
+
mondayObservabilityKit.Metric.increment(`authorization.authorizationCheck.${apiType}.error`, { statusCode: String(statusCode) }, 1);
|
|
50
50
|
}
|
|
51
|
-
catch
|
|
52
|
-
|
|
51
|
+
catch {
|
|
52
|
+
// ignore metric emission failures
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-error-handler.d.ts","sourceRoot":"","sources":["../../src/utils/api-error-handler.ts"],"names":[],"mappings":"AAIA,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,KAAK,CAgBpG"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
|
|
4
|
+
const authorizationInternalService = require('../authorization-internal-service.js');
|
|
5
|
+
const metricsService = require('../metrics-service.js');
|
|
6
|
+
|
|
7
|
+
function handleApiError(err, apiType, placement) {
|
|
8
|
+
if (err instanceof mondayFetchApi.HttpFetcherError) {
|
|
9
|
+
authorizationInternalService.logger.error({ tag: `${apiType}-api`, status: err.status, error: err.message }, `${apiType.charAt(0).toUpperCase() + apiType.slice(1)} API authorization request failed`);
|
|
10
|
+
metricsService.recordAuthorizationError(apiType, err.status);
|
|
11
|
+
authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, placement);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
authorizationInternalService.logger.error({ tag: `${apiType}-api`, error: err instanceof Error ? err.message : String(err) }, `${apiType.charAt(0).toUpperCase() + apiType.slice(1)} API authorization request failed`);
|
|
15
|
+
metricsService.recordAuthorizationError(apiType, 500);
|
|
16
|
+
throw err;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exports.handleApiError = handleApiError;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mondaydotcomorg/monday-authorization",
|
|
3
|
-
"version": "3.3.0-feat-add-graph-api-routing-support-
|
|
3
|
+
"version": "3.3.0-feat-add-graph-api-routing-support-5c7bcd4",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -63,7 +63,7 @@ export class AuthorizationInternalService {
|
|
|
63
63
|
throw new Error(`AuthorizationService: [${placement}] authorization request failed with status ${status}`);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
static throwOnHttpError(status: number, placement: string) {
|
|
66
|
+
static throwOnHttpError(status: number, placement: string): never {
|
|
67
67
|
logger.error(
|
|
68
68
|
{ tag: 'authorization-service', placement, status },
|
|
69
69
|
'AuthorizationService: authorization request failed'
|
|
@@ -190,23 +190,7 @@ export class AuthorizationService {
|
|
|
190
190
|
|
|
191
191
|
if (shouldNavigateToGraph) {
|
|
192
192
|
apiType = 'graph';
|
|
193
|
-
|
|
194
|
-
try {
|
|
195
|
-
scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
|
|
196
|
-
} catch (error) {
|
|
197
|
-
const status = error instanceof HttpFetcherError ? error.status : undefined;
|
|
198
|
-
logger.warn(
|
|
199
|
-
{
|
|
200
|
-
tag: 'authorization-service',
|
|
201
|
-
error: error instanceof Error ? error.message : String(error),
|
|
202
|
-
accountId,
|
|
203
|
-
userId,
|
|
204
|
-
status,
|
|
205
|
-
},
|
|
206
|
-
'Graph API authorization failed'
|
|
207
|
-
);
|
|
208
|
-
throw error;
|
|
209
|
-
}
|
|
193
|
+
scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
|
|
210
194
|
} else {
|
|
211
195
|
apiType = 'platform';
|
|
212
196
|
const profile = this.getProfile(accountId, userId);
|
package/src/clients/graph-api.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Api, HttpClient } from '@mondaydotcomorg/trident-backend-api';
|
|
2
|
-
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
3
2
|
import {
|
|
4
3
|
ScopedAction,
|
|
5
4
|
ScopedActionResponseObject,
|
|
@@ -18,9 +17,9 @@ import {
|
|
|
18
17
|
GraphPermissionReason,
|
|
19
18
|
} from '../types/graph-api.types';
|
|
20
19
|
import { scopeToResource } from '../utils/authorization.utils';
|
|
21
|
-
import { recordAuthorizationError } from '../metrics-service';
|
|
22
20
|
import { signAuthorizationHeader } from '@mondaydotcomorg/monday-jwt';
|
|
23
21
|
import { GRAPH_APP_NAME } from '../constants';
|
|
22
|
+
import { handleApiError } from '../utils/api-error-handler';
|
|
24
23
|
|
|
25
24
|
const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
|
|
26
25
|
const APP_NAME_REQUIRED_ERROR = 'GraphApi: APP_NAME environment variable is required for Graph API authentication';
|
|
@@ -103,13 +102,8 @@ export class GraphApi {
|
|
|
103
102
|
|
|
104
103
|
return response;
|
|
105
104
|
} catch (err) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (scopedActions.length > 0) {
|
|
109
|
-
recordAuthorizationError('graph', err.status);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
throw err;
|
|
105
|
+
// handleApiError never returns (throws)
|
|
106
|
+
return handleApiError(err, 'graph', 'canActionInScopeMultiple');
|
|
113
107
|
}
|
|
114
108
|
}
|
|
115
109
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Api, HttpClient } from '@mondaydotcomorg/trident-backend-api';
|
|
2
|
-
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
3
2
|
import { ScopedAction, ScopedActionResponseObject } from '../types/scoped-actions-contracts';
|
|
4
3
|
import { AuthorizationInternalService, logger } from '../authorization-internal-service';
|
|
5
4
|
import { getAttributionsFromApi, PlatformProfile } from '../attributions-service';
|
|
6
5
|
import { toCamelCase, toSnakeCase } from '../utils/authorization.utils';
|
|
7
|
-
import {
|
|
6
|
+
import { handleApiError } from '../utils/api-error-handler';
|
|
8
7
|
|
|
9
8
|
const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
|
|
10
9
|
|
|
@@ -76,13 +75,8 @@ export class PlatformApi {
|
|
|
76
75
|
|
|
77
76
|
return response;
|
|
78
77
|
} catch (err) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (scopedActionsPayload.length > 0) {
|
|
82
|
-
recordAuthorizationError('platform', err.status);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
throw err;
|
|
78
|
+
// handleApiError never returns (throws)
|
|
79
|
+
return handleApiError(err, 'platform', 'canActionInScopeMultiple');
|
|
86
80
|
}
|
|
87
81
|
}
|
|
88
82
|
|
package/src/metrics-service.ts
CHANGED
|
@@ -49,8 +49,8 @@ export function recordAuthorizationTiming(apiType: ApiType, duration: number): v
|
|
|
49
49
|
|
|
50
50
|
try {
|
|
51
51
|
Metric.distribution(`authorization.authorizationCheck.${apiType}.duration`, duration);
|
|
52
|
-
} catch
|
|
53
|
-
|
|
52
|
+
} catch {
|
|
53
|
+
// ignore metric emission failures
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -60,8 +60,8 @@ export function recordAuthorizationError(apiType: ApiType, statusCode: number):
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
try {
|
|
63
|
-
Metric.increment(`authorization.authorizationCheck.${apiType}.error
|
|
64
|
-
} catch
|
|
65
|
-
|
|
63
|
+
Metric.increment(`authorization.authorizationCheck.${apiType}.error`, { statusCode: String(statusCode) }, 1);
|
|
64
|
+
} catch {
|
|
65
|
+
// ignore metric emission failures
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
2
|
+
import { AuthorizationInternalService, logger } from '../authorization-internal-service';
|
|
3
|
+
import { recordAuthorizationError } from '../metrics-service';
|
|
4
|
+
|
|
5
|
+
export function handleApiError(err: unknown, apiType: 'platform' | 'graph', placement: string): never {
|
|
6
|
+
if (err instanceof HttpFetcherError) {
|
|
7
|
+
logger.error(
|
|
8
|
+
{ tag: `${apiType}-api`, status: err.status, error: err.message },
|
|
9
|
+
`${apiType.charAt(0).toUpperCase() + apiType.slice(1)} API authorization request failed`
|
|
10
|
+
);
|
|
11
|
+
recordAuthorizationError(apiType, err.status);
|
|
12
|
+
AuthorizationInternalService.throwOnHttpError(err.status, placement);
|
|
13
|
+
} else {
|
|
14
|
+
logger.error(
|
|
15
|
+
{ tag: `${apiType}-api`, error: err instanceof Error ? err.message : String(err) },
|
|
16
|
+
`${apiType.charAt(0).toUpperCase() + apiType.slice(1)} API authorization request failed`
|
|
17
|
+
);
|
|
18
|
+
recordAuthorizationError(apiType, 500);
|
|
19
|
+
throw err;
|
|
20
|
+
}
|
|
21
|
+
}
|