@mondaydotcomorg/monday-authorization 3.3.0-feat-add-graph-api-routing-support-2d70b30 → 3.3.0-feat-add-graph-api-routing-support-c37c919

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 (50) hide show
  1. package/README.md +4 -0
  2. package/dist/authorization-service.d.ts +4 -0
  3. package/dist/authorization-service.d.ts.map +1 -1
  4. package/dist/authorization-service.js +21 -5
  5. package/dist/clients/graph-api.d.ts +27 -0
  6. package/dist/clients/graph-api.d.ts.map +1 -0
  7. package/dist/clients/{graph-api.client.js → graph-api.js} +34 -30
  8. package/dist/clients/platform-api.d.ts +26 -0
  9. package/dist/clients/platform-api.d.ts.map +1 -0
  10. package/dist/clients/{platform-api.client.js → platform-api.js} +19 -13
  11. package/dist/esm/authorization-service.d.ts +4 -0
  12. package/dist/esm/authorization-service.d.ts.map +1 -1
  13. package/dist/esm/authorization-service.mjs +22 -6
  14. package/dist/esm/clients/graph-api.d.ts +27 -0
  15. package/dist/esm/clients/graph-api.d.ts.map +1 -0
  16. package/dist/esm/clients/{graph-api.client.mjs → graph-api.mjs} +34 -30
  17. package/dist/esm/clients/platform-api.d.ts +26 -0
  18. package/dist/esm/clients/platform-api.d.ts.map +1 -0
  19. package/dist/esm/clients/{platform-api.client.mjs → platform-api.mjs} +20 -14
  20. package/dist/esm/index.d.ts +6 -0
  21. package/dist/esm/index.d.ts.map +1 -1
  22. package/dist/esm/index.mjs +7 -0
  23. package/dist/esm/metrics-service.d.ts +13 -0
  24. package/dist/esm/metrics-service.d.ts.map +1 -0
  25. package/dist/esm/metrics-service.mjs +65 -0
  26. package/dist/esm/prometheus-service.d.ts +0 -2
  27. package/dist/esm/prometheus-service.d.ts.map +1 -1
  28. package/dist/esm/prometheus-service.mjs +4 -50
  29. package/dist/esm/types/graph-api.types.d.ts +8 -7
  30. package/dist/esm/types/graph-api.types.d.ts.map +1 -1
  31. package/dist/index.d.ts +6 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +7 -0
  34. package/dist/metrics-service.d.ts +13 -0
  35. package/dist/metrics-service.d.ts.map +1 -0
  36. package/dist/metrics-service.js +70 -0
  37. package/dist/prometheus-service.d.ts +0 -2
  38. package/dist/prometheus-service.d.ts.map +1 -1
  39. package/dist/prometheus-service.js +3 -51
  40. package/dist/types/graph-api.types.d.ts +8 -7
  41. package/dist/types/graph-api.types.d.ts.map +1 -1
  42. package/package.json +2 -1
  43. package/dist/clients/graph-api.client.d.ts +0 -24
  44. package/dist/clients/graph-api.client.d.ts.map +0 -1
  45. package/dist/clients/platform-api.client.d.ts +0 -31
  46. package/dist/clients/platform-api.client.d.ts.map +0 -1
  47. package/dist/esm/clients/graph-api.client.d.ts +0 -24
  48. package/dist/esm/clients/graph-api.client.d.ts.map +0 -1
  49. package/dist/esm/clients/platform-api.client.d.ts +0 -31
  50. package/dist/esm/clients/platform-api.client.d.ts.map +0 -1
package/README.md CHANGED
@@ -27,6 +27,9 @@ import * as MondayAuthorization from '@mondaydotcomorg/monday-authorization';
27
27
 
28
28
  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,7 @@ 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`).
39
43
 
40
44
  ## Usage
41
45
 
@@ -9,6 +9,10 @@ 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?;
12
16
  static redisClient?: any;
13
17
  static grantedFeatureRedisExpirationInSeconds?: number;
14
18
  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,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;mBA8DnB,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,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,20 @@ 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;
24
39
  static redisClient;
25
40
  static grantedFeatureRedisExpirationInSeconds;
26
41
  static igniteClient;
@@ -99,7 +114,7 @@ class AuthorizationService {
99
114
  let apiType;
100
115
  if (shouldNavigateToGraph) {
101
116
  try {
102
- scopedActionResponseObjects = await clients_graphApi_client.GraphApiClient.checkPermissions(internalAuthToken, scopedActions);
117
+ scopedActionResponseObjects = await this.graphApi.checkPermissions(internalAuthToken, scopedActions);
103
118
  apiType = 'graph';
104
119
  }
105
120
  catch (error) {
@@ -116,7 +131,7 @@ class AuthorizationService {
116
131
  }
117
132
  else {
118
133
  const profile = this.getProfile(accountId, userId);
119
- scopedActionResponseObjects = await clients_platformApi_client.PlatformApiClient.checkPermissions(profile, internalAuthToken, userId, scopedActions);
134
+ scopedActionResponseObjects = await this.platformApi.checkPermissions(profile, internalAuthToken, userId, scopedActions);
120
135
  apiType = 'platform';
121
136
  }
122
137
  const endTime = perf_hooks.performance.now();
@@ -127,8 +142,9 @@ class AuthorizationService {
127
142
  const { resourceType } = utils_authorization_utils.scopeToResource(scope);
128
143
  const isAuthorized = obj.permit.can;
129
144
  prometheusService.sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time, apiType);
145
+ metricsService.recordAuthorizationTiming(apiType, time);
130
146
  if (obj.permit.can) {
131
- prometheusService.incrementAuthorizationSuccess(resourceType, action, apiType);
147
+ metricsService.recordAuthorizationSuccess(apiType);
132
148
  }
133
149
  }
134
150
  return scopedActionResponseObjects;
@@ -0,0 +1,27 @@
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
+ constructor();
9
+ /**
10
+ * Builds the request body for Graph API calls
11
+ */
12
+ private static buildRequestBody;
13
+ /**
14
+ * Fetches authorization data from the Graph API
15
+ */
16
+ fetchPermissions(internalAuthToken: string, scopedActions: ScopedAction[]): Promise<GraphIsAllowedResponse>;
17
+ /**
18
+ * Maps Graph API response to the expected format
19
+ */
20
+ private static mapResponse;
21
+ /**
22
+ * Performs a complete authorization check using the Graph API
23
+ */
24
+ checkPermissions(internalAuthToken: string, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
25
+ private static ensureGraphReason;
26
+ }
27
+ //# 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":"AAEA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEL,sBAAsB,EAMvB,MAAM,0BAA0B,CAAC;AAMlC;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;;IAUxC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAyB/B;;OAEG;IACG,gBAAgB,CAAC,iBAAiB,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAqCjH;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAiC1B;;OAEG;IACG,gBAAgB,CACpB,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAKxC,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAWjC"}
@@ -6,13 +6,21 @@ const types_scopedActionsContracts = require('../types/scoped-actions-contracts.
6
6
  const authorizationInternalService = require('../authorization-internal-service.js');
7
7
  const attributionsService = require('../attributions-service.js');
8
8
  const utils_authorization_utils = require('../utils/authorization.utils.js');
9
- const prometheusService = require('../prometheus-service.js');
9
+ const metricsService = require('../metrics-service.js');
10
10
 
11
11
  const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
12
12
  /**
13
13
  * Client for handling Graph API authorization operations
14
14
  */
15
- class GraphApiClient {
15
+ class GraphApi {
16
+ httpClient;
17
+ constructor() {
18
+ const httpClient = tridentBackendApi.Api.getPart('httpClient');
19
+ if (!httpClient) {
20
+ throw new Error('GraphApi: http client is not initialized');
21
+ }
22
+ this.httpClient = httpClient;
23
+ }
16
24
  /**
17
25
  * Builds the request body for Graph API calls
18
26
  */
@@ -41,12 +49,11 @@ class GraphApiClient {
41
49
  /**
42
50
  * Fetches authorization data from the Graph API
43
51
  */
44
- static async fetchPermissions(internalAuthToken, scopedActions) {
45
- const httpClient = tridentBackendApi.Api.getPart('httpClient');
52
+ async fetchPermissions(internalAuthToken, scopedActions) {
46
53
  const attributionHeaders = attributionsService.getAttributionsFromApi();
47
- const bodyPayload = this.buildRequestBody(scopedActions);
54
+ const bodyPayload = GraphApi.buildRequestBody(scopedActions);
48
55
  try {
49
- const response = await httpClient.fetch({
56
+ const response = await this.httpClient.fetch({
50
57
  url: {
51
58
  appName: 'authorization-graph',
52
59
  path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
@@ -68,7 +75,7 @@ class GraphApiClient {
68
75
  if (err instanceof mondayFetchApi.HttpFetcherError) {
69
76
  authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
70
77
  if (scopedActions.length > 0) {
71
- prometheusService.incrementAuthorizationError(utils_authorization_utils.scopeToResource(scopedActions[0].scope).resourceType, scopedActions[0].action, err.status, 'graph');
78
+ metricsService.recordAuthorizationError('graph', err.status);
72
79
  }
73
80
  }
74
81
  throw err;
@@ -83,41 +90,38 @@ class GraphApiClient {
83
90
  const { action, scope } = scopedAction;
84
91
  const { resourceType, resourceId } = utils_authorization_utils.scopeToResource(scope);
85
92
  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
93
  const permit = {
104
94
  can: permissionResult?.can ?? false,
105
95
  reason: {
106
- key: reasonKey,
107
- ...additionalOptions,
96
+ key: 'unknown',
108
97
  },
109
- technicalReason,
98
+ technicalReason: types_scopedActionsContracts.PermitTechnicalReason.NO_REASON,
110
99
  };
100
+ if (permissionResult) {
101
+ const graphReason = GraphApi.ensureGraphReason(permissionResult.reason, { resourceType, resourceId, action });
102
+ permit.reason = {
103
+ key: graphReason.key,
104
+ ...(graphReason.additionalOptions ?? {}),
105
+ };
106
+ permit.technicalReason = (graphReason.technicalReason ??
107
+ types_scopedActionsContracts.PermitTechnicalReason.NO_REASON);
108
+ }
111
109
  return { scopedAction, permit };
112
110
  });
113
111
  }
114
112
  /**
115
113
  * Performs a complete authorization check using the Graph API
116
114
  */
117
- static async checkPermissions(internalAuthToken, scopedActions) {
115
+ async checkPermissions(internalAuthToken, scopedActions) {
118
116
  const response = await this.fetchPermissions(internalAuthToken, scopedActions);
119
- return this.mapResponse(scopedActions, response);
117
+ return GraphApi.mapResponse(scopedActions, response);
118
+ }
119
+ static ensureGraphReason(reason, context) {
120
+ if (!reason || typeof reason !== 'object' || typeof reason.key !== 'string') {
121
+ throw new Error(`GraphApi: unexpected reason format for ${context.resourceType}/${context.resourceId}/${context.action}`);
122
+ }
123
+ return reason;
120
124
  }
121
125
  }
122
126
 
123
- exports.GraphApiClient = GraphApiClient;
127
+ 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":"AAEA,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;IA0C9B;;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"}
@@ -5,13 +5,21 @@ const mondayFetchApi = require('@mondaydotcomorg/monday-fetch-api');
5
5
  const authorizationInternalService = require('../authorization-internal-service.js');
6
6
  const attributionsService = require('../attributions-service.js');
7
7
  const utils_authorization_utils = require('../utils/authorization.utils.js');
8
- const prometheusService = require('../prometheus-service.js');
8
+ const metricsService = require('../metrics-service.js');
9
9
 
10
10
  const PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH = '/internal_ms/authorization/can_actions_in_scopes';
11
11
  /**
12
12
  * Client for handling Platform API authorization operations
13
13
  */
14
- class PlatformApiClient {
14
+ class PlatformApi {
15
+ httpClient;
16
+ constructor() {
17
+ const httpClient = tridentBackendApi.Api.getPart('httpClient');
18
+ if (!httpClient) {
19
+ throw new Error('PlatformApi: http client is not initialized');
20
+ }
21
+ this.httpClient = httpClient;
22
+ }
15
23
  /**
16
24
  * Builds the request payload for Platform API calls
17
25
  */
@@ -24,11 +32,10 @@ class PlatformApiClient {
24
32
  /**
25
33
  * Fetches authorization data from the Platform API
26
34
  */
27
- static async fetchPermissions(profile, internalAuthToken, userId, scopedActionsPayload) {
35
+ async fetchPermissions(profile, internalAuthToken, userId, scopedActionsPayload) {
28
36
  const attributionHeaders = attributionsService.getAttributionsFromApi();
29
- const httpClient = tridentBackendApi.Api.getPart('httpClient');
30
37
  try {
31
- const response = await httpClient.fetch({
38
+ const response = await this.httpClient.fetch({
32
39
  url: {
33
40
  appName: 'platform',
34
41
  path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
@@ -51,8 +58,7 @@ class PlatformApiClient {
51
58
  if (err instanceof mondayFetchApi.HttpFetcherError) {
52
59
  authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
53
60
  if (scopedActionsPayload.length > 0) {
54
- const { resourceType } = utils_authorization_utils.scopeToResource(utils_authorization_utils.toCamelCase(scopedActionsPayload[0].scope));
55
- prometheusService.incrementAuthorizationError(resourceType, scopedActionsPayload[0].action, err.status, 'platform');
61
+ metricsService.recordAuthorizationError('platform', err.status);
56
62
  }
57
63
  }
58
64
  throw err;
@@ -63,8 +69,8 @@ class PlatformApiClient {
63
69
  */
64
70
  static mapResponse(response) {
65
71
  if (!response) {
66
- authorizationInternalService.logger.error({ tag: 'platform-api-client', response }, 'PlatformApiClient: missing response');
67
- throw new Error('PlatformApiClient: missing response');
72
+ authorizationInternalService.logger.error({ tag: 'platform-api', response }, 'PlatformApi: missing response');
73
+ throw new Error('PlatformApi: missing response');
68
74
  }
69
75
  return response.result.map(responseObject => {
70
76
  const { scopedAction, permit } = responseObject;
@@ -79,11 +85,11 @@ class PlatformApiClient {
79
85
  /**
80
86
  * Performs a complete authorization check using the Platform API
81
87
  */
82
- static async checkPermissions(profile, internalAuthToken, userId, scopedActions) {
83
- const scopedActionsPayload = this.buildRequestPayload(scopedActions);
88
+ async checkPermissions(profile, internalAuthToken, userId, scopedActions) {
89
+ const scopedActionsPayload = PlatformApi.buildRequestPayload(scopedActions);
84
90
  const platformResponse = await this.fetchPermissions(profile, internalAuthToken, userId, scopedActionsPayload);
85
- return this.mapResponse(platformResponse);
91
+ return PlatformApi.mapResponse(platformResponse);
86
92
  }
87
93
  }
88
94
 
89
- exports.PlatformApiClient = PlatformApiClient;
95
+ exports.PlatformApi = PlatformApi;
@@ -9,6 +9,10 @@ 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?;
12
16
  static redisClient?: any;
13
17
  static grantedFeatureRedisExpirationInSeconds?: number;
14
18
  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,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;mBA8DnB,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"}
@@ -2,11 +2,12 @@ import { performance } from 'perf_hooks';
2
2
  import { Api } from '@mondaydotcomorg/trident-backend-api';
3
3
  import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
4
4
  import { getIgniteClient } from '@mondaydotcomorg/ignite-sdk';
5
- import { sendAuthorizationCheckResponseTimeMetric, incrementAuthorizationSuccess } from './prometheus-service.mjs';
5
+ import { sendAuthorizationCheckResponseTimeMetric } from './prometheus-service.mjs';
6
+ import { recordAuthorizationTiming, recordAuthorizationSuccess } from './metrics-service.mjs';
6
7
  import { AuthorizationInternalService, logger } from './authorization-internal-service.mjs';
7
8
  import { getProfile, PlatformProfile, getAttributionsFromApi } from './attributions-service.mjs';
8
- import { GraphApiClient } from './clients/graph-api.client.mjs';
9
- import { PlatformApiClient } from './clients/platform-api.client.mjs';
9
+ import { GraphApi } from './clients/graph-api.mjs';
10
+ import { PlatformApi } from './clients/platform-api.mjs';
10
11
  import { scopeToResource } from './utils/authorization.utils.mjs';
11
12
 
12
13
  const GRANTED_FEATURE_CACHE_EXPIRATION_SECONDS = 5 * 60;
@@ -19,6 +20,20 @@ function setRequestFetchOptions(customMondayFetchOptions) {
19
20
  AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
20
21
  }
21
22
  class AuthorizationService {
23
+ static get graphApi() {
24
+ if (!this._graphApi) {
25
+ this._graphApi = new GraphApi();
26
+ }
27
+ return this._graphApi;
28
+ }
29
+ static _graphApi;
30
+ static get platformApi() {
31
+ if (!this._platformApi) {
32
+ this._platformApi = new PlatformApi();
33
+ }
34
+ return this._platformApi;
35
+ }
36
+ static _platformApi;
22
37
  static redisClient;
23
38
  static grantedFeatureRedisExpirationInSeconds;
24
39
  static igniteClient;
@@ -97,7 +112,7 @@ class AuthorizationService {
97
112
  let apiType;
98
113
  if (shouldNavigateToGraph) {
99
114
  try {
100
- scopedActionResponseObjects = await GraphApiClient.checkPermissions(internalAuthToken, scopedActions);
115
+ scopedActionResponseObjects = await this.graphApi.checkPermissions(internalAuthToken, scopedActions);
101
116
  apiType = 'graph';
102
117
  }
103
118
  catch (error) {
@@ -114,7 +129,7 @@ class AuthorizationService {
114
129
  }
115
130
  else {
116
131
  const profile = this.getProfile(accountId, userId);
117
- scopedActionResponseObjects = await PlatformApiClient.checkPermissions(profile, internalAuthToken, userId, scopedActions);
132
+ scopedActionResponseObjects = await this.platformApi.checkPermissions(profile, internalAuthToken, userId, scopedActions);
118
133
  apiType = 'platform';
119
134
  }
120
135
  const endTime = performance.now();
@@ -125,8 +140,9 @@ class AuthorizationService {
125
140
  const { resourceType } = scopeToResource(scope);
126
141
  const isAuthorized = obj.permit.can;
127
142
  sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time, apiType);
143
+ recordAuthorizationTiming(apiType, time);
128
144
  if (obj.permit.can) {
129
- incrementAuthorizationSuccess(resourceType, action, apiType);
145
+ recordAuthorizationSuccess(apiType);
130
146
  }
131
147
  }
132
148
  return scopedActionResponseObjects;
@@ -0,0 +1,27 @@
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
+ constructor();
9
+ /**
10
+ * Builds the request body for Graph API calls
11
+ */
12
+ private static buildRequestBody;
13
+ /**
14
+ * Fetches authorization data from the Graph API
15
+ */
16
+ fetchPermissions(internalAuthToken: string, scopedActions: ScopedAction[]): Promise<GraphIsAllowedResponse>;
17
+ /**
18
+ * Maps Graph API response to the expected format
19
+ */
20
+ private static mapResponse;
21
+ /**
22
+ * Performs a complete authorization check using the Graph API
23
+ */
24
+ checkPermissions(internalAuthToken: string, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
25
+ private static ensureGraphReason;
26
+ }
27
+ //# 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":"AAEA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAEL,sBAAsB,EAMvB,MAAM,0BAA0B,CAAC;AAMlC;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;;IAUxC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAyB/B;;OAEG;IACG,gBAAgB,CAAC,iBAAiB,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAqCjH;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAiC1B;;OAEG;IACG,gBAAgB,CACpB,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAKxC,OAAO,CAAC,MAAM,CAAC,iBAAiB;CAWjC"}
@@ -4,13 +4,21 @@ import { PermitTechnicalReason } from '../types/scoped-actions-contracts.mjs';
4
4
  import { AuthorizationInternalService } from '../authorization-internal-service.mjs';
5
5
  import { getAttributionsFromApi } from '../attributions-service.mjs';
6
6
  import { scopeToResource } from '../utils/authorization.utils.mjs';
7
- import { incrementAuthorizationError } from '../prometheus-service.mjs';
7
+ import { recordAuthorizationError } from '../metrics-service.mjs';
8
8
 
9
9
  const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
10
10
  /**
11
11
  * Client for handling Graph API authorization operations
12
12
  */
13
- class GraphApiClient {
13
+ class GraphApi {
14
+ httpClient;
15
+ constructor() {
16
+ const httpClient = Api.getPart('httpClient');
17
+ if (!httpClient) {
18
+ throw new Error('GraphApi: http client is not initialized');
19
+ }
20
+ this.httpClient = httpClient;
21
+ }
14
22
  /**
15
23
  * Builds the request body for Graph API calls
16
24
  */
@@ -39,12 +47,11 @@ class GraphApiClient {
39
47
  /**
40
48
  * Fetches authorization data from the Graph API
41
49
  */
42
- static async fetchPermissions(internalAuthToken, scopedActions) {
43
- const httpClient = Api.getPart('httpClient');
50
+ async fetchPermissions(internalAuthToken, scopedActions) {
44
51
  const attributionHeaders = getAttributionsFromApi();
45
- const bodyPayload = this.buildRequestBody(scopedActions);
52
+ const bodyPayload = GraphApi.buildRequestBody(scopedActions);
46
53
  try {
47
- const response = await httpClient.fetch({
54
+ const response = await this.httpClient.fetch({
48
55
  url: {
49
56
  appName: 'authorization-graph',
50
57
  path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
@@ -66,7 +73,7 @@ class GraphApiClient {
66
73
  if (err instanceof HttpFetcherError) {
67
74
  AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
68
75
  if (scopedActions.length > 0) {
69
- incrementAuthorizationError(scopeToResource(scopedActions[0].scope).resourceType, scopedActions[0].action, err.status, 'graph');
76
+ recordAuthorizationError('graph', err.status);
70
77
  }
71
78
  }
72
79
  throw err;
@@ -81,41 +88,38 @@ class GraphApiClient {
81
88
  const { action, scope } = scopedAction;
82
89
  const { resourceType, resourceId } = scopeToResource(scope);
83
90
  const permissionResult = resources?.[resourceType]?.[String(resourceId)]?.[action];
84
- const graphReason = permissionResult?.reason;
85
- let reasonKey;
86
- let additionalOptions = {};
87
- let technicalReason = PermitTechnicalReason.NO_REASON;
88
- if (typeof graphReason === 'string') {
89
- reasonKey = graphReason;
90
- }
91
- else if (graphReason && typeof graphReason === 'object') {
92
- reasonKey = graphReason.key ?? 'unknown';
93
- additionalOptions = graphReason.additionalOptions ?? {};
94
- if (graphReason.technicalReason !== undefined) {
95
- technicalReason = (graphReason.technicalReason ?? PermitTechnicalReason.NO_REASON);
96
- }
97
- }
98
- else {
99
- reasonKey = 'unknown';
100
- }
101
91
  const permit = {
102
92
  can: permissionResult?.can ?? false,
103
93
  reason: {
104
- key: reasonKey,
105
- ...additionalOptions,
94
+ key: 'unknown',
106
95
  },
107
- technicalReason,
96
+ technicalReason: PermitTechnicalReason.NO_REASON,
108
97
  };
98
+ if (permissionResult) {
99
+ const graphReason = GraphApi.ensureGraphReason(permissionResult.reason, { resourceType, resourceId, action });
100
+ permit.reason = {
101
+ key: graphReason.key,
102
+ ...(graphReason.additionalOptions ?? {}),
103
+ };
104
+ permit.technicalReason = (graphReason.technicalReason ??
105
+ PermitTechnicalReason.NO_REASON);
106
+ }
109
107
  return { scopedAction, permit };
110
108
  });
111
109
  }
112
110
  /**
113
111
  * Performs a complete authorization check using the Graph API
114
112
  */
115
- static async checkPermissions(internalAuthToken, scopedActions) {
113
+ async checkPermissions(internalAuthToken, scopedActions) {
116
114
  const response = await this.fetchPermissions(internalAuthToken, scopedActions);
117
- return this.mapResponse(scopedActions, response);
115
+ return GraphApi.mapResponse(scopedActions, response);
116
+ }
117
+ static ensureGraphReason(reason, context) {
118
+ if (!reason || typeof reason !== 'object' || typeof reason.key !== 'string') {
119
+ throw new Error(`GraphApi: unexpected reason format for ${context.resourceType}/${context.resourceId}/${context.action}`);
120
+ }
121
+ return reason;
118
122
  }
119
123
  }
120
124
 
121
- export { GraphApiClient };
125
+ export { 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":"AAEA,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;IA0C9B;;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"}