Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -204,33 +204,43 @@ class AuthManager {
* @param {*} api
*/
static isRestricted(scopesAllowedToEdit, api = {}) {
const user = AuthManager.getUser();

if (!user) {
return true;
}
// Block read-only users right away
if (AuthManager.isReadOnlyUser()) {
return true;
}
// determines whether the apiType is API PRODUCT and user has publisher role, then allow access.
if (api.apiType === 'APIPRODUCT') {
if (AuthManager.getUser().scopes.includes('apim:api_publish')) {
return false;
} else {
return true;
}
return !user.scopes.includes('apim:api_publish');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GavinHemsada the user object here return !user.scopes.includes('apim:api_publish'); does not seem to have been initialised.

}
// If user doesn't have any of the required scopes → restrict
const hasAllowedScope =
scopesAllowedToEdit.some(scope => user.scopes.includes(scope));
if (!hasAllowedScope) {
return true;
}
// Check for publisher override (publisher can always access)
const isPublisherOverride =
user.scopes.includes('apim:api_publish') ||
(api.apiType === 'MCP' && user.scopes.includes('apim:mcp_server_publish'));

// determines whether the user is a publisher or creator (based on what is passed from the element)
// if (scopesAllowedToEdit.filter(element => AuthManager.getUser().scopes.includes(element)).length > 0) {
if (AuthManager.getUser()
&& scopesAllowedToEdit.find((element) => AuthManager.getUser().scopes.includes(element))) {
// if the user has publisher role, no need to consider the api LifeCycleStatus
const isPublisherOverride = AuthManager.getUser().scopes.includes('apim:api_publish')
|| (api.apiType === 'MCP' && AuthManager.getUser().scopes.includes('apim:mcp_server_publish'));
if ((Object.keys(api).length === 0 && api.constructor === Object) || isPublisherOverride) {
return false;
} else if (
// if the user has creator role, but not the publisher role
api.lifeCycleStatus === 'CREATED'
|| api.lifeCycleStatus === 'PROTOTYPED'
) {
return false;
} else {
return true;
}
if (isPublisherOverride) {
return false; // unrestricted
}

// Handle create-page case (empty api object)
if (Object.keys(api).length === 0 && api.constructor === Object) {
// Only allow users with create permission on create pages
return !user.scopes.includes('apim:api_create');
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard against api being null before calling Object.keys.

Several callers pass null while the API payload is still loading (e.g., initial React renders). With the new logic, Object.keys(api) will throw TypeError: Cannot convert undefined or null to object, breaking those routes before the user even hits the create-page path. Please short-circuit when api is falsy before touching Object.keys.

Apply this diff to avoid the crash:

-        if (Object.keys(api).length === 0 && api.constructor === Object) {
-            // Only allow users with create permission on create pages
-            return !user.scopes.includes('apim:api_create');
-        }
+        if (
+            !api
+            || (api.constructor === Object && Object.keys(api).length === 0)
+        ) {
+            // Only allow users with create permission on create pages
+            return !user.scopes.includes('apim:api_create');
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (Object.keys(api).length === 0 && api.constructor === Object) {
// Only allow users with create permission on create pages
return !user.scopes.includes('apim:api_create');
}
if (
!api
|| (api.constructor === Object && Object.keys(api).length === 0)
) {
// Only allow users with create permission on create pages
return !user.scopes.includes('apim:api_create');
}
🤖 Prompt for AI Agents
In portals/publisher/src/main/webapp/source/src/app/data/AuthManager.js around
lines 235 to 238, guard against api being null/undefined before calling
Object.keys by short-circuiting when api is falsy; change the condition to first
check if (!api) return <appropriate value> or combine as if (!api ||
(Object.keys(api).length === 0 && api.constructor === Object)) { ... } so you
never call Object.keys on null/undefined and preserve the existing behavior of
only allowing users with 'apim:api_create' on create pages.


// Allow creator access based on lifecycle status
if (api.lifeCycleStatus === 'CREATED' || api.lifeCycleStatus === 'PROTOTYPED') {
return false;
}
return true;
}
Expand Down