@mondaydotcomorg/monday-authorization 3.3.0-feature-bashanye-navigate-can-action-in-scope-to-graph-63c65ad → 3.3.1-feature-bashanye-add-membership-create-delete-api-d00c165

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +160 -11
  2. package/dist/attributions-service.d.ts +3 -2
  3. package/dist/attributions-service.d.ts.map +1 -1
  4. package/dist/attributions-service.js +1 -0
  5. package/dist/authorization-internal-service.d.ts +1 -1
  6. package/dist/authorization-internal-service.d.ts.map +1 -1
  7. package/dist/authorization-service.d.ts +5 -0
  8. package/dist/authorization-service.d.ts.map +1 -1
  9. package/dist/authorization-service.js +30 -26
  10. package/dist/clients/graph-api.d.ts +28 -0
  11. package/dist/clients/graph-api.d.ts.map +1 -0
  12. package/dist/clients/{graph-api.client.js → graph-api.js} +48 -40
  13. package/dist/clients/platform-api.d.ts +26 -0
  14. package/dist/clients/platform-api.d.ts.map +1 -0
  15. package/dist/clients/{platform-api.client.js → platform-api.js} +20 -20
  16. package/dist/constants.d.ts +1 -0
  17. package/dist/constants.d.ts.map +1 -1
  18. package/dist/constants.js +2 -0
  19. package/dist/esm/attributions-service.d.ts +3 -2
  20. package/dist/esm/attributions-service.d.ts.map +1 -1
  21. package/dist/esm/attributions-service.mjs +1 -0
  22. package/dist/esm/authorization-internal-service.d.ts +1 -1
  23. package/dist/esm/authorization-internal-service.d.ts.map +1 -1
  24. package/dist/esm/authorization-service.d.ts +5 -0
  25. package/dist/esm/authorization-service.d.ts.map +1 -1
  26. package/dist/esm/authorization-service.mjs +31 -27
  27. package/dist/esm/clients/graph-api.d.ts +28 -0
  28. package/dist/esm/clients/graph-api.d.ts.map +1 -0
  29. package/dist/esm/clients/{graph-api.client.mjs → graph-api.mjs} +48 -40
  30. package/dist/esm/clients/platform-api.d.ts +26 -0
  31. package/dist/esm/clients/platform-api.d.ts.map +1 -0
  32. package/dist/esm/clients/{platform-api.client.mjs → platform-api.mjs} +21 -21
  33. package/dist/esm/constants.d.ts +1 -0
  34. package/dist/esm/constants.d.ts.map +1 -1
  35. package/dist/esm/constants.mjs +2 -1
  36. package/dist/esm/index.d.ts +7 -0
  37. package/dist/esm/index.d.ts.map +1 -1
  38. package/dist/esm/index.mjs +9 -0
  39. package/dist/esm/memberships.d.ts +30 -0
  40. package/dist/esm/memberships.d.ts.map +1 -0
  41. package/dist/esm/memberships.mjs +98 -0
  42. package/dist/esm/metrics-service.d.ts +12 -0
  43. package/dist/esm/metrics-service.d.ts.map +1 -0
  44. package/dist/esm/metrics-service.mjs +54 -0
  45. package/dist/esm/prometheus-service.d.ts +1 -3
  46. package/dist/esm/prometheus-service.d.ts.map +1 -1
  47. package/dist/esm/prometheus-service.mjs +5 -58
  48. package/dist/esm/types/graph-api.types.d.ts +8 -7
  49. package/dist/esm/types/graph-api.types.d.ts.map +1 -1
  50. package/dist/esm/types/memberships.d.ts +42 -0
  51. package/dist/esm/types/memberships.d.ts.map +1 -0
  52. package/dist/esm/types/memberships.mjs +1 -0
  53. package/dist/esm/types/scoped-actions-contracts.d.ts +10 -1
  54. package/dist/esm/types/scoped-actions-contracts.d.ts.map +1 -1
  55. package/dist/esm/types/scoped-actions-contracts.mjs +9 -0
  56. package/dist/esm/utils/api-error-handler.d.ts +2 -0
  57. package/dist/esm/utils/api-error-handler.d.ts.map +1 -0
  58. package/dist/esm/utils/api-error-handler.mjs +18 -0
  59. package/dist/index.d.ts +7 -0
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +10 -0
  62. package/dist/memberships.d.ts +30 -0
  63. package/dist/memberships.d.ts.map +1 -0
  64. package/dist/memberships.js +100 -0
  65. package/dist/metrics-service.d.ts +12 -0
  66. package/dist/metrics-service.d.ts.map +1 -0
  67. package/dist/metrics-service.js +58 -0
  68. package/dist/prometheus-service.d.ts +1 -3
  69. package/dist/prometheus-service.d.ts.map +1 -1
  70. package/dist/prometheus-service.js +4 -59
  71. package/dist/types/graph-api.types.d.ts +8 -7
  72. package/dist/types/graph-api.types.d.ts.map +1 -1
  73. package/dist/types/memberships.d.ts +42 -0
  74. package/dist/types/memberships.d.ts.map +1 -0
  75. package/dist/types/memberships.js +1 -0
  76. package/dist/types/scoped-actions-contracts.d.ts +10 -1
  77. package/dist/types/scoped-actions-contracts.d.ts.map +1 -1
  78. package/dist/types/scoped-actions-contracts.js +9 -0
  79. package/dist/utils/api-error-handler.d.ts +2 -0
  80. package/dist/utils/api-error-handler.d.ts.map +1 -0
  81. package/dist/utils/api-error-handler.js +20 -0
  82. package/package.json +5 -2
  83. package/src/attributions-service.ts +93 -0
  84. package/src/authorization-attributes-service.ts +234 -0
  85. package/src/authorization-internal-service.ts +129 -0
  86. package/src/authorization-middleware.ts +51 -0
  87. package/src/authorization-service.ts +356 -0
  88. package/src/clients/graph-api.ts +170 -0
  89. package/src/clients/platform-api.ts +117 -0
  90. package/src/constants/sns.ts +5 -0
  91. package/src/constants.ts +23 -0
  92. package/src/index.ts +63 -0
  93. package/src/memberships.ts +111 -0
  94. package/src/metrics-service.ts +71 -0
  95. package/src/prometheus-service.ts +51 -0
  96. package/src/roles-service.ts +125 -0
  97. package/src/testKit/index.ts +69 -0
  98. package/src/types/authorization-attributes-contracts.ts +33 -0
  99. package/src/types/express.ts +8 -0
  100. package/src/types/general.ts +32 -0
  101. package/src/types/graph-api.types.ts +25 -0
  102. package/src/types/memberships.ts +47 -0
  103. package/src/types/roles.ts +42 -0
  104. package/src/types/scoped-actions-contracts.ts +57 -0
  105. package/src/utils/api-error-handler.ts +25 -0
  106. package/src/utils/authorization.utils.ts +47 -0
  107. package/dist/clients/graph-api.client.d.ts +0 -24
  108. package/dist/clients/graph-api.client.d.ts.map +0 -1
  109. package/dist/clients/platform-api.client.d.ts +0 -31
  110. package/dist/clients/platform-api.client.d.ts.map +0 -1
  111. package/dist/esm/clients/graph-api.client.d.ts +0 -24
  112. package/dist/esm/clients/graph-api.client.d.ts.map +0 -1
  113. package/dist/esm/clients/platform-api.client.d.ts +0 -31
  114. package/dist/esm/clients/platform-api.client.d.ts.map +0 -1
