Skip to content

Fix multiple UI UX issues - #3062

Merged
lasanthaS merged 20 commits into
wso2:mainfrom
Piumal1999:rb-bug-fixes
Aug 2, 2026
Merged

Fix multiple UI UX issues#3062
lasanthaS merged 20 commits into
wso2:mainfrom
Piumal1999:rb-bug-fixes

Conversation

@Piumal1999

@Piumal1999 Piumal1999 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Purpose

$subject

Fixes #3059
Fixes #3058
Fixes #3057

Summary

  • Updated Login page logo
  • "Revoke keys" renamed to "Remove keys" in application keys
  • MCP playground URL now auto-fetched from the API definition instead of rendering blank
  • "MCP Servers" breadcrumb pointed at /mcp; now links correctly
  • Non-existent view returns a proper 404 page on all view routes, not just some
  • Views can be created without labels; API description is now optional
  • Labels and Webhooks admin UIs show name and handle
  • Handles are read-only when editing (immutable after creation)
  • Editing a label no longer drops APIs from that label
  • Removed service API key authentication (static shared-secret header auth)
  • Control-plane reference ID now behaves like the IDP reference ID, defaulting to the org handle
  • Missing content pages return 404 instead of 500 (bare Error had no status, so pageErrorStatus() fell back to 500)
  • Markdown/agent endpoints now set the correct Content-Type on error responses (previously fell back to text/html for a markdown body)
  • Read-only inputs keep a visible (muted) keyboard focus ring instead of none

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

API Portal changes

