@mondaydotcomorg/monday-authorization 3.3.0-feature-bashanye-navigate-can-action-in-scope-to-graph-7ce3f8a → 3.3.0-feature-bashanye-navigate-can-action-in-scope-to-graph-0a3cfd6
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/dist/authorization-service.d.ts.map +1 -1
- package/dist/authorization-service.js +28 -2
- package/dist/clients/graph-api.client.d.ts.map +1 -1
- package/dist/clients/graph-api.client.js +21 -1
- package/dist/clients/platform-api.client.d.ts.map +1 -1
- package/dist/clients/platform-api.client.js +24 -1
- package/dist/esm/authorization-service.d.ts.map +1 -1
- package/dist/esm/authorization-service.mjs +28 -2
- package/dist/esm/clients/graph-api.client.d.ts.map +1 -1
- package/dist/esm/clients/graph-api.client.mjs +22 -2
- package/dist/esm/clients/platform-api.client.d.ts.map +1 -1
- package/dist/esm/clients/platform-api.client.mjs +25 -2
- package/dist/esm/testKit/index.d.ts.map +1 -1
- package/dist/esm/testKit/index.mjs +9 -7
- package/dist/esm/utils/authorization.utils.d.ts.map +1 -1
- package/dist/esm/utils/authorization.utils.mjs +12 -0
- package/dist/testKit/index.d.ts.map +1 -1
- package/dist/testKit/index.js +9 -7
- package/dist/utils/authorization.utils.d.ts.map +1 -1
- package/dist/utils/authorization.utils.js +12 -0
- package/package.json +1 -1
|
@@ -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;
|
|
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;mBA6FnB,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"}
|
|
@@ -89,20 +89,46 @@ class AuthorizationService {
|
|
|
89
89
|
return attributionsService.PlatformProfile.INTERNAL;
|
|
90
90
|
}
|
|
91
91
|
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
92
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-service', accountId, userId, scopedActionsCount: scopedActions.length }, 'canActionInScopeMultiple called');
|
|
92
93
|
const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
|
|
94
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-service', accountId, userId, shouldNavigateToGraph }, `Graph API routing feature flag: ${shouldNavigateToGraph ? 'ENABLED' : 'DISABLED'}`);
|
|
93
95
|
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
94
96
|
const startTime = perf_hooks.performance.now();
|
|
95
97
|
let scopedActionResponseObjects;
|
|
98
|
+
let usedGraphApi = false;
|
|
96
99
|
if (shouldNavigateToGraph) {
|
|
97
|
-
|
|
100
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-service', accountId, userId }, 'Attempting Graph API authorization');
|
|
101
|
+
try {
|
|
102
|
+
scopedActionResponseObjects = await clients_graphApi_client.GraphApiClient.checkPermissions(internalAuthToken, scopedActions);
|
|
103
|
+
usedGraphApi = true;
|
|
104
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-service', accountId, userId, resultCount: scopedActionResponseObjects.length }, 'Graph API authorization successful');
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
// Fallback to Platform API if Graph API fails
|
|
108
|
+
authorizationInternalService.logger.warn({
|
|
109
|
+
tag: 'authorization-service',
|
|
110
|
+
error: error instanceof Error ? error.message : String(error),
|
|
111
|
+
accountId,
|
|
112
|
+
userId,
|
|
113
|
+
}, 'Graph API authorization failed, falling back to Platform API');
|
|
114
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-service', accountId, userId }, 'Starting Platform API fallback');
|
|
115
|
+
const profile = this.getProfile(accountId, userId);
|
|
116
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-service', accountId, userId, profile }, 'Retrieved Platform API profile for fallback');
|
|
117
|
+
scopedActionResponseObjects = await clients_platformApi_client.PlatformApiClient.checkPermissions(profile, internalAuthToken, userId, scopedActions);
|
|
118
|
+
usedGraphApi = false;
|
|
119
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-service', accountId, userId, resultCount: scopedActionResponseObjects.length }, 'Platform API fallback successful');
|
|
120
|
+
}
|
|
98
121
|
}
|
|
99
122
|
else {
|
|
123
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-service', accountId, userId }, 'Using Platform API directly (Graph API FF disabled)');
|
|
100
124
|
const profile = this.getProfile(accountId, userId);
|
|
125
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-service', accountId, userId, profile }, 'Retrieved Platform API profile');
|
|
101
126
|
scopedActionResponseObjects = await clients_platformApi_client.PlatformApiClient.checkPermissions(profile, internalAuthToken, userId, scopedActions);
|
|
127
|
+
usedGraphApi = false;
|
|
102
128
|
}
|
|
103
129
|
const endTime = perf_hooks.performance.now();
|
|
104
130
|
const time = endTime - startTime;
|
|
105
|
-
const apiType =
|
|
131
|
+
const apiType = usedGraphApi ? 'graph' : 'platform';
|
|
106
132
|
// Record metrics for each authorization check
|
|
107
133
|
for (const obj of scopedActionResponseObjects) {
|
|
108
134
|
const { action, scope } = obj.scopedAction;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-api.client.d.ts","sourceRoot":"","sources":["../../src/clients/graph-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAsB,MAAM,mCAAmC,CAAC;AAGjH,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EAIvB,MAAM,0BAA0B,CAAC;AAMlC;;GAEG;AACH,qBAAa,cAAc;IACzB;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,iBAAiB;IAyBzE;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"graph-api.client.d.ts","sourceRoot":"","sources":["../../src/clients/graph-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAsB,MAAM,mCAAmC,CAAC;AAGjH,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EAIvB,MAAM,0BAA0B,CAAC;AAMlC;;GAEG;AACH,qBAAa,cAAc;IACzB;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,iBAAiB;IAyBzE;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,sBAAsB,CAAC;IA0ElC;;OAEG;IACH,MAAM,CAAC,WAAW,CAChB,aAAa,EAAE,YAAY,EAAE,EAC7B,aAAa,EAAE,sBAAsB,GACpC,0BAA0B,EAAE;IAkB/B;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAIzC"}
|
|
@@ -44,6 +44,15 @@ class GraphApiClient {
|
|
|
44
44
|
const httpClient = tridentBackendApi.Api.getPart('httpClient');
|
|
45
45
|
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
46
46
|
const bodyPayload = this.buildRequestBody(scopedActions);
|
|
47
|
+
authorizationInternalService.logger.debug({
|
|
48
|
+
tag: 'graph-api-client',
|
|
49
|
+
scopedActionsCount: scopedActions.length,
|
|
50
|
+
appName: 'authorization-graph',
|
|
51
|
+
path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
|
|
52
|
+
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
53
|
+
retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
|
|
54
|
+
bodyPayloadKeys: Object.keys(bodyPayload),
|
|
55
|
+
}, '🔍 Graph API Debug: Starting request');
|
|
47
56
|
try {
|
|
48
57
|
const response = await httpClient.fetch({
|
|
49
58
|
url: {
|
|
@@ -52,7 +61,7 @@ class GraphApiClient {
|
|
|
52
61
|
},
|
|
53
62
|
method: 'POST',
|
|
54
63
|
headers: {
|
|
55
|
-
Authorization: internalAuthToken,
|
|
64
|
+
Authorization: internalAuthToken.substring(0, 20) + '...', // Mask token for security
|
|
56
65
|
'Content-Type': 'application/json',
|
|
57
66
|
...attributionHeaders,
|
|
58
67
|
},
|
|
@@ -61,10 +70,21 @@ class GraphApiClient {
|
|
|
61
70
|
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
62
71
|
retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
|
|
63
72
|
});
|
|
73
|
+
authorizationInternalService.logger.debug({
|
|
74
|
+
tag: 'graph-api-client',
|
|
75
|
+
responseKeys: Object.keys(response),
|
|
76
|
+
scopedActionsCount: scopedActions.length,
|
|
77
|
+
}, '✅ Graph API Debug: Request successful');
|
|
64
78
|
prometheusService.setGraphAvailability(true);
|
|
65
79
|
return response;
|
|
66
80
|
}
|
|
67
81
|
catch (err) {
|
|
82
|
+
authorizationInternalService.logger.debug({
|
|
83
|
+
tag: 'graph-api-client',
|
|
84
|
+
error: err instanceof Error ? err.message : String(err),
|
|
85
|
+
status: err instanceof mondayFetchApi.HttpFetcherError ? err.status : 'unknown',
|
|
86
|
+
scopedActionsCount: scopedActions.length,
|
|
87
|
+
}, '❌ Graph API Debug: Request failed');
|
|
68
88
|
prometheusService.setGraphAvailability(false);
|
|
69
89
|
if (err instanceof mondayFetchApi.HttpFetcherError) {
|
|
70
90
|
authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-api.client.d.ts","sourceRoot":"","sources":["../../src/clients/platform-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAE7F,OAAO,EAA0B,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAOlF,KAAK,2BAA2B,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF,UAAU,0BAA0B;IAClC,MAAM,EAAE,0BAA0B,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,2BAA2B,EAAE;IAOxF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,oBAAoB,EAAE,2BAA2B,EAAE,GAClD,OAAO,CAAC,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"platform-api.client.d.ts","sourceRoot":"","sources":["../../src/clients/platform-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAE7F,OAAO,EAA0B,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAOlF,KAAK,2BAA2B,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF,UAAU,0BAA0B;IAClC,MAAM,EAAE,0BAA0B,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,2BAA2B,EAAE;IAOxF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,oBAAoB,EAAE,2BAA2B,EAAE,GAClD,OAAO,CAAC,0BAA0B,CAAC;IA2EtC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,0BAA0B,GAAG,0BAA0B,EAAE;IAkBtF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAKzC"}
|
|
@@ -27,6 +27,16 @@ class PlatformApiClient {
|
|
|
27
27
|
static async fetchPermissions(profile, internalAuthToken, userId, scopedActionsPayload) {
|
|
28
28
|
const attributionHeaders = attributionsService.getAttributionsFromApi();
|
|
29
29
|
const httpClient = tridentBackendApi.Api.getPart('httpClient');
|
|
30
|
+
authorizationInternalService.logger.debug({
|
|
31
|
+
tag: 'platform-api-client',
|
|
32
|
+
profile,
|
|
33
|
+
userId,
|
|
34
|
+
scopedActionsCount: scopedActionsPayload.length,
|
|
35
|
+
appName: 'platform',
|
|
36
|
+
path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
|
|
37
|
+
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
38
|
+
retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
|
|
39
|
+
}, '🔍 Platform API Debug: Starting request');
|
|
30
40
|
try {
|
|
31
41
|
const response = await httpClient.fetch({
|
|
32
42
|
url: {
|
|
@@ -36,7 +46,7 @@ class PlatformApiClient {
|
|
|
36
46
|
},
|
|
37
47
|
method: 'POST',
|
|
38
48
|
headers: {
|
|
39
|
-
Authorization: internalAuthToken,
|
|
49
|
+
Authorization: internalAuthToken.substring(0, 20) + '...', // Mask token for security
|
|
40
50
|
'Content-Type': 'application/json',
|
|
41
51
|
...attributionHeaders,
|
|
42
52
|
},
|
|
@@ -45,9 +55,22 @@ class PlatformApiClient {
|
|
|
45
55
|
timeout: authorizationInternalService.AuthorizationInternalService.getRequestTimeout(),
|
|
46
56
|
retryPolicy: authorizationInternalService.AuthorizationInternalService.getRetriesPolicy(),
|
|
47
57
|
});
|
|
58
|
+
authorizationInternalService.logger.debug({
|
|
59
|
+
tag: 'platform-api-client',
|
|
60
|
+
hasResult: !!response.result,
|
|
61
|
+
resultCount: response.result?.length || 0,
|
|
62
|
+
}, '✅ Platform API Debug: Request successful');
|
|
48
63
|
return response;
|
|
49
64
|
}
|
|
50
65
|
catch (err) {
|
|
66
|
+
authorizationInternalService.logger.debug({
|
|
67
|
+
tag: 'platform-api-client',
|
|
68
|
+
error: err instanceof Error ? err.message : String(err),
|
|
69
|
+
status: err instanceof mondayFetchApi.HttpFetcherError ? err.status : 'unknown',
|
|
70
|
+
profile,
|
|
71
|
+
userId,
|
|
72
|
+
scopedActionsCount: scopedActionsPayload.length,
|
|
73
|
+
}, '❌ Platform API Debug: Request failed');
|
|
51
74
|
if (err instanceof mondayFetchApi.HttpFetcherError) {
|
|
52
75
|
authorizationInternalService.AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
53
76
|
prometheusService.incrementAuthorizationError(utils_authorization_utils.scopeToResource(utils_authorization_utils.toCamelCase(scopedActionsPayload[0].scope)).resourceType, scopedActionsPayload[0].action, err.status);
|
|
@@ -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;
|
|
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;mBA6FnB,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"}
|
|
@@ -87,20 +87,46 @@ class AuthorizationService {
|
|
|
87
87
|
return PlatformProfile.INTERNAL;
|
|
88
88
|
}
|
|
89
89
|
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
90
|
+
logger.debug({ tag: 'authorization-service', accountId, userId, scopedActionsCount: scopedActions.length }, 'canActionInScopeMultiple called');
|
|
90
91
|
const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
|
|
92
|
+
logger.debug({ tag: 'authorization-service', accountId, userId, shouldNavigateToGraph }, `Graph API routing feature flag: ${shouldNavigateToGraph ? 'ENABLED' : 'DISABLED'}`);
|
|
91
93
|
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
92
94
|
const startTime = performance.now();
|
|
93
95
|
let scopedActionResponseObjects;
|
|
96
|
+
let usedGraphApi = false;
|
|
94
97
|
if (shouldNavigateToGraph) {
|
|
95
|
-
|
|
98
|
+
logger.debug({ tag: 'authorization-service', accountId, userId }, 'Attempting Graph API authorization');
|
|
99
|
+
try {
|
|
100
|
+
scopedActionResponseObjects = await GraphApiClient.checkPermissions(internalAuthToken, scopedActions);
|
|
101
|
+
usedGraphApi = true;
|
|
102
|
+
logger.debug({ tag: 'authorization-service', accountId, userId, resultCount: scopedActionResponseObjects.length }, 'Graph API authorization successful');
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
// Fallback to Platform API if Graph API fails
|
|
106
|
+
logger.warn({
|
|
107
|
+
tag: 'authorization-service',
|
|
108
|
+
error: error instanceof Error ? error.message : String(error),
|
|
109
|
+
accountId,
|
|
110
|
+
userId,
|
|
111
|
+
}, 'Graph API authorization failed, falling back to Platform API');
|
|
112
|
+
logger.debug({ tag: 'authorization-service', accountId, userId }, 'Starting Platform API fallback');
|
|
113
|
+
const profile = this.getProfile(accountId, userId);
|
|
114
|
+
logger.debug({ tag: 'authorization-service', accountId, userId, profile }, 'Retrieved Platform API profile for fallback');
|
|
115
|
+
scopedActionResponseObjects = await PlatformApiClient.checkPermissions(profile, internalAuthToken, userId, scopedActions);
|
|
116
|
+
usedGraphApi = false;
|
|
117
|
+
logger.debug({ tag: 'authorization-service', accountId, userId, resultCount: scopedActionResponseObjects.length }, 'Platform API fallback successful');
|
|
118
|
+
}
|
|
96
119
|
}
|
|
97
120
|
else {
|
|
121
|
+
logger.debug({ tag: 'authorization-service', accountId, userId }, 'Using Platform API directly (Graph API FF disabled)');
|
|
98
122
|
const profile = this.getProfile(accountId, userId);
|
|
123
|
+
logger.debug({ tag: 'authorization-service', accountId, userId, profile }, 'Retrieved Platform API profile');
|
|
99
124
|
scopedActionResponseObjects = await PlatformApiClient.checkPermissions(profile, internalAuthToken, userId, scopedActions);
|
|
125
|
+
usedGraphApi = false;
|
|
100
126
|
}
|
|
101
127
|
const endTime = performance.now();
|
|
102
128
|
const time = endTime - startTime;
|
|
103
|
-
const apiType =
|
|
129
|
+
const apiType = usedGraphApi ? 'graph' : 'platform';
|
|
104
130
|
// Record metrics for each authorization check
|
|
105
131
|
for (const obj of scopedActionResponseObjects) {
|
|
106
132
|
const { action, scope } = obj.scopedAction;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-api.client.d.ts","sourceRoot":"","sources":["../../../src/clients/graph-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAsB,MAAM,mCAAmC,CAAC;AAGjH,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EAIvB,MAAM,0BAA0B,CAAC;AAMlC;;GAEG;AACH,qBAAa,cAAc;IACzB;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,iBAAiB;IAyBzE;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"graph-api.client.d.ts","sourceRoot":"","sources":["../../../src/clients/graph-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAsB,MAAM,mCAAmC,CAAC;AAGjH,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EAIvB,MAAM,0BAA0B,CAAC;AAMlC;;GAEG;AACH,qBAAa,cAAc;IACzB;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,iBAAiB;IAyBzE;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,sBAAsB,CAAC;IA0ElC;;OAEG;IACH,MAAM,CAAC,WAAW,CAChB,aAAa,EAAE,YAAY,EAAE,EAC7B,aAAa,EAAE,sBAAsB,GACpC,0BAA0B,EAAE;IAkB/B;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAIzC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Api } from '@mondaydotcomorg/trident-backend-api';
|
|
2
2
|
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
3
|
-
import { AuthorizationInternalService } from '../authorization-internal-service.mjs';
|
|
3
|
+
import { logger, AuthorizationInternalService } from '../authorization-internal-service.mjs';
|
|
4
4
|
import { getAttributionsFromApi } from '../attributions-service.mjs';
|
|
5
5
|
import { scopeToResource } from '../utils/authorization.utils.mjs';
|
|
6
6
|
import { setGraphAvailability, incrementAuthorizationError } from '../prometheus-service.mjs';
|
|
@@ -42,6 +42,15 @@ class GraphApiClient {
|
|
|
42
42
|
const httpClient = Api.getPart('httpClient');
|
|
43
43
|
const attributionHeaders = getAttributionsFromApi();
|
|
44
44
|
const bodyPayload = this.buildRequestBody(scopedActions);
|
|
45
|
+
logger.debug({
|
|
46
|
+
tag: 'graph-api-client',
|
|
47
|
+
scopedActionsCount: scopedActions.length,
|
|
48
|
+
appName: 'authorization-graph',
|
|
49
|
+
path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
|
|
50
|
+
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
51
|
+
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
52
|
+
bodyPayloadKeys: Object.keys(bodyPayload),
|
|
53
|
+
}, '🔍 Graph API Debug: Starting request');
|
|
45
54
|
try {
|
|
46
55
|
const response = await httpClient.fetch({
|
|
47
56
|
url: {
|
|
@@ -50,7 +59,7 @@ class GraphApiClient {
|
|
|
50
59
|
},
|
|
51
60
|
method: 'POST',
|
|
52
61
|
headers: {
|
|
53
|
-
Authorization: internalAuthToken,
|
|
62
|
+
Authorization: internalAuthToken.substring(0, 20) + '...', // Mask token for security
|
|
54
63
|
'Content-Type': 'application/json',
|
|
55
64
|
...attributionHeaders,
|
|
56
65
|
},
|
|
@@ -59,10 +68,21 @@ class GraphApiClient {
|
|
|
59
68
|
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
60
69
|
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
61
70
|
});
|
|
71
|
+
logger.debug({
|
|
72
|
+
tag: 'graph-api-client',
|
|
73
|
+
responseKeys: Object.keys(response),
|
|
74
|
+
scopedActionsCount: scopedActions.length,
|
|
75
|
+
}, '✅ Graph API Debug: Request successful');
|
|
62
76
|
setGraphAvailability(true);
|
|
63
77
|
return response;
|
|
64
78
|
}
|
|
65
79
|
catch (err) {
|
|
80
|
+
logger.debug({
|
|
81
|
+
tag: 'graph-api-client',
|
|
82
|
+
error: err instanceof Error ? err.message : String(err),
|
|
83
|
+
status: err instanceof HttpFetcherError ? err.status : 'unknown',
|
|
84
|
+
scopedActionsCount: scopedActions.length,
|
|
85
|
+
}, '❌ Graph API Debug: Request failed');
|
|
66
86
|
setGraphAvailability(false);
|
|
67
87
|
if (err instanceof HttpFetcherError) {
|
|
68
88
|
AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-api.client.d.ts","sourceRoot":"","sources":["../../../src/clients/platform-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAE7F,OAAO,EAA0B,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAOlF,KAAK,2BAA2B,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF,UAAU,0BAA0B;IAClC,MAAM,EAAE,0BAA0B,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,2BAA2B,EAAE;IAOxF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,oBAAoB,EAAE,2BAA2B,EAAE,GAClD,OAAO,CAAC,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"platform-api.client.d.ts","sourceRoot":"","sources":["../../../src/clients/platform-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAE7F,OAAO,EAA0B,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAOlF,KAAK,2BAA2B,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF,UAAU,0BAA0B;IAClC,MAAM,EAAE,0BAA0B,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,2BAA2B,EAAE;IAOxF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,oBAAoB,EAAE,2BAA2B,EAAE,GAClD,OAAO,CAAC,0BAA0B,CAAC;IA2EtC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,0BAA0B,GAAG,0BAA0B,EAAE;IAkBtF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAKzC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Api } from '@mondaydotcomorg/trident-backend-api';
|
|
2
2
|
import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
|
|
3
|
-
import {
|
|
3
|
+
import { logger, AuthorizationInternalService } from '../authorization-internal-service.mjs';
|
|
4
4
|
import { getAttributionsFromApi } from '../attributions-service.mjs';
|
|
5
5
|
import { toSnakeCase, scopeToResource, toCamelCase } from '../utils/authorization.utils.mjs';
|
|
6
6
|
import { incrementAuthorizationError } from '../prometheus-service.mjs';
|
|
@@ -25,6 +25,16 @@ class PlatformApiClient {
|
|
|
25
25
|
static async fetchPermissions(profile, internalAuthToken, userId, scopedActionsPayload) {
|
|
26
26
|
const attributionHeaders = getAttributionsFromApi();
|
|
27
27
|
const httpClient = Api.getPart('httpClient');
|
|
28
|
+
logger.debug({
|
|
29
|
+
tag: 'platform-api-client',
|
|
30
|
+
profile,
|
|
31
|
+
userId,
|
|
32
|
+
scopedActionsCount: scopedActionsPayload.length,
|
|
33
|
+
appName: 'platform',
|
|
34
|
+
path: PLATFORM_CAN_ACTIONS_IN_SCOPES_PATH,
|
|
35
|
+
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
36
|
+
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
37
|
+
}, '🔍 Platform API Debug: Starting request');
|
|
28
38
|
try {
|
|
29
39
|
const response = await httpClient.fetch({
|
|
30
40
|
url: {
|
|
@@ -34,7 +44,7 @@ class PlatformApiClient {
|
|
|
34
44
|
},
|
|
35
45
|
method: 'POST',
|
|
36
46
|
headers: {
|
|
37
|
-
Authorization: internalAuthToken,
|
|
47
|
+
Authorization: internalAuthToken.substring(0, 20) + '...', // Mask token for security
|
|
38
48
|
'Content-Type': 'application/json',
|
|
39
49
|
...attributionHeaders,
|
|
40
50
|
},
|
|
@@ -43,9 +53,22 @@ class PlatformApiClient {
|
|
|
43
53
|
timeout: AuthorizationInternalService.getRequestTimeout(),
|
|
44
54
|
retryPolicy: AuthorizationInternalService.getRetriesPolicy(),
|
|
45
55
|
});
|
|
56
|
+
logger.debug({
|
|
57
|
+
tag: 'platform-api-client',
|
|
58
|
+
hasResult: !!response.result,
|
|
59
|
+
resultCount: response.result?.length || 0,
|
|
60
|
+
}, '✅ Platform API Debug: Request successful');
|
|
46
61
|
return response;
|
|
47
62
|
}
|
|
48
63
|
catch (err) {
|
|
64
|
+
logger.debug({
|
|
65
|
+
tag: 'platform-api-client',
|
|
66
|
+
error: err instanceof Error ? err.message : String(err),
|
|
67
|
+
status: err instanceof HttpFetcherError ? err.status : 'unknown',
|
|
68
|
+
profile,
|
|
69
|
+
userId,
|
|
70
|
+
scopedActionsCount: scopedActionsPayload.length,
|
|
71
|
+
}, '❌ Platform API Debug: Request failed');
|
|
49
72
|
if (err instanceof HttpFetcherError) {
|
|
50
73
|
AuthorizationInternalService.throwOnHttpError(err.status, 'canActionInScopeMultiple');
|
|
51
74
|
incrementAuthorizationError(scopeToResource(toCamelCase(scopedActionsPayload[0].scope)).resourceType, scopedActionsPayload[0].action, err.status);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testKit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG9G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,eAAO,MAAM,sBAAsB,GAAI,WAAW,MAAM,EAAE,QAAQ,MAAM,EAAE,WAAW,QAAQ,EAAE,EAAE,QAAQ,MAAM,SAE9G,CAAC;AAEF,eAAO,MAAM,yBAAyB,YAErC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testKit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG9G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,eAAO,MAAM,sBAAsB,GAAI,WAAW,MAAM,EAAE,QAAQ,MAAM,EAAE,WAAW,QAAQ,EAAE,EAAE,QAAQ,MAAM,SAE9G,CAAC;AAEF,eAAO,MAAM,yBAAyB,YAErC,CAAC;AA4BF,eAAO,MAAM,8BAA8B,GACzC,QAAQ,MAAM,EACd,gBAAgB,cAAc,EAC9B,gBAAgB,aAAa,MAG3B,SAAS,WAAW,EACpB,UAAU,YAAY,EACtB,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAYhB,CAAC"}
|
|
@@ -9,18 +9,20 @@ const clearTestPermittedActions = () => {
|
|
|
9
9
|
testPermittedActions = [];
|
|
10
10
|
};
|
|
11
11
|
const isActionAuthorized = (accountId, userId, resources, action) => {
|
|
12
|
+
// If no resources to check, deny access
|
|
13
|
+
if (resources.length === 0) {
|
|
14
|
+
return { isAuthorized: false };
|
|
15
|
+
}
|
|
12
16
|
return {
|
|
13
|
-
isAuthorized: resources.every(
|
|
17
|
+
isAuthorized: resources.every(resource => {
|
|
14
18
|
return testPermittedActions.some(combination => {
|
|
15
19
|
return (combination.accountId === accountId &&
|
|
16
20
|
combination.userId === userId &&
|
|
17
21
|
combination.action === action &&
|
|
18
22
|
combination.resources.some(combinationResource => {
|
|
19
|
-
return
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
JSON.stringify(combinationResource.wrapperData) === JSON.stringify(resource.wrapperData));
|
|
23
|
-
});
|
|
23
|
+
return (combinationResource.id === resource.id &&
|
|
24
|
+
combinationResource.type === resource.type &&
|
|
25
|
+
JSON.stringify(combinationResource.wrapperData) === JSON.stringify(resource.wrapperData));
|
|
24
26
|
}));
|
|
25
27
|
});
|
|
26
28
|
}),
|
|
@@ -32,11 +34,11 @@ const getTestAuthorizationMiddleware = (action, resourceGetter, contextGetter) =
|
|
|
32
34
|
const { userId, accountId } = contextGetter(request);
|
|
33
35
|
const resources = resourceGetter(request);
|
|
34
36
|
const { isAuthorized } = isActionAuthorized(accountId, userId, resources, action);
|
|
35
|
-
AuthorizationInternalService.markAuthorized(request);
|
|
36
37
|
if (!isAuthorized) {
|
|
37
38
|
response.status(403).json({ message: 'Access denied' });
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
41
|
+
AuthorizationInternalService.markAuthorized(request);
|
|
40
42
|
next();
|
|
41
43
|
};
|
|
42
44
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/authorization.utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"authorization.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/authorization.utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGpE,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACpH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,GAC3C;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GAC9E,CAAC,CAAC;AAEN;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG;IAAE,YAAY,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAoC3G;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAEtE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAEzE"}
|
|
@@ -1,26 +1,38 @@
|
|
|
1
1
|
import snakeCase from 'lodash/snakeCase.js';
|
|
2
2
|
import camelCase from 'lodash/camelCase.js';
|
|
3
3
|
import mapKeys from 'lodash/mapKeys.js';
|
|
4
|
+
import { logger } from '../authorization-internal-service.mjs';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Converts a scope object to resource type and resource ID
|
|
7
8
|
*/
|
|
8
9
|
function scopeToResource(scope) {
|
|
10
|
+
logger.debug({
|
|
11
|
+
tag: 'authorization-utils',
|
|
12
|
+
scopeKeys: Object.keys(scope),
|
|
13
|
+
scopeValues: Object.values(scope),
|
|
14
|
+
}, '🔍 Utils Debug: Converting scope to resource');
|
|
9
15
|
if ('workspaceId' in scope) {
|
|
16
|
+
logger.debug({ tag: 'authorization-utils', resourceId: scope.workspaceId }, '🔍 Utils Debug: Mapped to workspace');
|
|
10
17
|
return { resourceType: 'workspace', resourceId: scope.workspaceId };
|
|
11
18
|
}
|
|
12
19
|
if ('boardId' in scope) {
|
|
20
|
+
logger.debug({ tag: 'authorization-utils', resourceId: scope.boardId }, '🔍 Utils Debug: Mapped to board');
|
|
13
21
|
return { resourceType: 'board', resourceId: scope.boardId };
|
|
14
22
|
}
|
|
15
23
|
if ('pulseId' in scope) {
|
|
24
|
+
logger.debug({ tag: 'authorization-utils', resourceId: scope.pulseId }, '🔍 Utils Debug: Mapped to pulse');
|
|
16
25
|
return { resourceType: 'pulse', resourceId: scope.pulseId };
|
|
17
26
|
}
|
|
18
27
|
if ('accountProductId' in scope) {
|
|
28
|
+
logger.debug({ tag: 'authorization-utils', resourceId: scope.accountProductId }, '🔍 Utils Debug: Mapped to account_product');
|
|
19
29
|
return { resourceType: 'account_product', resourceId: scope.accountProductId };
|
|
20
30
|
}
|
|
21
31
|
if ('accountId' in scope) {
|
|
32
|
+
logger.debug({ tag: 'authorization-utils', resourceId: scope.accountId }, '🔍 Utils Debug: Mapped to account');
|
|
22
33
|
return { resourceType: 'account', resourceId: scope.accountId };
|
|
23
34
|
}
|
|
35
|
+
logger.debug({ tag: 'authorization-utils', scope }, '❌ Utils Debug: Unsupported scope provided');
|
|
24
36
|
throw new Error('Unsupported scope provided');
|
|
25
37
|
}
|
|
26
38
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testKit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG9G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,eAAO,MAAM,sBAAsB,GAAI,WAAW,MAAM,EAAE,QAAQ,MAAM,EAAE,WAAW,QAAQ,EAAE,EAAE,QAAQ,MAAM,SAE9G,CAAC;AAEF,eAAO,MAAM,yBAAyB,YAErC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testKit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAG9G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAGF,eAAO,MAAM,sBAAsB,GAAI,WAAW,MAAM,EAAE,QAAQ,MAAM,EAAE,WAAW,QAAQ,EAAE,EAAE,QAAQ,MAAM,SAE9G,CAAC;AAEF,eAAO,MAAM,yBAAyB,YAErC,CAAC;AA4BF,eAAO,MAAM,8BAA8B,GACzC,QAAQ,MAAM,EACd,gBAAgB,cAAc,EAC9B,gBAAgB,aAAa,MAG3B,SAAS,WAAW,EACpB,UAAU,YAAY,EACtB,MAAM,YAAY,KACjB,OAAO,CAAC,IAAI,CAYhB,CAAC"}
|
package/dist/testKit/index.js
CHANGED
|
@@ -11,18 +11,20 @@ const clearTestPermittedActions = () => {
|
|
|
11
11
|
testPermittedActions = [];
|
|
12
12
|
};
|
|
13
13
|
const isActionAuthorized = (accountId, userId, resources, action) => {
|
|
14
|
+
// If no resources to check, deny access
|
|
15
|
+
if (resources.length === 0) {
|
|
16
|
+
return { isAuthorized: false };
|
|
17
|
+
}
|
|
14
18
|
return {
|
|
15
|
-
isAuthorized: resources.every(
|
|
19
|
+
isAuthorized: resources.every(resource => {
|
|
16
20
|
return testPermittedActions.some(combination => {
|
|
17
21
|
return (combination.accountId === accountId &&
|
|
18
22
|
combination.userId === userId &&
|
|
19
23
|
combination.action === action &&
|
|
20
24
|
combination.resources.some(combinationResource => {
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
JSON.stringify(combinationResource.wrapperData) === JSON.stringify(resource.wrapperData));
|
|
25
|
-
});
|
|
25
|
+
return (combinationResource.id === resource.id &&
|
|
26
|
+
combinationResource.type === resource.type &&
|
|
27
|
+
JSON.stringify(combinationResource.wrapperData) === JSON.stringify(resource.wrapperData));
|
|
26
28
|
}));
|
|
27
29
|
});
|
|
28
30
|
}),
|
|
@@ -34,11 +36,11 @@ const getTestAuthorizationMiddleware = (action, resourceGetter, contextGetter) =
|
|
|
34
36
|
const { userId, accountId } = contextGetter(request);
|
|
35
37
|
const resources = resourceGetter(request);
|
|
36
38
|
const { isAuthorized } = isActionAuthorized(accountId, userId, resources, action);
|
|
37
|
-
authorizationInternalService.AuthorizationInternalService.markAuthorized(request);
|
|
38
39
|
if (!isAuthorized) {
|
|
39
40
|
response.status(403).json({ message: 'Access denied' });
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
43
|
+
authorizationInternalService.AuthorizationInternalService.markAuthorized(request);
|
|
42
44
|
next();
|
|
43
45
|
};
|
|
44
46
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization.utils.d.ts","sourceRoot":"","sources":["../../src/utils/authorization.utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"authorization.utils.d.ts","sourceRoot":"","sources":["../../src/utils/authorization.utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAGpE,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACpH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,GAC3C;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GAC9E,CAAC,CAAC;AAEN;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG;IAAE,YAAY,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAoC3G;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAEtE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAEzE"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3
3
|
const snakeCase = require('lodash/snakeCase.js');
|
|
4
4
|
const camelCase = require('lodash/camelCase.js');
|
|
5
5
|
const mapKeys = require('lodash/mapKeys.js');
|
|
6
|
+
const authorizationInternalService = require('../authorization-internal-service.js');
|
|
6
7
|
|
|
7
8
|
const _interopDefault = e => e && e.__esModule ? e : { default: e };
|
|
8
9
|
|
|
@@ -14,21 +15,32 @@ const mapKeys__default = /*#__PURE__*/_interopDefault(mapKeys);
|
|
|
14
15
|
* Converts a scope object to resource type and resource ID
|
|
15
16
|
*/
|
|
16
17
|
function scopeToResource(scope) {
|
|
18
|
+
authorizationInternalService.logger.debug({
|
|
19
|
+
tag: 'authorization-utils',
|
|
20
|
+
scopeKeys: Object.keys(scope),
|
|
21
|
+
scopeValues: Object.values(scope),
|
|
22
|
+
}, '🔍 Utils Debug: Converting scope to resource');
|
|
17
23
|
if ('workspaceId' in scope) {
|
|
24
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-utils', resourceId: scope.workspaceId }, '🔍 Utils Debug: Mapped to workspace');
|
|
18
25
|
return { resourceType: 'workspace', resourceId: scope.workspaceId };
|
|
19
26
|
}
|
|
20
27
|
if ('boardId' in scope) {
|
|
28
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-utils', resourceId: scope.boardId }, '🔍 Utils Debug: Mapped to board');
|
|
21
29
|
return { resourceType: 'board', resourceId: scope.boardId };
|
|
22
30
|
}
|
|
23
31
|
if ('pulseId' in scope) {
|
|
32
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-utils', resourceId: scope.pulseId }, '🔍 Utils Debug: Mapped to pulse');
|
|
24
33
|
return { resourceType: 'pulse', resourceId: scope.pulseId };
|
|
25
34
|
}
|
|
26
35
|
if ('accountProductId' in scope) {
|
|
36
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-utils', resourceId: scope.accountProductId }, '🔍 Utils Debug: Mapped to account_product');
|
|
27
37
|
return { resourceType: 'account_product', resourceId: scope.accountProductId };
|
|
28
38
|
}
|
|
29
39
|
if ('accountId' in scope) {
|
|
40
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-utils', resourceId: scope.accountId }, '🔍 Utils Debug: Mapped to account');
|
|
30
41
|
return { resourceType: 'account', resourceId: scope.accountId };
|
|
31
42
|
}
|
|
43
|
+
authorizationInternalService.logger.debug({ tag: 'authorization-utils', scope }, '❌ Utils Debug: Unsupported scope provided');
|
|
32
44
|
throw new Error('Unsupported scope provided');
|
|
33
45
|
}
|
|
34
46
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mondaydotcomorg/monday-authorization",
|
|
3
|
-
"version": "3.3.0-feature-bashanye-navigate-can-action-in-scope-to-graph-
|
|
3
|
+
"version": "3.3.0-feature-bashanye-navigate-can-action-in-scope-to-graph-0a3cfd6",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"license": "BSD-3-Clause",
|