package/README.md CHANGED
@@ -25,8 +25,11 @@ import * as MondayAuthorization from '@mondaydotcomorg/monday-authorization';
25
25
 
26
26
  ...
27
27
 
28
- MondayAuthorization.init({
28
+ await MondayAuthorization.init({
29
29
  prometheus: getPrometheus(),
30
+ metrics: {
31
+ serviceName: process.env.APP_NAME,
32
+ },
30
33
  redisClient: redisClient,
31
34
  grantedFeatureRedisExpirationInSeconds: 10 * 60
32
35
  });
@@ -36,6 +39,16 @@ startServer(...)
36
39
  **Recommended** - optionally init authorization with redisClient so the granted feature results will be cached and reduce http calls.
37
40
 
38
41
  - grantedFeatureRedisExpirationInSeconds - (optional), redis TTL for cached granted features, default set to 5 minutes
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
+
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.
39
52
 
40
53
  ## Usage
41
54
 
@@ -137,17 +150,13 @@ const canActionInScopeMultipleResponse: ScopedActionResponseObject[] =
137
150
  * /
138
151
  ```
139
152
 
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
153
+ **Graph API Routing (v3.3.0+)**
149
154
 
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.
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.
151
160
 
152
161
  ### Authorization Attributes API
153
162
 
@@ -256,6 +265,7 @@ const rolesResponse = await rolesService.getRoles(accountId, resourceTypes, styl
256
265
  ```
257
266
 
258
267
  **Parameters:**
268
+
259
269
  - `accountId` - The account ID
260
270
  - `resourceTypes` - Array of resource types to filter roles by (e.g., ['account', 'workspace'])
261
271
  - `style` - Deprecated, don't use it. the style of the roles to return, either 'A' or 'B' (default is 'A'). Note that basic role IDs are returned in A style and not B style.
@@ -285,6 +295,7 @@ const rolesResponse = await rolesService.createCustomRole(accountId, customRoles
285
295
  ```
286
296
 
287
297
  **Parameters:**
298
+
288
299
  - `accountId` - The account ID
289
300
  - `roles` - Array of `RoleCreateRequest` objects (cannot be empty)
290
301
 
@@ -310,6 +321,7 @@ const rolesResponse = await rolesService.updateCustomRole(accountId, updateReque
310
321
  ```
311
322
 
312
323
  **Parameters:**
324
+
313
325
  - `accountId` - The account ID
314
326
  - `updateRequests` - Array of `RoleUpdateRequest` objects
315
327
 
@@ -328,6 +340,7 @@ const rolesResponse = await rolesService.deleteCustomRole(accountId, roleIds);
328
340
  ```
329
341
 
330
342
  **Parameters:**
343
+
331
344
  - `accountId` - The account ID
332
345
  - `roleIds` - Array of custom role IDs to delete
333
346
 
@@ -388,3 +401,139 @@ interface RolesResponse {
388
401
  basicRoles?: BasicRole[];
389
402
  }
390
403
  ```
404
+
405
+ ### Memberships API
406
+
407
+ The Memberships API allows you to manage memberships (role assignments) for entities on resources. Use `MembershipsService` to create/update and delete memberships synchronously.
408
+
409
+ Important note: there is no validations for the user that create/delete memberships on authorization side.
410
+ It's on the caller responsibility to validate the user have the right permission to change these memberships.
411
+
412
+ #### Create/Update Memberships
413
+
414
+ Use `MembershipsService.upsertMemberships` to create or update memberships synchronously:
415
+
416
+ ```ts
417
+ import { MembershipsService, MembershipForCreate } from '@mondaydotcomorg/monday-authorization';
418
+
419
+ const membershipsService = new MembershipsService();
420
+ const accountId = 739630;
421
+ const memberships: MembershipForCreate[] = [
422
+ {
423
+ entityId: 123,
424
+ entityType: 'user',
425
+ resourceId: 456,
426
+ resourceType: 'workspace',
427
+ roleId: 5,
428
+ roleType: 'basic',
429
+ addedById: 789,
430
+ },
431
+ ];
432
+
433
+ const response = await membershipsService.upsertMemberships(accountId, memberships);
434
+ // Returns: { memberships: Membership[] }
435
+ ```
436
+
437
+ **Parameters:**
438
+
439
+ - `accountId` - The account ID
440
+ - `memberships` - Array of `MembershipForCreate` objects
441
+
442
+ #### Delete Memberships
443
+
444
+ Use `MembershipsService.deleteMemberships` to delete memberships synchronously:
445
+
446
+ ```ts
447
+ import { MembershipsService, MembershipForDelete } from '@mondaydotcomorg/monday-authorization';
448
+
449
+ const membershipsService = new MembershipsService();
450
+ const accountId = 739630;
451
+ const memberships: MembershipForDelete[] = [
452
+ {
453
+ entityId: 123,
454
+ entityType: 'user',
455
+ resourceId: 456,
456
+ resourceType: 'workspace',
457
+ },
458
+ ];
459
+
460
+ const response = await membershipsService.deleteMemberships(accountId, memberships);
461
+ // Returns: { memberships: Membership[] }
462
+ ```
463
+
464
+ **Parameters:**
465
+
466
+ - `accountId` - The account ID
467
+ - `memberships` - Array of `MembershipForDelete` objects
468
+
469
+ #### Types
470
+
471
+ The following types are available for working with memberships:
472
+
473
+ ```ts
474
+ import {
475
+ MembershipForCreate,
476
+ MembershipForDelete,
477
+ Membership,
478
+ MembershipCreateResponse,
479
+ MembershipDeleteResponse,
480
+ } from '@mondaydotcomorg/monday-authorization';
481
+
482
+ // MembershipForCreate interface
483
+ interface MembershipForCreate {
484
+ entityId: number;
485
+ entityType: string;
486
+ resourceId: number;
487
+ resourceType: string;
488
+ roleId: number;
489
+ roleType?: string;
490
+ addedById: number;
491
+ }
492
+
493
+ // MembershipForDelete interface
494
+ interface MembershipForDelete {
495
+ entityId?: number;
496
+ entityType: string;
497
+ resourceId?: number;
498
+ resourceType: string;
499
+ }
500
+
501
+ // Membership interface
502
+ interface Membership {
503
+ id: number;
504
+ entityId: number;
505
+ entityType: string;
506
+ resourceId: number;
507
+ resourceType: string;
508
+ roleId: number;
509
+ roleType: string;
510
+ addedById: null | number | undefined;
511
+ hops: number;
512
+ isNewRecord: boolean;
513
+ previousValues: Partial<Membership>;
514
+ walVersion: number | null | undefined;
515
+ }
516
+
517
+ // MembershipCreateResponse interface
518
+ interface MembershipCreateResponse {
519
+ memberships: Membership[];
520
+ }
521
+
522
+ // MembershipDeleteResponse interface
523
+ interface MembershipDeleteResponse {
524
+ memberships: Membership[];
525
+ }
526
+ ```
527
+
528
+ ## Development
529
+
530
+ ### Local Development and Testing
531
+
532
+ This package includes an `ignite-local-overrides.json` file for local development and testing only. It does **not** affect consumers of this package - they use their own Ignite configuration.
533
+
534
+ The file enables feature flags for testing:
535
+
536
+ - `sdk-platform-profiles`: Platform profile routing
537
+ - `navigate-can-action-in-scope-to-graph`: Graph API routing for `canActionInScope` methods
538
+
539
+ Modify this file for different local test scenarios, but remember changes only affect this package's development/testing.
@@ -2,9 +2,10 @@ import { Context, ExecutionContext } from '@mondaydotcomorg/trident-backend-api'
2
2
  export declare enum PlatformProfile {
3
3
  API_INTERNAL = "api-internal",
4
4
  SLOW = "slow",
5
- INTERNAL = "internal"
5
+ INTERNAL = "internal",
6
+ APP = "app"
6
7
  }
7
- export declare function getProfile(): PlatformProfile;
8
+ export declare function getProfile(): PlatformProfile.API_INTERNAL | PlatformProfile.SLOW | PlatformProfile.INTERNAL;
8
9
  export declare function getExecutionContext(context: Context): ExecutionContext;
9
10
  export declare function getAttributionsFromApi(): {
10
11
  [key: string]: string;
@@ -1 +1 @@
1
- {"version":3,"file":"attributions-service.d.ts","sourceRoot":"","sources":["../src/attributions-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAStF,oBAAY,eAAe;IACzB,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,QAAQ,aAAa;CACtB;AAED,wBAAgB,UAAU,oBAiBzB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAEtE;AAED,wBAAgB,sBAAsB,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAqClE"}
1
+ {"version":3,"file":"attributions-service.d.ts","sourceRoot":"","sources":["../src/attributions-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,OAAO,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAStF,oBAAY,eAAe;IACzB,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,GAAG,QAAQ;CACZ;AAED,wBAAgB,UAAU,mFAiBzB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAEtE;AAED,wBAAgB,sBAAsB,IAAI;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAqClE"}
@@ -12,6 +12,7 @@ exports.PlatformProfile = void 0;
12
12
  PlatformProfile["API_INTERNAL"] = "api-internal";
13
13
  PlatformProfile["SLOW"] = "slow";
14
14
  PlatformProfile["INTERNAL"] = "internal";
15
+ PlatformProfile["APP"] = "app";
15
16
  })(exports.PlatformProfile || (exports.PlatformProfile = {}));
16
17
  function getProfile() {
17
18
  const tridentContext = tridentBackendApi.Api.getPart('context');
@@ -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): void;
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;IAQzD,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
+ {"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"}
@@ -9,6 +9,11 @@ export interface AuthorizeResponse {
9
9
  }
10
10
  export declare function setRequestFetchOptions(customMondayFetchOptions: MondayFetchOptions): void;
11
11
  export declare class AuthorizationService {
12
+ private static get graphApi();
13
+ private static _graphApi?;
14
+ private static get platformApi();
15
+ private static _platformApi?;
16
+ static resetApiClients(): void;
12
17
  static redisClient?: any;
13
18
  static grantedFeatureRedisExpirationInSeconds?: number;
14
19
  static igniteClient?: IgniteClient;
@@ -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;AAE7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAe1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAMD,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;WAsBZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBA6DnB,oBAAoB;mBAUpB,oBAAoB;CAoF1C;AAED,wBAAgB,cAAc,CAC5B,MAAM,KAAA,EACN,sCAAsC,GAAE,MAAiD,QAY1F;AAED,wBAAsB,eAAe,kBAMpC;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAepG"}
1
+ {"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../src/authorization-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;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"}
@@ -5,10 +5,11 @@ const tridentBackendApi = require('@mondaydotcomorg/trident-backend-api');
5
5
  const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
6
6
  const igniteSdk = require('@mondaydotcomorg/ignite-sdk');
7
7
  const prometheusService = require('./prometheus-service.js');
8
+ const metricsService = require('./metrics-service.js');
8
9
  const authorizationInternalService = require('./authorization-internal-service.js');
9
10
  const attributionsService = require('./attributions-service.js');
10
- const clients_graphApi_client = require('./clients/graph-api.client.js');
11
- const clients_platformApi_client = require('./clients/platform-api.client.js');
11
+ const clients_graphApi = require('./clients/graph-api.js');
12
+ const clients_platformApi = require('./clients/platform-api.js');
12
13
  const utils_authorization_utils = require('./utils/authorization.utils.js');
13
14
 
14
15
  const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
@@ -21,6 +22,24 @@ function setRequestFetchOptions(customMondayFetchOptions) {
21
22
  authorizationInternalService.AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
22
23
  }
23
24
  class AuthorizationService {
25
+ static get graphApi() {
26
+ if (!this._graphApi) {
27
+ this._graphApi = new clients_graphApi.GraphApi();
28
+ }
29
+ return this._graphApi;
30
+ }
31
+ static _graphApi;
32
+ static get platformApi() {
33
+ if (!this._platformApi) {
34
+ this._platformApi = new clients_platformApi.PlatformApi();
35
+ }
36
+ return this._platformApi;
37
+ }
38
+ static _platformApi;
39
+ static resetApiClients() {
40
+ this._graphApi = undefined;
41
+ this._platformApi = undefined;
42
+ }
24
43
  static redisClient;
25
44
  static grantedFeatureRedisExpirationInSeconds;
26
45
  static igniteClient;
@@ -86,38 +105,25 @@ class AuthorizationService {
86
105
  this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId })) {
87
106
  return attributionsService.getProfile();
88
107
  }
89
- return attributionsService.PlatformProfile.INTERNAL;
108
+ return attributionsService.PlatformProfile.APP;
90
109
  }
91
110
  static async canActionInScopeMultiple(accountId, userId, scopedActions) {
92
111
  if (scopedActions.length === 0) {
93
112
  return [];
94
113
  }
95
114
  const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
96
- const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
97
115
  const startTime = perf_hooks.performance.now();
98
116
  let scopedActionResponseObjects;
99
117
  let apiType;
100
118
  if (shouldNavigateToGraph) {
101
- try {
102
- scopedActionResponseObjects = await clients_graphApi_client.GraphApiClient.checkPermissions(internalAuthToken, scopedActions);
103
- apiType = 'graph';
104
- }
105
- catch (error) {
106
- const status = error instanceof mondayFetchApi.HttpFetcherError ? error.status : undefined;
107
- authorizationInternalService.logger.warn({
108
- tag: 'authorization-service',
109
- error: error instanceof Error ? error.message : String(error),
110
- accountId,
111
- userId,
112
- status,
113
- }, 'Graph API authorization failed');
114
- throw error;
115
- }
119
+ apiType = 'graph';
120
+ scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
116
121
  }
117
122
  else {
118
- const profile = this.getProfile(accountId, userId);
119
- scopedActionResponseObjects = await clients_platformApi_client.PlatformApiClient.checkPermissions(profile, internalAuthToken, userId, scopedActions);
120
123
  apiType = 'platform';
124
+ const profile = this.getProfile(accountId, userId);
125
+ const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
126
+ scopedActionResponseObjects = await this.platformApi.checkPermissions(profile, internalAuthToken, userId, scopedActions);
121
127
  }
122
128
  const endTime = perf_hooks.performance.now();
123
129
  const time = endTime - startTime;
@@ -126,10 +132,8 @@ class AuthorizationService {
126
132
  const { action, scope } = obj.scopedAction;
127
133
  const { resourceType } = utils_authorization_utils.scopeToResource(scope);
128
134
  const isAuthorized = obj.permit.can;
129
- prometheusService.sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time, apiType);
130
- if (obj.permit.can) {
131
- prometheusService.incrementAuthorizationSuccess(resourceType, action, apiType);
132
- }
135
+ prometheusService.sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time);
136
+ metricsService.recordAuthorizationTiming(apiType, time, 'canActionInScopeMultiple');
133
137
  }
134
138
  return scopedActionResponseObjects;
135
139
  }
@@ -186,7 +190,7 @@ class AuthorizationService {
186
190
  if (!isAuthorized) {
187
191
  unauthorizedObjects.push(authorizationObject);
188
192
  }
189
- prometheusService.sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, 200, time, 'platform');
193
+ prometheusService.sendAuthorizationCheckResponseTimeMetric(authorizationObject.resource_type, authorizationObject.action, isAuthorized, 200, time);
190
194
  });
191
195
  if (unauthorizedObjects.length > 0) {
192
196
  authorizationInternalService.logger.info({
@@ -0,0 +1,28 @@
1
+ import { ScopedAction, ScopedActionResponseObject } from '../types/scoped-actions-contracts';
2
+ import { GraphIsAllowedResponse } from '../types/graph-api.types';
3
+ /**
4
+ * Client for handling Graph API authorization operations
5
+ */
6
+ export declare class GraphApi {
7
+ private readonly httpClient;
8
+ private readonly consumerAppName;
9
+ constructor();
10
+ /**
11
+ * Builds the request body for Graph API calls
12
+ */
13
+ private static buildRequestBody;
14
+ /**
15
+ * Fetches authorization data from the Graph API
16
+ */
17
+ fetchPermissions(authToken: string, scopedActions: ScopedAction[]): Promise<GraphIsAllowedResponse>;
18
+ /**
19
+ * Maps Graph API response to the expected format
20
+ */
21
+ private static mapResponse;
22
+ /**
23
+ * Performs a complete authorization check using the Graph API
24
+ */
25
+ checkPermissions(accountId: number, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
26
+ private static ensureGraphReason;
27
+ }
28
+ //# sourceMappingURL=graph-api.d.ts.map
@@ -0,0 +1 @@
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,18 +1,34 @@
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 prometheusService = require('../prometheus-service.js');
8
+ const mondayJwt = require('@mondaydotcomorg/monday-jwt');
9
+ const constants = require('../constants.js');
10
+ const utils_apiErrorHandler = require('../utils/api-error-handler.js');
10
11
 
11
12
  const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
13
+ const APP_NAME_REQUIRED_ERROR = 'GraphApi: APP_NAME environment variable is required for Graph API authentication';
12
14
  /**
13
15
  * Client for handling Graph API authorization operations
14
16
  */
15
- class GraphApiClient {
17
+ class GraphApi {
18
+ httpClient;
19
+ consumerAppName;
20
+ constructor() {
21
+ const httpClient = tridentBackendApi.Api.getPart('httpClient');
22
+ if (!httpClient) {
23
+ throw new Error('GraphApi: http client is not initialized');
24
+ }
25
+ const consumerAppName = process.env.APP_NAME?.trim();
26
+ if (!consumerAppName) {
27
+ throw new Error(APP_NAME_REQUIRED_ERROR);
28
+ }
29
+ this.httpClient = httpClient;
30
+ this.consumerAppName = consumerAppName;
31
+ }
16
32
  /**
17
33
  * Builds the request body for Graph API calls
18
34
  */
@@ -41,19 +57,18 @@ class GraphApiClient {
41
57
  /**
42
58
  * Fetches authorization data from the Graph API
43
59
  */
44
- static async fetchPermissions(internalAuthToken, scopedActions) {
45
- const httpClient = tridentBackendApi.Api.getPart('httpClient');
60
+ async fetchPermissions(authToken, scopedActions) {
46
61
  const attributionHeaders = attributionsService.getAttributionsFromApi();
47
- const bodyPayload = this.buildRequestBody(scopedActions);
62
+ const bodyPayload = GraphApi.buildRequestBody(scopedActions);
48
63
  try {
49
- const response = await httpClient.fetch({
64
+ const response = await this.httpClient.fetch({
50
65
  url: {
51
- appName: 'authorization-graph',
66
+ appName: constants.GRAPH_APP_NAME,
52
67
  path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
53
68
  },
54
69
  method: 'POST',
55
70
  headers: {
56
- Authorization: internalAuthToken,
71
+ Authorization: authToken,
57
72
  'Content-Type': 'application/json',
58
73
  ...attributionHeaders,
59
74
  },
@@ -65,13 +80,8 @@ class GraphApiClient {
65
80
  return response;
66
81
  }
67
82
  catch (err) {
68
- if (err instanceof mondayFetchApi.HttpFetcherError) {
69
- authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
70
- if (scopedActions.length > 0) {
71
- prometheusService.incrementAuthorizationError(utils_authorization_utils.scopeToResource(scopedActions[0].scope).resourceType, scopedActions[0].action, err.status, 'graph');
72
- }
73
- }
74
- throw err;
83
+ // handleApiError never returns (throws)
84
+ return utils_apiErrorHandler.handleApiError(err, 'graph', 'canActionInScopeMultiple');
75
85
  }
76
86
  }
77
87
  /**
@@ -83,41 +93,39 @@ class GraphApiClient {
83
93
  const { action, scope } = scopedAction;
84
94
  const { resourceType, resourceId } = utils_authorization_utils.scopeToResource(scope);
85
95
  const permissionResult = resources?.[resourceType]?.[String(resourceId)]?.[action];
86
- const graphReason = permissionResult?.reason;
87
- let reasonKey;
88
- let additionalOptions = {};
89
- let technicalReason = types_scopedActionsContracts.PermitTechnicalReason.NO_REASON;
90
- if (typeof graphReason === 'string') {
91
- reasonKey = graphReason;
92
- }
93
- else if (graphReason && typeof graphReason === 'object') {
94
- reasonKey = graphReason.key ?? 'unknown';
95
- additionalOptions = graphReason.additionalOptions ?? {};
96
- if (graphReason.technicalReason !== undefined) {
97
- technicalReason = (graphReason.technicalReason ?? types_scopedActionsContracts.PermitTechnicalReason.NO_REASON);
98
- }
99
- }
100
- else {
101
- reasonKey = 'unknown';
102
- }
103
96
  const permit = {
104
97
  can: permissionResult?.can ?? false,
105
98
  reason: {
106
- key: reasonKey,
107
- ...additionalOptions,
99
+ key: 'unknown',
108
100
  },
109
- technicalReason,
101
+ technicalReason: types_scopedActionsContracts.PermitTechnicalReason.NO_REASON,
110
102
  };
103
+ if (permissionResult) {
104
+ const graphReason = GraphApi.ensureGraphReason(permissionResult.reason, { resourceType, resourceId, action });
105
+ permit.reason = {
106
+ key: graphReason.key,
107
+ ...(graphReason.additionalOptions ?? {}),
108
+ };
109
+ permit.technicalReason = (graphReason.technicalReason ??
110
+ types_scopedActionsContracts.PermitTechnicalReason.NO_REASON);
111
+ }
111
112
  return { scopedAction, permit };
112
113
  });
113
114
  }
114
115
  /**
115
116
  * Performs a complete authorization check using the Graph API
116
117
  */
117
- static async checkPermissions(internalAuthToken, scopedActions) {
118
- const response = await this.fetchPermissions(internalAuthToken, scopedActions);
119
- return this.mapResponse(scopedActions, response);
118
+ async checkPermissions(accountId, userId, scopedActions) {
119
+ const authToken = mondayJwt.signAuthorizationHeader({ appName: this.consumerAppName, accountId, userId });
120
+ const response = await this.fetchPermissions(authToken, scopedActions);
121
+ return GraphApi.mapResponse(scopedActions, response);
122
+ }
123
+ static ensureGraphReason(reason, context) {
124
+ if (!reason || typeof reason !== 'object' || typeof reason.key !== 'string') {
125
+ throw new Error(`GraphApi: unexpected reason format for ${context.resourceType}/${context.resourceId}/${context.action}`);
126
+ }
127
+ return reason;
120
128
  }
121
129
  }
122
130
 
123
- exports.GraphApiClient = GraphApiClient;
131
+ exports.GraphApi = GraphApi;
@@ -0,0 +1,26 @@
1
+ import { ScopedAction, ScopedActionResponseObject } from '../types/scoped-actions-contracts';
2
+ import { PlatformProfile } from '../attributions-service';
3
+ /**
4
+ * Client for handling Platform API authorization operations
5
+ */
6
+ export declare class PlatformApi {
7
+ private readonly httpClient;
8
+ constructor();
9
+ /**
10
+ * Builds the request payload for Platform API calls
11
+ */
12
+ private static buildRequestPayload;
13
+ /**
14
+ * Fetches authorization data from the Platform API
15
+ */
16
+ private fetchPermissions;
17
+ /**
18
+ * Maps Platform API response to the expected format
19
+ */
20
+ private static mapResponse;
21
+ /**
22
+ * Performs a complete authorization check using the Platform API
23
+ */
24
+ checkPermissions(profile: PlatformProfile, internalAuthToken: string, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
25
+ }
26
+ //# sourceMappingURL=platform-api.d.ts.map
@@ -0,0 +1 @@
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"}