Layer / File(s) Summary
Session authentication and service API-key removal
portals/api-portal/src/middlewares/*, portals/api-portal/it/ui/cypress/*, portals/api-portal/it/rest-api/*
Removed static service API-key authentication. Cypress and integration requests now use logged-in sessions with CSRF tokens.
Role-mode authorization fixtures and tests
.github/workflows/*, portals/api-portal/it/configs/*, portals/api-portal/it/rest-api/auth/*, portals/api-portal/it/Makefile
Added scope and role authorization modes, role mappings, grant parity checks, and a four-way database and authorization test matrix.
Content rendering and status-aware responses
portals/api-portal/src/controllers/*, portals/api-portal/src/utils/util.js, portals/api-portal/src/defaultContent/*, portals/api-portal/it/rest-api/ai-discovery/*
Added status-aware page and Markdown errors. Updated API catalog grouping, MCP URLs, GraphQL headers, breadcrumb paths, version rendering, and visibility coverage.
View, organization, and resource management contracts
portals/api-portal/docs/*, portals/api-portal/src/services/*, portals/api-portal/src/scripts/settings-*, portals/api-portal/src/pages/settings/*, portals/api-portal/it/rest-api/views-and-labels/*
Made view labels optional. Added clearing for organization references. Made resource handles immutable during edits and updated webhook validation and persistence.
Portal copy and key-management UI
portals/api-portal/src/pages/application/*, portals/api-portal/src/scripts/oauth2-key-generation.js, portals/api-portal/src/pages/login-page/*, portals/api-portal/src/styles/*, portals/api-portal/docs/consume-an-api/*
Changed key-removal wording to describe client-ID unlinking, updated login branding, and added read-only field styling.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TestRunner
  participant ApiPortal
  participant AuthorizationConfig
  TestRunner->>ApiPortal: send request with selected authorization mode
  ApiPortal->>AuthorizationConfig: resolve scope or role grants
  AuthorizationConfig-->>ApiPortal: return grants
  ApiPortal-->>TestRunner: allow or deny request
Loading

Possibly related PRs

Suggested reviewers: lasanthas, krishanx92, renuka-fernando

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description contains only the template headings and placeholder text, with no purpose, goals, approach, testing, security checks, or environment details. Complete each required section with specific issue references, implementation details, test results, documentation links, security confirmations, related PRs, and the test environment.
Docstring Coverage ⚠️ Warning Docstring coverage is 42.31% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is generic and does not identify the main changes, which include authentication removal, authorization tests, API behavior, and UI updates. Replace the title with a specific summary of the primary change, such as removing service API key authentication and updating portal authorization tests.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
portals/api-portal/src/middlewares/authMiddleware.js (2)

400-412: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the stale "org resolved from header" comment.

The comment on line 400 says the mTLS branch resolves the org "from the organization request header." The function it calls, resolvePortalOrg (documented at lines 246-253), does the opposite: the header no longer selects the organization, it is only checked for a mismatch. Update the line 400 comment to match the documented behavior of resolvePortalOrg, or a future reader will misunderstand how org selection works for mTLS credentials.

📝 Proposed fix
-        // 4. mTLS — org resolved from the `organization` request header
+        // 4. mTLS — org resolved from the portal's configured organization;
+        //    the `organization` header, if present, is only checked for a mismatch.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/src/middlewares/authMiddleware.js` around lines 400 - 412,
Update the comment immediately above the mTLS branch in the authentication
middleware to state that resolvePortalOrg validates the organization header for
mismatches rather than selecting the organization from it; leave the
resolvePortalOrg call and authentication behavior unchanged.

465-479: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Correct the apiKeyAuth docstring — it inverts the actual acceptance rule.

The docstring says this handler "Accepts any preauthorized non-OAuth mode (mTLS, role-mode session)." That does not match req.auth?.preauthorized:

  • Role-mode sessions set preauthorized: !isRoleMode(), which is false in role mode (line 347) — they are rejected, not accepted, contradicting "role-mode session" in the doc.
  • Scope-mode IDP sessions have mode: 'oauth2' and preauthorized: true — they are accepted, contradicting "non-OAuth mode" in the doc.

This handler is currently unreachable (no operation declares apiKeyAuth), so there is no live exposure. Still, fix the wording now so a future engineer who adds security: [apiKeyAuth] to an operation does not rely on an incorrect mental model of which sessions pass.

📝 Proposed fix
- * Accepts any preauthorized non-OAuth mode (mTLS, role-mode session).
+ * Accepts any mode with req.auth.preauthorized === true — currently mTLS,
+ * and scope-mode OAuth2 sessions (preauthorized is false for role-mode
+ * sessions, platform-jwt sessions, and bearer tokens).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/src/middlewares/authMiddleware.js` around lines 465 - 479,
Correct the apiKeyAuth docstring to state that the handler accepts requests only
when req.auth?.preauthorized is true, including scope-mode OAuth2 sessions, and
does not accept role-mode sessions when they set it false. Remove the inaccurate
“non-OAuth” and “role-mode session” wording while preserving the surrounding
credential-store and scope-check guidance.
🧹 Nitpick comments (1)
portals/api-portal/it/rest-api/views-and-labels/views.spec.js (1)

63-67: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Verify persistence for an explicit empty label array.

The test checks only 201 for labels: []. It does not prove that the stored view has an empty label set. Fetch /views/${id} and assert fetched.body.labels is [], as in the omitted-label test.

Proposed test assertion
         expect(res.status).toBe(201);
+        const fetched = await client.as('admin').get(`/views/${id}`);
+        expect(fetched.status).toBe(200);
+        expect(fetched.body.labels).toEqual([]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/it/rest-api/views-and-labels/views.spec.js` around lines
63 - 67, Update the creates-a-view-with-an-empty-label-array test around
uniqueHandle and the POST request to fetch /views/${id} after confirming
creation, then assert the fetched response’s body.labels is an empty array,
matching the omitted-label persistence test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@portals/api-portal/src/controllers/apiContentController.js`:
- Around line 1139-1143: Update sendMarkdownError to set the response
Content-Type to the caller’s success media type before sending either the 404 or
500 markdown body, passing that media type into the helper if necessary and
updating its callers accordingly.

In `@portals/api-portal/src/controllers/customContentController.js`:
- Line 105: Update the locally generated missing-page errors in the controller
to include a 404 status before they are passed to next(error), ensuring
pageErrorStatus(error) maps both missing-file branches to HTTP 404 instead of
500.

In `@portals/api-portal/src/pages/application/partials/manage-keys-km-card.hbs`:
- Around line 65-74: Update the removal messaging in the manage-keys footer and
the related confirmation flows in confirmAndRemoveKeys and
oauth2-key-generation.js to accurately describe the DELETE route: it removes
only the portal’s local OAuth client_id mapping, while external OAuth clients
and already-issued tokens remain active. Remove wording that claims credentials
are deleted or tokens are revoked, and synchronize any related documentation
with this behavior.

In `@portals/api-portal/src/styles/settings-layout.css`:
- Around line 612-615: Update the .cfg-form-input[readonly]:focus rule to retain
a clearly visible keyboard-focus indicator instead of removing all focus
styling. Add or preserve a distinct outline, border, or shadow that contrasts
with the base read-only input appearance.

---

Outside diff comments:
In `@portals/api-portal/src/middlewares/authMiddleware.js`:
- Around line 400-412: Update the comment immediately above the mTLS branch in
the authentication middleware to state that resolvePortalOrg validates the
organization header for mismatches rather than selecting the organization from
it; leave the resolvePortalOrg call and authentication behavior unchanged.
- Around line 465-479: Correct the apiKeyAuth docstring to state that the
handler accepts requests only when req.auth?.preauthorized is true, including
scope-mode OAuth2 sessions, and does not accept role-mode sessions when they set
it false. Remove the inaccurate “non-OAuth” and “role-mode session” wording
while preserving the surrounding credential-store and scope-check guidance.

---

Nitpick comments:
In `@portals/api-portal/it/rest-api/views-and-labels/views.spec.js`:
- Around line 63-67: Update the creates-a-view-with-an-empty-label-array test
around uniqueHandle and the POST request to fetch /views/${id} after confirming
creation, then assert the fetched response’s body.labels is an empty array,
matching the omitted-label persistence test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c30c0454-113e-4dee-90a7-548a1c8afd22

📥 Commits

Reviewing files that changed from the base of the PR and between 29f710c and b690361.

⛔ Files ignored due to path filters (2)
  • portals/api-portal/src/defaultContent/images/api-portal-logo-white.png is excluded by !**/*.png
  • portals/api-portal/src/defaultContent/images/api-portal-logo-white.svg is excluded by !**/*.svg
📒 Files selected for processing (54)
  • portals/api-portal/configs/config-template.toml
  • portals/api-portal/docs/api-portal-openapi-spec-v0.9.yaml
  • portals/api-portal/docs/consume-an-api/consume-with-oauth2.md
  • portals/api-portal/it/README.md
  • portals/api-portal/it/configs/portal-roles-role-mode-it.yaml
  • portals/api-portal/it/docker-compose.test.postgres.yaml
  • portals/api-portal/it/docker-compose.test.yaml
  • portals/api-portal/it/rest-api/ai-discovery/apis-md.spec.js
  • portals/api-portal/it/rest-api/auth/role-mode-authorization.spec.js
  • portals/api-portal/it/rest-api/organizations/single-org-isolation.spec.js
  • portals/api-portal/it/rest-api/support/fixtures.js
  • portals/api-portal/it/rest-api/views-and-labels/views.spec.js
  • portals/api-portal/it/test-config.toml
  • portals/api-portal/it/ui/cypress/e2e/001-basic/001-portal-access.cy.js
  • portals/api-portal/it/ui/cypress/e2e/002-apis/001-api-listing.cy.js
  • portals/api-portal/it/ui/cypress/e2e/002-apis/002-rest-api-details.cy.js
  • portals/api-portal/it/ui/cypress/e2e/003-mcp-servers/001-mcp-listing.cy.js
  • portals/api-portal/it/ui/cypress/e2e/applications/application-flows.cy.js
  • portals/api-portal/it/ui/cypress/e2e/settings/001-views-labels.cy.js
  • portals/api-portal/it/ui/cypress/e2e/settings/002-key-managers.cy.js
  • portals/api-portal/it/ui/cypress/support/commands/portal.js
  • portals/api-portal/it/ui/cypress/support/commands/seed.js
  • portals/api-portal/src/config/configDefaults.js
  • portals/api-portal/src/controllers/apiContentController.js
  • portals/api-portal/src/controllers/apiKeysOverviewController.js
  • portals/api-portal/src/controllers/apiWorkflowsController.js
  • portals/api-portal/src/controllers/applicationsContentController.js
  • portals/api-portal/src/controllers/customContentController.js
  • portals/api-portal/src/controllers/orgContentController.js
  • portals/api-portal/src/controllers/subscriptionsContentController.js
  • portals/api-portal/src/dao/organizationDao.js
  • portals/api-portal/src/defaultContent/pages/apis/partials/apis-md.hbs
  • portals/api-portal/src/defaultContent/pages/docs/page.hbs
  • portals/api-portal/src/defaultContent/pages/mcp-landing/page.hbs
  • portals/api-portal/src/defaultContent/pages/mcps/partials/mcps-md.hbs
  • portals/api-portal/src/middlewares/authMiddleware.js
  • portals/api-portal/src/middlewares/csrfProtection.js
  • portals/api-portal/src/middlewares/ensureAuthenticated.js
  • portals/api-portal/src/middlewares/registerPartials.js
  • portals/api-portal/src/pages/application/partials/manage-keys-km-card.hbs
  • portals/api-portal/src/pages/login-page/layout.hbs
  • portals/api-portal/src/pages/settings/partials/cfg-apis-panel.hbs
  • portals/api-portal/src/pages/settings/partials/cfg-labels-panel.hbs
  • portals/api-portal/src/pages/settings/partials/cfg-modals.hbs
  • portals/api-portal/src/pages/settings/partials/cfg-webhook-form.hbs
  • portals/api-portal/src/pages/settings/partials/cfg-webhooks-panel.hbs
  • portals/api-portal/src/scripts/oauth2-key-generation.js
  • portals/api-portal/src/scripts/settings-apis.js
  • portals/api-portal/src/scripts/settings-labels.js
  • portals/api-portal/src/scripts/settings-organization.js
  • portals/api-portal/src/scripts/settings-webhooks.js
  • portals/api-portal/src/services/apiMetadataService.js
  • portals/api-portal/src/styles/settings-layout.css
  • portals/api-portal/src/utils/util.js
💤 Files with no reviewable changes (3)
  • portals/api-portal/src/config/configDefaults.js
  • portals/api-portal/configs/config-template.toml
  • portals/api-portal/src/middlewares/ensureAuthenticated.js

Comment thread portals/api-portal/src/controllers/apiContentController.js Outdated
Comment thread portals/api-portal/src/controllers/customContentController.js
Comment thread portals/api-portal/src/styles/settings-layout.css

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
portals/api-portal/src/scripts/oauth2-key-generation.js (1)

61-61: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Invoke key removal through the confirmation flow.

warning.js calls removeApplicationKeys(...) directly for the removeKeys path, so openWarningModal('removeKeys', ...) -> Remove can bypass confirmAndRemoveKeys. Route this modal callback through confirmAndRemoveKeys instead of the direct deletion helper.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@portals/api-portal/src/scripts/oauth2-key-generation.js` at line 61, Update
the removeKeys callback used by openWarningModal so its Remove action invokes
confirmAndRemoveKeys(applicationId, keyMappingId, keyType) instead of calling
removeApplicationKeys directly, ensuring key deletion always passes through
confirmation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@portals/api-portal/src/scripts/oauth2-key-generation.js`:
- Line 93: Update the fallback confirmation prompt in the unlink-client flow
around confirm so it also states that already-issued tokens remain valid until
expiry, matching the modal text; preferably reuse a shared confirmation-message
constant if one already exists.

---

Outside diff comments:
In `@portals/api-portal/src/scripts/oauth2-key-generation.js`:
- Line 61: Update the removeKeys callback used by openWarningModal so its Remove
action invokes confirmAndRemoveKeys(applicationId, keyMappingId, keyType)
instead of calling removeApplicationKeys directly, ensuring key deletion always
passes through confirmation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5e3d668b-13e4-49f4-87ed-1762a96c6e9a

📥 Commits

Reviewing files that changed from the base of the PR and between b690361 and d2aa71e.

⛔ Files ignored due to path filters (1)
  • portals/api-portal/it/rest-api/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (20)
  • .github/workflows/devportal-integration-test.yml
  • portals/api-portal/it/Makefile
  • portals/api-portal/it/README.md
  • portals/api-portal/it/configs/config-platform-api-it.toml
  • portals/api-portal/it/configs/portal-roles-it.yaml
  • portals/api-portal/it/configs/roles-platform-api-it.yaml
  • portals/api-portal/it/docker-compose.test.postgres.yaml
  • portals/api-portal/it/docker-compose.test.yaml
  • portals/api-portal/it/rest-api/auth/authorization-mode.spec.js
  • portals/api-portal/it/rest-api/auth/grant-table-parity.spec.js
  • portals/api-portal/it/rest-api/package.json
  • portals/api-portal/it/rest-api/support/client.js
  • portals/api-portal/it/rest-api/views-and-labels/views.spec.js
  • portals/api-portal/src/controllers/apiContentController.js
  • portals/api-portal/src/controllers/customContentController.js
  • portals/api-portal/src/middlewares/authMiddleware.js
  • portals/api-portal/src/pages/application/partials/manage-keys-km-card.hbs
  • portals/api-portal/src/scripts/oauth2-key-generation.js
  • portals/api-portal/src/services/apiMetadataService.js
  • portals/api-portal/src/styles/settings-layout.css
🚧 Files skipped from review as they are similar to previous changes (5)
  • portals/api-portal/src/pages/application/partials/manage-keys-km-card.hbs
  • portals/api-portal/src/styles/settings-layout.css
  • portals/api-portal/src/middlewares/authMiddleware.js
  • portals/api-portal/it/rest-api/views-and-labels/views.spec.js
  • portals/api-portal/src/controllers/apiContentController.js

Comment thread portals/api-portal/src/scripts/oauth2-key-generation.js
@lasanthaS
lasanthaS merged commit 95ebb37 into wso2:main Aug 2, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants