@mondaydotcomorg/monday-authorization 3.5.0 → 3.5.1-debug-getprofile-not-resolving-to-internal-ba14ff5
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 +66 -25
- package/dist/clients/graph-api.d.ts.map +1 -1
- package/dist/clients/graph-api.js +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +4 -0
- package/dist/esm/authorization-service.d.ts.map +1 -1
- package/dist/esm/authorization-service.mjs +66 -25
- package/dist/esm/clients/graph-api.d.ts.map +1 -1
- package/dist/esm/clients/graph-api.mjs +2 -1
- package/dist/esm/constants.d.ts +3 -0
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.mjs +5 -1
- package/package.json +1 -1
- package/src/authorization-service.ts +90 -35
- package/src/clients/graph-api.ts +2 -1
- package/src/constants.ts +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../src/authorization-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAe1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAMD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,KAAK,QAAQ,GAK1B;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAW;IAEpC,OAAO,CAAC,MAAM,KAAK,WAAW,GAK7B;IACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAc;IAE1C,MAAM,CAAC,eAAe,IAAI,IAAI;IAK9B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;
|
|
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;WAwCZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBAiFnB,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"}
|
|
@@ -17,7 +17,6 @@ const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
|
|
|
17
17
|
const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
|
|
18
18
|
const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
|
|
19
19
|
const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
|
|
20
|
-
const NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF = 'navigate-can-action-in-scope-to-graph';
|
|
21
20
|
function setRequestFetchOptions(customMondayFetchOptions) {
|
|
22
21
|
authorizationInternalService.AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
|
|
23
22
|
}
|
|
@@ -96,46 +95,88 @@ class AuthorizationService {
|
|
|
96
95
|
authorizationInternalService.logger.error({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, failing request');
|
|
97
96
|
throw new Error('AuthorizationService: igniteClient is not set, failing request');
|
|
98
97
|
}
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
const allowedApps = this.igniteClient.configuration.getObjectValue(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []);
|
|
99
|
+
const inReleaseApps = this.igniteClient.configuration.getObjectValue(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, []);
|
|
100
|
+
const isInAllowedApps = allowedApps.includes(appName);
|
|
101
|
+
const isInReleaseApps = inReleaseApps.includes(appName);
|
|
102
|
+
const isFeatureFlagReleased = this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId });
|
|
103
|
+
const debugInfo = {
|
|
104
|
+
appName,
|
|
105
|
+
allowedApps,
|
|
106
|
+
inReleaseApps,
|
|
107
|
+
isInAllowedApps,
|
|
108
|
+
isInReleaseApps,
|
|
109
|
+
isFeatureFlagReleased,
|
|
110
|
+
accountId,
|
|
111
|
+
userId,
|
|
112
|
+
};
|
|
113
|
+
authorizationInternalService.logger.info({ tag: 'authorization-service', ...debugInfo }, 'AuthorizationService.getProfile debug info');
|
|
114
|
+
if (isInAllowedApps) {
|
|
115
|
+
const profile = attributionsService.getProfile();
|
|
116
|
+
authorizationInternalService.logger.info({ tag: 'authorization-service', profile }, 'Returning profile from ALLOWED_SDK_PLATFORM_PROFILES_KEY');
|
|
117
|
+
return profile;
|
|
101
118
|
}
|
|
102
|
-
if (
|
|
103
|
-
.
|
|
104
|
-
.
|
|
105
|
-
|
|
106
|
-
return attributionsService.getProfile();
|
|
119
|
+
if (isInReleaseApps && isFeatureFlagReleased) {
|
|
120
|
+
const profile = attributionsService.getProfile();
|
|
121
|
+
authorizationInternalService.logger.info({ tag: 'authorization-service', profile }, 'Returning profile from IN_RELEASE_SDK_PLATFORM_PROFILES_KEY');
|
|
122
|
+
return profile;
|
|
107
123
|
}
|
|
124
|
+
authorizationInternalService.logger.info({ tag: 'authorization-service', profile: attributionsService.PlatformProfile.APP }, 'Returning default PlatformProfile.APP');
|
|
108
125
|
return attributionsService.PlatformProfile.APP;
|
|
109
126
|
}
|
|
110
127
|
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
111
128
|
if (scopedActions.length === 0) {
|
|
112
129
|
return [];
|
|
113
130
|
}
|
|
114
|
-
const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
|
|
115
131
|
const startTime = perf_hooks.performance.now();
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
else {
|
|
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);
|
|
127
|
-
}
|
|
132
|
+
// Always call both APIs for comparison
|
|
133
|
+
const graphApiPromise = this.graphApi.checkPermissions(accountId, userId, scopedActions);
|
|
134
|
+
const profile = this.getProfile(accountId, userId);
|
|
135
|
+
const internalAuthToken = authorizationInternalService.AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
136
|
+
const platformApiPromise = this.platformApi.checkPermissions(profile, internalAuthToken, userId, scopedActions);
|
|
137
|
+
const [graphApiResponse, platformApiResponse] = await Promise.all([graphApiPromise, platformApiPromise]);
|
|
128
138
|
const endTime = perf_hooks.performance.now();
|
|
129
139
|
const time = endTime - startTime;
|
|
130
|
-
//
|
|
131
|
-
|
|
140
|
+
// Compare responses and log differences
|
|
141
|
+
const differences = [];
|
|
142
|
+
for (let i = 0; i < scopedActions.length; i++) {
|
|
143
|
+
const graphResult = graphApiResponse[i];
|
|
144
|
+
const platformResult = platformApiResponse[i];
|
|
145
|
+
const graphCan = graphResult?.permit?.can;
|
|
146
|
+
const platformCan = platformResult?.permit?.can;
|
|
147
|
+
if (graphCan !== platformCan) {
|
|
148
|
+
differences.push({
|
|
149
|
+
action: scopedActions[i].action,
|
|
150
|
+
scope: scopedActions[i].scope,
|
|
151
|
+
graphResult: graphResult?.permit,
|
|
152
|
+
platformResult: platformResult?.permit,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const isSame = differences.length === 0;
|
|
157
|
+
authorizationInternalService.logger.info({
|
|
158
|
+
tag: 'authorization-service-api-comparison',
|
|
159
|
+
accountId,
|
|
160
|
+
userId,
|
|
161
|
+
profile,
|
|
162
|
+
scopedActionsCount: scopedActions.length,
|
|
163
|
+
isSame,
|
|
164
|
+
differencesCount: differences.length,
|
|
165
|
+
differences: differences.length > 0 ? differences : undefined,
|
|
166
|
+
graphApiResponse,
|
|
167
|
+
platformApiResponse,
|
|
168
|
+
timeMs: time,
|
|
169
|
+
}, `API comparison: graphApi vs platformApi - ${isSame ? 'SAME' : 'DIFFERENT'}`);
|
|
170
|
+
// Record metrics for each authorization check (using platform response)
|
|
171
|
+
for (const obj of platformApiResponse) {
|
|
132
172
|
const { action, scope } = obj.scopedAction;
|
|
133
173
|
const { resourceType } = utils_authorization_utils.scopeToResource(scope);
|
|
134
174
|
const isAuthorized = obj.permit.can;
|
|
135
175
|
prometheusService.sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time);
|
|
136
|
-
metricsService.recordAuthorizationTiming(
|
|
176
|
+
metricsService.recordAuthorizationTiming('platform', time, 'canActionInScopeMultiple');
|
|
137
177
|
}
|
|
138
|
-
|
|
178
|
+
// Return platform API response
|
|
179
|
+
return platformApiResponse;
|
|
139
180
|
}
|
|
140
181
|
static async isAuthorizedSingular(accountId, userId, resources, action) {
|
|
141
182
|
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
@@ -1 +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;AAQlC;;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;
|
|
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;AAQlC;;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;IAiCzG;;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"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ import { RecursivePartial } from '@mondaydotcomorg/monday-fetch-api';
|
|
|
2
2
|
import { FetcherConfig } from '@mondaydotcomorg/trident-backend-api';
|
|
3
3
|
export declare const APP_NAME = "authorization";
|
|
4
4
|
export declare const GRAPH_APP_NAME = "authorization-graph";
|
|
5
|
+
export declare enum GraphApiProfile {
|
|
6
|
+
PERMISSION = "authorization-graph-permission"
|
|
7
|
+
}
|
|
5
8
|
export declare const ERROR_MESSAGES: {
|
|
6
9
|
readonly HTTP_CLIENT_NOT_INITIALIZED: "MondayAuthorization: HTTP client is not initialized";
|
|
7
10
|
readonly REQUEST_FAILED: (method: string, status: number, reason: string) => string;
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAErE,eAAO,MAAM,QAAQ,kBAAkB,CAAC;AACxC,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAEpD,eAAO,MAAM,cAAc;;sCAEA,MAAM,UAAU,MAAM,UAAU,MAAM;CAEvD,CAAC;AAEX,eAAO,MAAM,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAUjE,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAErE,eAAO,MAAM,QAAQ,kBAAkB,CAAC;AACxC,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAEpD,oBAAY,eAAe;IACzB,UAAU,mCAAmC;CAC9C;AAED,eAAO,MAAM,cAAc;;sCAEA,MAAM,UAAU,MAAM,UAAU,MAAM;CAEvD,CAAC;AAEX,eAAO,MAAM,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAUjE,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -2,6 +2,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
|
|
3
3
|
const APP_NAME = 'authorization';
|
|
4
4
|
const GRAPH_APP_NAME = 'authorization-graph';
|
|
5
|
+
exports.GraphApiProfile = void 0;
|
|
6
|
+
(function (GraphApiProfile) {
|
|
7
|
+
GraphApiProfile["PERMISSION"] = "authorization-graph-permission";
|
|
8
|
+
})(exports.GraphApiProfile || (exports.GraphApiProfile = {}));
|
|
5
9
|
const ERROR_MESSAGES = {
|
|
6
10
|
HTTP_CLIENT_NOT_INITIALIZED: 'MondayAuthorization: HTTP client is not initialized',
|
|
7
11
|
REQUEST_FAILED: (method, status, reason) => `MondayAuthorization: [${method}] request failed with status ${status} with reason: ${reason}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-service.d.ts","sourceRoot":"","sources":["../../src/authorization-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAGnE,OAAO,EAAmB,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG7F,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACb,MAAM,kCAAkC,CAAC;AAe1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC7C;AAED,wBAAgB,sBAAsB,CAAC,wBAAwB,EAAE,kBAAkB,QAElF;AAMD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,KAAK,QAAQ,GAK1B;IACD,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAW;IAEpC,OAAO,CAAC,MAAM,KAAK,WAAW,GAK7B;IACD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAc;IAE1C,MAAM,CAAC,eAAe,IAAI,IAAI;IAK9B,MAAM,CAAC,WAAW,CAAC,MAAC;IACpB,MAAM,CAAC,sCAAsC,CAAC,EAAE,MAAM,CAAC;IACvD,MAAM,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IAEnC;;;OAGG;WACU,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,QAAQ,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,iBAAiB,CAAC;WAEhB,YAAY,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,2BAA2B,EAAE,mBAAmB,EAAE,GACjD,OAAO,CAAC,iBAAiB,CAAC;IAY7B;;;OAGG;WACU,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;QAAE,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAC1C,OAAO,CAAC,OAAO,CAAC;mBAkBE,6BAA6B;IAclD,OAAO,CAAC,MAAM,CAAC,gBAAgB;WAIlB,gBAAgB,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAM9B,OAAO,CAAC,MAAM,CAAC,UAAU;
|
|
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;WAwCZ,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;mBAiFnB,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"}
|
|
@@ -15,7 +15,6 @@ const PLATFORM_AUTHORIZE_PATH = '/internal_ms/authorization/authorize';
|
|
|
15
15
|
const ALLOWED_SDK_PLATFORM_PROFILES_KEY = 'allowed-sdk-platform-profiles';
|
|
16
16
|
const IN_RELEASE_SDK_PLATFORM_PROFILES_KEY = 'in-release-sdk-platform-profile';
|
|
17
17
|
const PLATFORM_PROFILE_RELEASE_FF = 'sdk-platform-profiles';
|
|
18
|
-
const NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF = 'navigate-can-action-in-scope-to-graph';
|
|
19
18
|
function setRequestFetchOptions(customMondayFetchOptions) {
|
|
20
19
|
AuthorizationInternalService.setRequestFetchOptions(customMondayFetchOptions);
|
|
21
20
|
}
|
|
@@ -94,46 +93,88 @@ class AuthorizationService {
|
|
|
94
93
|
logger.error({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, failing request');
|
|
95
94
|
throw new Error('AuthorizationService: igniteClient is not set, failing request');
|
|
96
95
|
}
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
const allowedApps = this.igniteClient.configuration.getObjectValue(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []);
|
|
97
|
+
const inReleaseApps = this.igniteClient.configuration.getObjectValue(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, []);
|
|
98
|
+
const isInAllowedApps = allowedApps.includes(appName);
|
|
99
|
+
const isInReleaseApps = inReleaseApps.includes(appName);
|
|
100
|
+
const isFeatureFlagReleased = this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId });
|
|
101
|
+
const debugInfo = {
|
|
102
|
+
appName,
|
|
103
|
+
allowedApps,
|
|
104
|
+
inReleaseApps,
|
|
105
|
+
isInAllowedApps,
|
|
106
|
+
isInReleaseApps,
|
|
107
|
+
isFeatureFlagReleased,
|
|
108
|
+
accountId,
|
|
109
|
+
userId,
|
|
110
|
+
};
|
|
111
|
+
logger.info({ tag: 'authorization-service', ...debugInfo }, 'AuthorizationService.getProfile debug info');
|
|
112
|
+
if (isInAllowedApps) {
|
|
113
|
+
const profile = getProfile();
|
|
114
|
+
logger.info({ tag: 'authorization-service', profile }, 'Returning profile from ALLOWED_SDK_PLATFORM_PROFILES_KEY');
|
|
115
|
+
return profile;
|
|
99
116
|
}
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
.
|
|
103
|
-
|
|
104
|
-
return getProfile();
|
|
117
|
+
if (isInReleaseApps && isFeatureFlagReleased) {
|
|
118
|
+
const profile = getProfile();
|
|
119
|
+
logger.info({ tag: 'authorization-service', profile }, 'Returning profile from IN_RELEASE_SDK_PLATFORM_PROFILES_KEY');
|
|
120
|
+
return profile;
|
|
105
121
|
}
|
|
122
|
+
logger.info({ tag: 'authorization-service', profile: PlatformProfile.APP }, 'Returning default PlatformProfile.APP');
|
|
106
123
|
return PlatformProfile.APP;
|
|
107
124
|
}
|
|
108
125
|
static async canActionInScopeMultiple(accountId, userId, scopedActions) {
|
|
109
126
|
if (scopedActions.length === 0) {
|
|
110
127
|
return [];
|
|
111
128
|
}
|
|
112
|
-
const shouldNavigateToGraph = Boolean(this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId }));
|
|
113
129
|
const startTime = performance.now();
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
else {
|
|
121
|
-
apiType = 'platform';
|
|
122
|
-
const profile = this.getProfile(accountId, userId);
|
|
123
|
-
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
124
|
-
scopedActionResponseObjects = await this.platformApi.checkPermissions(profile, internalAuthToken, userId, scopedActions);
|
|
125
|
-
}
|
|
130
|
+
// Always call both APIs for comparison
|
|
131
|
+
const graphApiPromise = this.graphApi.checkPermissions(accountId, userId, scopedActions);
|
|
132
|
+
const profile = this.getProfile(accountId, userId);
|
|
133
|
+
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
134
|
+
const platformApiPromise = this.platformApi.checkPermissions(profile, internalAuthToken, userId, scopedActions);
|
|
135
|
+
const [graphApiResponse, platformApiResponse] = await Promise.all([graphApiPromise, platformApiPromise]);
|
|
126
136
|
const endTime = performance.now();
|
|
127
137
|
const time = endTime - startTime;
|
|
128
|
-
//
|
|
129
|
-
|
|
138
|
+
// Compare responses and log differences
|
|
139
|
+
const differences = [];
|
|
140
|
+
for (let i = 0; i < scopedActions.length; i++) {
|
|
141
|
+
const graphResult = graphApiResponse[i];
|
|
142
|
+
const platformResult = platformApiResponse[i];
|
|
143
|
+
const graphCan = graphResult?.permit?.can;
|
|
144
|
+
const platformCan = platformResult?.permit?.can;
|
|
145
|
+
if (graphCan !== platformCan) {
|
|
146
|
+
differences.push({
|
|
147
|
+
action: scopedActions[i].action,
|
|
148
|
+
scope: scopedActions[i].scope,
|
|
149
|
+
graphResult: graphResult?.permit,
|
|
150
|
+
platformResult: platformResult?.permit,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const isSame = differences.length === 0;
|
|
155
|
+
logger.info({
|
|
156
|
+
tag: 'authorization-service-api-comparison',
|
|
157
|
+
accountId,
|
|
158
|
+
userId,
|
|
159
|
+
profile,
|
|
160
|
+
scopedActionsCount: scopedActions.length,
|
|
161
|
+
isSame,
|
|
162
|
+
differencesCount: differences.length,
|
|
163
|
+
differences: differences.length > 0 ? differences : undefined,
|
|
164
|
+
graphApiResponse,
|
|
165
|
+
platformApiResponse,
|
|
166
|
+
timeMs: time,
|
|
167
|
+
}, `API comparison: graphApi vs platformApi - ${isSame ? 'SAME' : 'DIFFERENT'}`);
|
|
168
|
+
// Record metrics for each authorization check (using platform response)
|
|
169
|
+
for (const obj of platformApiResponse) {
|
|
130
170
|
const { action, scope } = obj.scopedAction;
|
|
131
171
|
const { resourceType } = scopeToResource(scope);
|
|
132
172
|
const isAuthorized = obj.permit.can;
|
|
133
173
|
sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time);
|
|
134
|
-
recordAuthorizationTiming(
|
|
174
|
+
recordAuthorizationTiming('platform', time, 'canActionInScopeMultiple');
|
|
135
175
|
}
|
|
136
|
-
|
|
176
|
+
// Return platform API response
|
|
177
|
+
return platformApiResponse;
|
|
137
178
|
}
|
|
138
179
|
static async isAuthorizedSingular(accountId, userId, resources, action) {
|
|
139
180
|
const { authorizationObjects } = createAuthorizationParams(resources, action);
|
|
@@ -1 +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;AAQlC;;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;
|
|
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;AAQlC;;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;IAiCzG;;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"}
|
|
@@ -4,7 +4,7 @@ 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 { GRAPH_APP_NAME } from '../constants.mjs';
|
|
7
|
+
import { GRAPH_APP_NAME, GraphApiProfile } from '../constants.mjs';
|
|
8
8
|
import { handleApiError } from '../utils/api-error-handler.mjs';
|
|
9
9
|
|
|
10
10
|
const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
|
|
@@ -63,6 +63,7 @@ class GraphApi {
|
|
|
63
63
|
url: {
|
|
64
64
|
appName: GRAPH_APP_NAME,
|
|
65
65
|
path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
|
|
66
|
+
profile: GraphApiProfile.PERMISSION,
|
|
66
67
|
},
|
|
67
68
|
method: 'POST',
|
|
68
69
|
headers: {
|
package/dist/esm/constants.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ import { RecursivePartial } from '@mondaydotcomorg/monday-fetch-api';
|
|
|
2
2
|
import { FetcherConfig } from '@mondaydotcomorg/trident-backend-api';
|
|
3
3
|
export declare const APP_NAME = "authorization";
|
|
4
4
|
export declare const GRAPH_APP_NAME = "authorization-graph";
|
|
5
|
+
export declare enum GraphApiProfile {
|
|
6
|
+
PERMISSION = "authorization-graph-permission"
|
|
7
|
+
}
|
|
5
8
|
export declare const ERROR_MESSAGES: {
|
|
6
9
|
readonly HTTP_CLIENT_NOT_INITIALIZED: "MondayAuthorization: HTTP client is not initialized";
|
|
7
10
|
readonly REQUEST_FAILED: (method: string, status: number, reason: string) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAErE,eAAO,MAAM,QAAQ,kBAAkB,CAAC;AACxC,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAEpD,eAAO,MAAM,cAAc;;sCAEA,MAAM,UAAU,MAAM,UAAU,MAAM;CAEvD,CAAC;AAEX,eAAO,MAAM,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAUjE,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAErE,eAAO,MAAM,QAAQ,kBAAkB,CAAC;AACxC,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAEpD,oBAAY,eAAe;IACzB,UAAU,mCAAmC;CAC9C;AAED,eAAO,MAAM,cAAc;;sCAEA,MAAM,UAAU,MAAM,UAAU,MAAM;CAEvD,CAAC;AAEX,eAAO,MAAM,qBAAqB,EAAE,gBAAgB,CAAC,aAAa,CAUjE,CAAC"}
|
package/dist/esm/constants.mjs
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
const APP_NAME = 'authorization';
|
|
2
2
|
const GRAPH_APP_NAME = 'authorization-graph';
|
|
3
|
+
var GraphApiProfile;
|
|
4
|
+
(function (GraphApiProfile) {
|
|
5
|
+
GraphApiProfile["PERMISSION"] = "authorization-graph-permission";
|
|
6
|
+
})(GraphApiProfile || (GraphApiProfile = {}));
|
|
3
7
|
const ERROR_MESSAGES = {
|
|
4
8
|
HTTP_CLIENT_NOT_INITIALIZED: 'MondayAuthorization: HTTP client is not initialized',
|
|
5
9
|
REQUEST_FAILED: (method, status, reason) => `MondayAuthorization: [${method}] request failed with status ${status} with reason: ${reason}`,
|
|
@@ -16,4 +20,4 @@ const DEFAULT_FETCH_OPTIONS = {
|
|
|
16
20
|
},
|
|
17
21
|
};
|
|
18
22
|
|
|
19
|
-
export { APP_NAME, DEFAULT_FETCH_OPTIONS, ERROR_MESSAGES, GRAPH_APP_NAME };
|
|
23
|
+
export { APP_NAME, DEFAULT_FETCH_OPTIONS, ERROR_MESSAGES, GRAPH_APP_NAME, GraphApiProfile };
|
package/package.json
CHANGED
|
@@ -155,19 +155,37 @@ export class AuthorizationService {
|
|
|
155
155
|
logger.error({ tag: 'authorization-service' }, 'AuthorizationService: igniteClient is not set, failing request');
|
|
156
156
|
throw new Error('AuthorizationService: igniteClient is not set, failing request');
|
|
157
157
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
)
|
|
161
|
-
|
|
158
|
+
|
|
159
|
+
const allowedApps = this.igniteClient.configuration.getObjectValue<string[]>(ALLOWED_SDK_PLATFORM_PROFILES_KEY, []);
|
|
160
|
+
const inReleaseApps = this.igniteClient.configuration.getObjectValue<string[]>(IN_RELEASE_SDK_PLATFORM_PROFILES_KEY, []);
|
|
161
|
+
const isInAllowedApps = allowedApps.includes(appName);
|
|
162
|
+
const isInReleaseApps = inReleaseApps.includes(appName);
|
|
163
|
+
const isFeatureFlagReleased = this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId });
|
|
164
|
+
|
|
165
|
+
const debugInfo = {
|
|
166
|
+
appName,
|
|
167
|
+
allowedApps,
|
|
168
|
+
inReleaseApps,
|
|
169
|
+
isInAllowedApps,
|
|
170
|
+
isInReleaseApps,
|
|
171
|
+
isFeatureFlagReleased,
|
|
172
|
+
accountId,
|
|
173
|
+
userId,
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
logger.info({ tag: 'authorization-service', ...debugInfo }, 'AuthorizationService.getProfile debug info');
|
|
177
|
+
|
|
178
|
+
if (isInAllowedApps) {
|
|
179
|
+
const profile = getProfile();
|
|
180
|
+
logger.info({ tag: 'authorization-service', profile }, 'Returning profile from ALLOWED_SDK_PLATFORM_PROFILES_KEY');
|
|
181
|
+
return profile;
|
|
162
182
|
}
|
|
163
|
-
if (
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
this.igniteClient.isReleased(PLATFORM_PROFILE_RELEASE_FF, { accountId, userId })
|
|
168
|
-
) {
|
|
169
|
-
return getProfile();
|
|
183
|
+
if (isInReleaseApps && isFeatureFlagReleased) {
|
|
184
|
+
const profile = getProfile();
|
|
185
|
+
logger.info({ tag: 'authorization-service', profile }, 'Returning profile from IN_RELEASE_SDK_PLATFORM_PROFILES_KEY');
|
|
186
|
+
return profile;
|
|
170
187
|
}
|
|
188
|
+
logger.info({ tag: 'authorization-service', profile: PlatformProfile.APP }, 'Returning default PlatformProfile.APP');
|
|
171
189
|
return PlatformProfile.APP;
|
|
172
190
|
}
|
|
173
191
|
|
|
@@ -180,43 +198,80 @@ export class AuthorizationService {
|
|
|
180
198
|
return [];
|
|
181
199
|
}
|
|
182
200
|
|
|
183
|
-
const shouldNavigateToGraph = Boolean(
|
|
184
|
-
this.igniteClient?.isReleased(NAVIGATE_CAN_ACTION_IN_SCOPE_TO_GRAPH_FF, { accountId, userId })
|
|
185
|
-
);
|
|
186
|
-
|
|
187
201
|
const startTime = performance.now();
|
|
188
|
-
let scopedActionResponseObjects: ScopedActionResponseObject[];
|
|
189
|
-
let apiType: 'graph' | 'platform';
|
|
190
202
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
scopedActionResponseObjects = await this.graphApi.checkPermissions(accountId, userId, scopedActions);
|
|
194
|
-
} else {
|
|
195
|
-
apiType = 'platform';
|
|
196
|
-
const profile = this.getProfile(accountId, userId);
|
|
197
|
-
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
203
|
+
// Always call both APIs for comparison
|
|
204
|
+
const graphApiPromise = this.graphApi.checkPermissions(accountId, userId, scopedActions);
|
|
198
205
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
const profile = this.getProfile(accountId, userId);
|
|
207
|
+
const internalAuthToken = AuthorizationInternalService.generateInternalAuthToken(accountId, userId);
|
|
208
|
+
const platformApiPromise = this.platformApi.checkPermissions(
|
|
209
|
+
profile,
|
|
210
|
+
internalAuthToken,
|
|
211
|
+
userId,
|
|
212
|
+
scopedActions
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
const [graphApiResponse, platformApiResponse] = await Promise.all([graphApiPromise, platformApiPromise]);
|
|
206
216
|
|
|
207
217
|
const endTime = performance.now();
|
|
208
218
|
const time = endTime - startTime;
|
|
209
219
|
|
|
210
|
-
//
|
|
211
|
-
|
|
220
|
+
// Compare responses and log differences
|
|
221
|
+
const differences: Array<{
|
|
222
|
+
action: string;
|
|
223
|
+
scope: ScopeOptions;
|
|
224
|
+
graphResult: ScopedActionPermit;
|
|
225
|
+
platformResult: ScopedActionPermit;
|
|
226
|
+
}> = [];
|
|
227
|
+
|
|
228
|
+
for (let i = 0; i < scopedActions.length; i++) {
|
|
229
|
+
const graphResult = graphApiResponse[i];
|
|
230
|
+
const platformResult = platformApiResponse[i];
|
|
231
|
+
|
|
232
|
+
const graphCan = graphResult?.permit?.can;
|
|
233
|
+
const platformCan = platformResult?.permit?.can;
|
|
234
|
+
|
|
235
|
+
if (graphCan !== platformCan) {
|
|
236
|
+
differences.push({
|
|
237
|
+
action: scopedActions[i].action,
|
|
238
|
+
scope: scopedActions[i].scope,
|
|
239
|
+
graphResult: graphResult?.permit,
|
|
240
|
+
platformResult: platformResult?.permit,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const isSame = differences.length === 0;
|
|
246
|
+
|
|
247
|
+
logger.info(
|
|
248
|
+
{
|
|
249
|
+
tag: 'authorization-service-api-comparison',
|
|
250
|
+
accountId,
|
|
251
|
+
userId,
|
|
252
|
+
profile,
|
|
253
|
+
scopedActionsCount: scopedActions.length,
|
|
254
|
+
isSame,
|
|
255
|
+
differencesCount: differences.length,
|
|
256
|
+
differences: differences.length > 0 ? differences : undefined,
|
|
257
|
+
graphApiResponse,
|
|
258
|
+
platformApiResponse,
|
|
259
|
+
timeMs: time,
|
|
260
|
+
},
|
|
261
|
+
`API comparison: graphApi vs platformApi - ${isSame ? 'SAME' : 'DIFFERENT'}`
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
// Record metrics for each authorization check (using platform response)
|
|
265
|
+
for (const obj of platformApiResponse) {
|
|
212
266
|
const { action, scope } = obj.scopedAction;
|
|
213
267
|
const { resourceType } = scopeToResource(scope);
|
|
214
268
|
const isAuthorized = obj.permit.can;
|
|
215
269
|
sendAuthorizationCheckResponseTimeMetric(resourceType, action, isAuthorized, 200, time);
|
|
216
|
-
recordAuthorizationTiming(
|
|
270
|
+
recordAuthorizationTiming('platform', time, 'canActionInScopeMultiple');
|
|
217
271
|
}
|
|
218
272
|
|
|
219
|
-
|
|
273
|
+
// Return platform API response
|
|
274
|
+
return platformApiResponse;
|
|
220
275
|
}
|
|
221
276
|
|
|
222
277
|
private static async isAuthorizedSingular(
|
package/src/clients/graph-api.ts
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
GraphPermissionReason,
|
|
19
19
|
} from '../types/graph-api.types';
|
|
20
20
|
import { scopeToResource } from '../utils/authorization.utils';
|
|
21
|
-
import { GRAPH_APP_NAME } from '../constants';
|
|
21
|
+
import { GRAPH_APP_NAME, GraphApiProfile } from '../constants';
|
|
22
22
|
import { handleApiError } from '../utils/api-error-handler';
|
|
23
23
|
|
|
24
24
|
const CAN_ACTION_IN_SCOPE_GRAPH_PATH = '/permissions/is-allowed';
|
|
@@ -85,6 +85,7 @@ export class GraphApi {
|
|
|
85
85
|
url: {
|
|
86
86
|
appName: GRAPH_APP_NAME,
|
|
87
87
|
path: CAN_ACTION_IN_SCOPE_GRAPH_PATH,
|
|
88
|
+
profile: GraphApiProfile.PERMISSION,
|
|
88
89
|
},
|
|
89
90
|
method: 'POST',
|
|
90
91
|
headers: {
|
package/src/constants.ts
CHANGED
|
@@ -4,6 +4,10 @@ import { FetcherConfig } from '@mondaydotcomorg/trident-backend-api';
|
|
|
4
4
|
export const APP_NAME = 'authorization';
|
|
5
5
|
export const GRAPH_APP_NAME = 'authorization-graph';
|
|
6
6
|
|
|
7
|
+
export enum GraphApiProfile {
|
|
8
|
+
PERMISSION = 'authorization-graph-permission',
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
export const ERROR_MESSAGES = {
|
|
8
12
|
HTTP_CLIENT_NOT_INITIALIZED: 'MondayAuthorization: HTTP client is not initialized',
|
|
9
13
|
REQUEST_FAILED: (method: string, status: number, reason: string) =>
|