[DevPortal] Fix admin UI and subscriptions#2275
Conversation
📝 WalkthroughUpdated the Developer Portal’s admin and subscription experience across APIs, MCPs, and workflows.
WalkthroughThe PR adds an API docs listing endpoint and supporting metadata, DAO, and service changes; extends sample seeding to include MCP samples; updates API and MCP catalog pages to show deprecated and subscribed states; replaces the MCP landing layout with a two-column configuration and subscription-management UI; removes the old API subscriptions route and page wiring; and revises the API Flows page for bulk selection, deprecation, document uploads, and a three-step wizard. Sequence Diagram(s)sequenceDiagram
participant Client
participant ListApiDocs as apiContentHandler.listApiDocs
participant ApiMetadataService as apiMetadataService.listApiDocs
participant ApiFileDao as apiFileDao.listDocNames
participant APIContentDB as APIContentDatabase
Client->>ListApiDocs: GET /o/{orgId}/devportal/v1/apis/{apiId}/docs
ListApiDocs->>ApiMetadataService: listApiDocs(orgId, apiId)
ApiMetadataService->>ApiFileDao: listDocNames(orgId, apiId)
ApiFileDao->>APIContentDB: query FILE_NAME rows
APIContentDB-->>ApiFileDao: FILE_NAME values
ApiFileDao-->>ApiMetadataService: file names
ApiMetadataService-->>ListApiDocs: [{ fileName }]
ListApiDocs-->>Client: 200 JSON
sequenceDiagram
participant Browser
participant TokenModal as window.showSubscriptionTokenModal
participant WarningModal as window.openWarningModal
participant DevportalApi as devportalApi
participant SubscribeFn as subscribe
Browser->>TokenModal: open token modal
TokenModal->>DevportalApi: GET /subscriptions/{id}
DevportalApi-->>TokenModal: token payload
TokenModal-->>Browser: display token modal
Browser->>WarningModal: switch plan
WarningModal->>DevportalApi: DELETE /subscriptions/{id}
DevportalApi-->>WarningModal: delete response
WarningModal->>SubscribeFn: create replacement subscription
SubscribeFn-->>Browser: refresh card state
Suggested reviewers
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
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. Comment |
|
Caution Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted. Error details |
There was a problem hiding this comment.
Actionable comments posted: 15
🧹 Nitpick comments (2)
portals/developer-portal/src/defaultContent/pages/mcp-landing/page.hbs (1)
21-28: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winConsider pinning CDN assets with Subresource Integrity.
The Highlight.js stylesheet and script are loaded from a third-party CDN without
integrity/crossoriginattributes. Adding SRI hashes strengthens supply-chain assurance for these pinned versions.🤖 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/developer-portal/src/defaultContent/pages/mcp-landing/page.hbs` around lines 21 - 28, The Highlight.js CDN assets in page.hbs are loaded without Subresource Integrity, so update the stylesheet and script tags to include matching integrity values and crossorigin attributes. Keep the existing Highlight.js version pinned, and make the change in the pageHead/pageScripts block where the external highlight.js resources are referenced.Source: Path instructions
portals/developer-portal/src/controllers/viewConfigureController.js (1)
74-74: 🎯 Functional Correctness | 🔵 TrivialVerify the casing of
DP_SUBSCRIPTION_POLICiesused inapi.DP_SUBSCRIPTION_POLICies.The code relies on a mixed-case property
DP_SUBSCRIPTION_POLICiesthat is manually assigned inapiMetadataService.js(line 477) rather than generated automatically by Sequelize's standardasalias convention (which typically usesDP_SUBSCRIPTION_POLICYor pluralized model names in the codebase).While this currently functions due to the explicit manual injection in the data layer, this inconsistency creates a hidden coupling where changes to the DAO implementation or manual assignment logic could silently break the controller without throwing an error. Aligning the property name with the standard association consistency used elsewhere (e.g.,
api.DP_SUBSCRIPTION_POLICY) is recommended to prevent fragility.🤖 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/developer-portal/src/controllers/viewConfigureController.js` at line 74, The controller is reading a manually injected mixed-case association property, so align the `viewConfigureController` lookup with the standard Sequelize association name used by the data layer. Update the `subscriptionPolicies` mapping to use the canonical association symbol exposed by `apiMetadataService` (for example the normal `DP_SUBSCRIPTION_POLICY` style) and adjust the controller to rely on that stable name rather than the fragile `DP_SUBSCRIPTION_POLICies` alias. Verify the corresponding property assignment in `apiMetadataService` matches the same casing so the controller and DAO stay consistent.
🤖 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/developer-portal/src/controllers/apiContentController.js`:
- Around line 116-125: The tag list is being built from the full metadata
instead of the filtered results, so `apiTags` can mismatch the current page.
Update `apiContentController` to derive tags from `filteredList` right after the
`isMcpPage`/`filteredList` logic, and pass those tags into `templateContent` so
`/mcps` and `/apis` only expose tags relevant to the selected API subset.
- Around line 359-365: The subscription mapping in apiContentController should
keep the raw POLICY_NAME in policyName for template comparisons while exposing
the readable label in subscriptionPlanName. Verify the object built from
sub.DP_SUBSCRIPTION_POLICY uses the right fallbacks for POLICY_NAME and
DISPLAY_NAME, and keep the subscriptionToken/maskedToken handling consistent in
the same block.
In `@portals/developer-portal/src/dao/apiFileDao.js`:
- Around line 547-553: The deleteByFileName flow in apiFileDao.js is deleting
rows by FILE_NAME and API_ID only, which can affect non-doc content that shares
the same filename. Update the APIContent query and the subsequent
APIContent.destroy call to apply the same document-type prefix filter used by
listDocNames, so only doc-scoped rows are selected and removed. Keep the change
localized around deleteByFileName and the contentsToDelete loop.
In `@portals/developer-portal/src/defaultContent/pages/api-landing/page.hbs`:
- Around line 32-38: The breadcrumb in page.hbs is resolving the API label
differently than the hero, so align the two displays to use the same field
resolution. Update the breadcrumb current item to match the logic used by
api-detail-banner.hbs and keep apiMetadata.apiInfo as the source of truth, using
the same apiTitle/apiName fallback behavior in both places so the label stays
consistent across the page.
In
`@portals/developer-portal/src/defaultContent/pages/api-landing/partials/api-subscription-plans.hbs`:
- Around line 233-249: The unsubscribe dialog title is being assembled with
dynamic plan names inserted through innerHTML, so update showUnsubDialog and
askUnsub to render the static title markup once and set the plan name via
textContent on the dedicated element instead of interpolating
_sub.subscriptionPlanName into HTML. Apply the same pattern in openWarningModal
as well, so any plan-name or similar dynamic value is handled as text and the
dialog builders remain easy to locate by their function names.
In
`@portals/developer-portal/src/defaultContent/pages/home/partials/onboarding-overlay.hbs`:
- Around line 149-150: Update the onboarding copy in onboarding-overlay.hbs so
it no longer refers only to “sample APIs” now that SAMPLES includes an MCP entry
like TravelAssistantMCP; adjust the headings/messages and any
progress/completion text to use a broader term such as samples or sample
integrations. Locate the existing onboarding strings near the SAMPLES list and
replace any API-specific wording consistently so the text matches the seeded
sample types.
In `@portals/developer-portal/src/defaultContent/pages/mcp-landing/page.hbs`:
- Around line 28-33: Highlight.js initialization in page.hbs can run before the
`.mc-json-block pre code` and `.mc-config-pre code` nodes exist, so the inline
`querySelectorAll(...).forEach(hljs.highlightElement)` should be guarded until
the DOM is ready. Update the script near the `hljs.highlightElement` call to run
inside a `DOMContentLoaded` check (or equivalent ready-state guard), matching
the deferred script behavior used elsewhere, so the selector runs after the
target elements are present.
In
`@portals/developer-portal/src/defaultContent/pages/mcp-landing/partials/mcp-default.hbs`:
- Around line 44-47: The mcp-default.hbs template uses the jsonBeautify helper,
but its registration is not clearly guaranteed in the Handlebars setup. Verify
that handlebarsHelpers.js is imported and jsonBeautify is explicitly registered
in the Handlebars instance initialization used by the developer portal, or
update the setup so this helper is included via the existing helper registration
path.
In
`@portals/developer-portal/src/defaultContent/pages/mcp-landing/partials/mcp-subscription-plans.hbs`:
- Around line 257-267: The closeUnsub function is clearing the wrong
_activeSubCard reference because that variable is scoped inside init rather than
shared with the cancel path. Hoist _activeSubCard to the outer IIFE scope in
mcp-subscription-plans.hbs, matching the pattern used in the API partial, so
closeUnsub can reliably reset it when handling the switch/unsubscribe flow.
In
`@portals/developer-portal/src/defaultContent/pages/mcp/partials/mcp-listing.hbs`:
- Around line 136-153: The inline navigation script added in mcp-listing.hbs is
not represented in the allowlist, so update util.js by adding a separate
allowedInlineScripts entry for the data-href-only handler that matches this
script. Keep the existing api-listing combined script entry intact, and ensure
the new entry uniquely covers the click handler logic in the mcp-listing partial
so theme validation accepts it during deployment.
In `@portals/developer-portal/src/defaultContent/styles/main.css`:
- Around line 2-3: The stylesheet has Stylelint violations in the Google Fonts
import and font-family usage. Update the Inter font import in the main
stylesheet to match the configured import-notation rule, and normalize any
font-family token usage in the same file so value-keyword-case is satisfied.
Check the font declaration(s) around the existing `@import` and the related
font-family rule near the referenced style block, then keep both entries
lint-clean with the expected casing and import form.
In `@portals/developer-portal/src/defaultContent/styles/mcp-landing.css`:
- Line 434: The `currentColor` value in the MCP landing styles is tripping the
`value-keyword-case` lint rule, so update the `background` declaration in the
relevant CSS rule to use the lowercase keyword form. Keep the change isolated to
the style definition in `mcp-landing.css` and preserve the existing behavior
while making the keyword casing consistent with Stylelint expectations.
In `@portals/developer-portal/src/pages/api-flows/page.hbs`:
- Line 916: The status mapping in the API flows page is collapsing any
non-DEPRECATED value to PUBLISHED, which causes draft APIs to be published when
saved. Update the status handling around the wz-status select in page.hbs so
editing an API preserves api.apiStatus unless the user explicitly changes it;
either include DRAFT as a selectable option or keep the current value when it is
not one of the allowed choices.
In `@portals/developer-portal/src/services/apiMetadataService.js`:
- Around line 493-497: The update flow in apiMetadataService’s document-upload
section is using apiFileDao.store for req.files.docs, which is not replace-safe
when a filename is re-uploaded. Switch this path to the docs-scoped upsert logic
used by the other update flows so re-uploading the same document replaces the
existing stored file instead of failing or duplicating entries; keep the change
localized to the apiFileDao call inside the req.files.docs loop.
In `@portals/developer-portal/src/services/sampleSeederService.js`:
- Around line 100-104: The pre-check in sampleSeederService is not enough to
prevent duplicate inserts under concurrency, so the catch handling in
seedSampleAPIs and seedSampleMCPs should treat unique-constraint violations as
an idempotent duplicate. Update both catch blocks to detect the DB duplicate-key
error from the transaction insert path and push an { name, status: 'exists' }
result instead of marking it failed, keeping the existing existsByNameVersion
pre-check and result-shaping logic intact.
---
Nitpick comments:
In `@portals/developer-portal/src/controllers/viewConfigureController.js`:
- Line 74: The controller is reading a manually injected mixed-case association
property, so align the `viewConfigureController` lookup with the standard
Sequelize association name used by the data layer. Update the
`subscriptionPolicies` mapping to use the canonical association symbol exposed
by `apiMetadataService` (for example the normal `DP_SUBSCRIPTION_POLICY` style)
and adjust the controller to rely on that stable name rather than the fragile
`DP_SUBSCRIPTION_POLICies` alias. Verify the corresponding property assignment
in `apiMetadataService` matches the same casing so the controller and DAO stay
consistent.
In `@portals/developer-portal/src/defaultContent/pages/mcp-landing/page.hbs`:
- Around line 21-28: The Highlight.js CDN assets in page.hbs are loaded without
Subresource Integrity, so update the stylesheet and script tags to include
matching integrity values and crossorigin attributes. Keep the existing
Highlight.js version pinned, and make the change in the pageHead/pageScripts
block where the external highlight.js resources are referenced.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2d621f9b-d6b2-4e1b-af1e-b8612350451a
📒 Files selected for processing (50)
portals/developer-portal/CLAUDE.mdportals/developer-portal/docs/devportal-openapi-spec-v1.yamlportals/developer-portal/src/controllers/apiContentController.jsportals/developer-portal/src/controllers/subscriptionsContentController.jsportals/developer-portal/src/controllers/viewConfigureController.jsportals/developer-portal/src/dao/apiDao.jsportals/developer-portal/src/dao/apiFileDao.jsportals/developer-portal/src/dao/subscriptionDao.jsportals/developer-portal/src/db/betterSqlite3Compat.jsportals/developer-portal/src/defaultContent/pages/api-keys/page.hbsportals/developer-portal/src/defaultContent/pages/api-landing/page.hbsportals/developer-portal/src/defaultContent/pages/api-landing/partials/api-detail-banner.hbsportals/developer-portal/src/defaultContent/pages/api-landing/partials/api-subscription-plans.hbsportals/developer-portal/src/defaultContent/pages/api-subscriptions/page.hbsportals/developer-portal/src/defaultContent/pages/api-subscriptions/partials/api-subscription-list.hbsportals/developer-portal/src/defaultContent/pages/apis/partials/api-listing.hbsportals/developer-portal/src/defaultContent/pages/home/partials/home.hbsportals/developer-portal/src/defaultContent/pages/home/partials/onboarding-overlay.hbsportals/developer-portal/src/defaultContent/pages/mcp-landing/page.hbsportals/developer-portal/src/defaultContent/pages/mcp-landing/partials/mcp-config-sidebar.hbsportals/developer-portal/src/defaultContent/pages/mcp-landing/partials/mcp-default.hbsportals/developer-portal/src/defaultContent/pages/mcp-landing/partials/mcp-detail-banner.hbsportals/developer-portal/src/defaultContent/pages/mcp-landing/partials/mcp-subscription-plans.hbsportals/developer-portal/src/defaultContent/pages/mcp/partials/mcp-listing.hbsportals/developer-portal/src/defaultContent/pages/subscriptions/page.hbsportals/developer-portal/src/defaultContent/partials/sidebar.hbsportals/developer-portal/src/defaultContent/styles/api-content.cssportals/developer-portal/src/defaultContent/styles/api-landing.cssportals/developer-portal/src/defaultContent/styles/api-listing.cssportals/developer-portal/src/defaultContent/styles/components.cssportals/developer-portal/src/defaultContent/styles/home.cssportals/developer-portal/src/defaultContent/styles/login.cssportals/developer-portal/src/defaultContent/styles/main.cssportals/developer-portal/src/defaultContent/styles/mcp-landing.cssportals/developer-portal/src/helpers/handlebarsHelpers.jsportals/developer-portal/src/middlewares/registerPartials.jsportals/developer-portal/src/pages/api-flows/page.hbsportals/developer-portal/src/pages/api-flows/partials/api-flows.hbsportals/developer-portal/src/pages/api-flows/partials/create-api-flow.hbsportals/developer-portal/src/pages/default-home/page.hbsportals/developer-portal/src/pages/login-page/partials/signin-card.hbsportals/developer-portal/src/routes/api/handlers/apiContentHandler.jsportals/developer-portal/src/routes/pages/apiContentRoute.jsportals/developer-portal/src/scripts/api-flows.jsportals/developer-portal/src/scripts/common.jsportals/developer-portal/src/services/apiMetadataService.jsportals/developer-portal/src/services/sampleSeederService.jsportals/developer-portal/src/styles/api-flows.cssportals/developer-portal/src/styles/settings-layout.cssportals/developer-portal/src/utils/constants.js
💤 Files with no reviewable changes (8)
- portals/developer-portal/src/defaultContent/pages/api-subscriptions/page.hbs
- portals/developer-portal/src/defaultContent/pages/subscriptions/page.hbs
- portals/developer-portal/src/defaultContent/pages/api-subscriptions/partials/api-subscription-list.hbs
- portals/developer-portal/CLAUDE.md
- portals/developer-portal/src/routes/pages/apiContentRoute.js
- portals/developer-portal/src/defaultContent/styles/api-content.css
- portals/developer-portal/src/styles/api-flows.css
- portals/developer-portal/src/defaultContent/styles/login.css
….css Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Purpose
Goals
Approach
$subject
Security checks