Skip to content

Implement pagination support across various API handlers and repositories#2561

Merged
Thushani-Jayasekera merged 4 commits into
wso2:mainfrom
Thushani-Jayasekera:pagination
Jul 9, 2026
Merged

Implement pagination support across various API handlers and repositories#2561
Thushani-Jayasekera merged 4 commits into
wso2:mainfrom
Thushani-Jayasekera:pagination

Conversation

@Thushani-Jayasekera

Copy link
Copy Markdown
Contributor

Add sortBy / sortOrder / query to core collection list endpoints

Summary

Extends the standard collection GET contract (APR-008) with sorting and search
on the four core org-scoped resources. Building on the existing limit/offset
pagination, list endpoints now accept:

Param Type Values / default Purpose
sortBy string name | createdAt (default createdAt) Field to sort by
sortOrder string asc | desc (default desc) Sort direction
query string Case-insensitive substring match on the id (handle)

Wired on: GET /rest-apis, GET /projects, GET /applications, GET /gateways.

sortBy/sortOrder/query are applied at the database (SQL ORDER BY + WHERE handle LIKE ?), and the same search filter is mirrored into the COUNT query so
pagination.total stays consistent when a search is active.

Design notes

  • Injection safety (the reason sortBy is an enum). sortBy/sortOrder
    cannot be bind parameters — they are interpolated into the ORDER BY clause. A
    new ListOptions.resolveSort maps the client's sortBy token to a real column
    only through a hardcoded allowlist (listSortColumns), falling back to the
    default column on anything unrecognized, and constrains the direction to the
    ASC/DESC constants. The raw client string never reaches the SQL.
  • Search escaping. handleSearchClause builds AND LOWER(handle) LIKE ? ESCAPE '\' with the term lowercased and its % / _ / \ escaped, so
    wildcards match literally. The value is a bind parameter — no injection surface.
  • Graceful fallback, not rejection. An unknown sortBy (or garbage
    sortOrder) silently falls back to the default rather than erroring, matching
    how out-of-range limit/offset are already clamped.
  • Threading. A repository.ListOptions struct carries the inputs
    handler → service → repository, keeping method signatures from ballooning.
    Handlers parse via a new parseListOptions helper (consistent with the
    existing parsePagination).

Changes

Repository

  • internal/repository/pagination.go (new)ListOptions, resolveSort
    (allowlist-based safe ORDER BY), handleSearchClause (escaped case-insensitive LIKE).
  • interfaces.go, api.go, project.go, application.go, gateway.go
    List* methods take ListOptions; Count* methods take a search arg; SQL
    updated (gateway's inner/outer join order kept in sync).

Service

  • api.go, project.go, application.go, gateway.go — thread ListOptions
    through; pass search to the count call; fixed the extra
    CountApplicationsByProjectID caller in project.go.

Handler

  • pagination.go — added parseListOptions (normalizes sortOrder, passes
    sortBy through for downstream allowlist resolution, trims query).
  • api.go, project.go, application.go, gateway.go — use parseListOptions.

Spec / generated

  • resources/openapi.yaml — added shared sortBy-Q / sortOrder-Q / query-Q
    parameter components and referenced them on the 4 list operations.
  • api/generated.go — regenerated via make generate (oapi-codegen v2.5.1).

Tests

  • internal/repository/pagination_test.go (new) — covers the allowlist fallback
    (including an injection-attempt token) and LIKE wildcard/backslash escaping.
  • internal/service/application_test.go — updated mock signatures.

Verification

go build ./..., go vet ./internal/..., and the service / handler / repository
test suites all pass.

Live smoke test (running server, file-based auth, 4 seeded projects)

GET /api/v0.9/projects:

Request Result
(default) inventory, payment-gateway, orders-service, payments-api (createdAt desc)
?sortBy=name&sortOrder=asc Alpha Orders, Beta Inventory, Mango Payment Gateway, Zeta Payments
?sortBy=name&sortOrder=desc reverse of the above
?query=payment payment-gateway, payments-apitotal: 2 (matches handle, not display name)
?query=PAYMENT same 2 results (case-insensitive)
?query=payment&sortBy=name&sortOrder=asc filter + sort compose correctly
?limit=2&offset=0&sortBy=nameoffset=2 stable paging: [orders-service, inventory] then [payment-gateway, payments-api], total: 4

Safety cases:

Request Result
?sortBy=created_at;DROP TABLE projects 200 OK, falls back to default sort, all 4 rows intact — token never reaches SQL
?query=% total: 0% escaped and matched literally, not as a wildcard
?query=zzz-nonexistent clean empty envelope, total: 0

Example envelope (?sortBy=name&sortOrder=asc&limit=1):

{
  "count": 1,
  "list": [
    {
      "id": "orders-service",
      "displayName": "Alpha Orders",
      "description": "orders",
      "organizationId": "default",
      "createdAt": "2026-07-09T10:57:10+05:30",
      "updatedAt": "2026-07-09T10:57:10+05:30"
    }
  ],
  "pagination": { "limit": 1, "offset": 0, "total": 4 }
}

Follow-ups (not in this PR)

The remaining SQL-paginated collections (organizations, subscriptions,
subscription plans, secrets, LLM providers / proxies / templates) can adopt the
same pattern — a few lines per repository method plus the service/handler wiring —
when needed.

…ries

This commit introduces a new pagination mechanism by adding a `parsePagination` function to standardize the handling of `limit` and `offset` query parameters. The pagination logic has been integrated into multiple API handlers, allowing for more efficient data retrieval and response structuring. Additionally, corresponding changes have been made in the repository layer to support paginated queries for APIs, applications, gateways, and subscription plans, enhancing the overall performance and usability of the API platform.
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6e19310e-4e0b-4fa3-9238-f7da20a22165

📥 Commits

Reviewing files that changed from the base of the PR and between f51a820 and b8dc8d0.

📒 Files selected for processing (21)
  • platform-api/internal/handler/organization.go
  • platform-api/internal/handler/pagination.go
  • platform-api/internal/integration/lifecycle_test.go
  • platform-api/internal/pagination/pagination.go
  • platform-api/internal/service/llm_apikey.go
  • platform-api/internal/service/llm_proxy_apikey.go
  • platform-api/internal/service/pagination.go
  • platform-api/resources/openapi.yaml
  • portals/ai-workspace/src/apis/keyManagementApis.ts
  • portals/ai-workspace/src/apis/llmProviderApis.ts
  • portals/ai-workspace/src/apis/llmProxiesApis.ts
  • portals/ai-workspace/src/contexts/KeyManagementContext.tsx
  • portals/ai-workspace/src/pages/appShell/appShellPages/applications/OverviewTabs/APIKeyTab.tsx
  • portals/ai-workspace/src/pages/appShell/appShellPages/applications/OverviewTabs/AssociationsTab.tsx
  • portals/ai-workspace/src/pages/appShell/appShellPages/proxies/LLMProxyOverviewTab.tsx
  • portals/ai-workspace/src/pages/appShell/appShellPages/quickStart/lllmStepBanner/LLLMStepBanner.tsx
  • portals/ai-workspace/src/pages/appShell/appShellPages/serviceProvider/ServiceProviderDeploymentsCard.tsx
  • portals/ai-workspace/src/pages/appShell/appShellPages/serviceProvider/ServiceProviderOverviewTab.tsx
  • portals/ai-workspace/src/utils/pagination.ts
  • portals/ai-workspace/src/utils/types.ts
  • tests/integration-e2e/steps_devportal_lifecycle_test.go
✅ Files skipped from review due to trivial changes (3)
  • platform-api/internal/pagination/pagination.go
  • portals/ai-workspace/src/utils/pagination.ts
  • platform-api/internal/integration/lifecycle_test.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • platform-api/internal/handler/organization.go
  • platform-api/internal/handler/pagination.go
  • platform-api/internal/service/llm_proxy_apikey.go
  • platform-api/internal/service/llm_apikey.go
  • platform-api/resources/openapi.yaml

📝 Walkthrough

Walkthrough

This PR replaces the generated error payload with a structured error schema and standardizes list pagination across platform-api and ai-workspace. It adds shared pagination helpers, updates OpenAPI and generated contracts, rewires repositories/services/handlers, and changes client code to consume list plus pagination fields.

Changes

Standardized Error Schema

Layer / File(s) Summary
Error/ErrorStatus/FieldError model
platform-api/api/generated.go
Replaces the prior error payload with string codes, message/status fields, structured details, field errors, and tracking IDs.

Pagination Standardization

Public contracts and generated models

Layer / File(s) Summary
List response and query contracts
platform-api/api/generated.go, platform-api/resources/openapi.yaml, platform-api/internal/dto/secret.go
Updates list response schemas and query parameter contracts to use list/count/pagination envelopes and typed pagination/sort/filter parameters.

Pagination wiring and consumers

Layer / File(s) Summary
Pagination helpers
platform-api/internal/repository/pagination.go, platform-api/internal/service/pagination.go, platform-api/internal/handler/pagination.go, platform-api/internal/repository/pagination_test.go
Adds shared pagination, sorting, and search helpers plus in-memory windowing and helper tests.
Repository queries and interfaces
platform-api/internal/repository/api.go, application.go, gateway.go, project.go, subscription_plan_repository.go, interfaces.go
Adds and updates repository contracts for paginated listing and counting with search and sort support.
Service pagination and response shaping
platform-api/internal/service/api.go, apikey_user.go, application.go, gateway.go, llm_apikey.go, llm_proxy_apikey.go, project.go, secret_service.go, subscription_plan_service.go, plus tests
Updates service methods to accept pagination inputs, compute totals, and return paginated response envelopes.
HTTP handler updates
platform-api/internal/handler/api.go, api_deployment.go, apikey_user.go, application.go, gateway.go, llm*.go, mcp*.go, organization.go, project.go, secret.go, subscription_handler.go, subscription_plan_handler.go, plus integration tests
Replaces inline query parsing with shared helpers and forwards pagination options into services.
Workspace client pagination consumers
portals/ai-workspace/src/apis/*, contexts/*, pages/*, utils/*
Adds paginated API fetching utilities and updates UI state consumers to read list and pagination fields.

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

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Handler
  participant Service
  participant Repository

  Client->>Handler: GET /applications?limit=&offset=&sortBy=&query=
  Handler->>Handler: parseListOptions(r)
  Handler->>Service: GetApplicationsByOrganization(orgID, opts)
  Service->>Repository: CountApplicationsByProjectID(opts.Search)
  Repository-->>Service: total
  Service->>Repository: GetApplicationsByProjectIDPaginated(opts)
  Repository-->>Service: pagedApps
  Service-->>Handler: ApplicationListResponse{List, Count, Pagination}
  Handler-->>Client: JSON response
Loading

Possibly related PRs

  • wso2/api-platform#2507: Introduces the error-schema refactor that aligns with the new standardized Error/ErrorStatus/FieldError payload in this PR.

Suggested reviewers: RakhithaRR, Tharsanan1, VirajSalaka, renuka-fernando, tharindu1st

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is detailed, but it does not follow the required template and omits several mandated sections. Reformat the PR body to the template and add the missing Purpose, Goals, User stories, Documentation, Automation tests, Security checks, Samples, Related PRs, and Test environment sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding pagination support across handlers and repositories.
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

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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: 2

Caution

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

⚠️ Outside diff range comments (1)
platform-api/internal/handler/subscription_handler.go (1)

206-213: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Update the remaining devportal list consumer to list.
tests/integration-e2e/steps_devportal_lifecycle_test.go:163-166 still unmarshals {"subscriptions": ...} from GET /subscriptions; switch that fixture to the new list envelope so it matches the API response.

🤖 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 `@platform-api/internal/handler/subscription_handler.go` around lines 206 -
213, The remaining devportal list consumer still expects the old subscriptions
envelope, so update the integration fixture to match the new list response
shape. In tests/integration-e2e/steps_devportal_lifecycle_test.go, adjust the
GET /subscriptions mock/unmarshal payload to use the list field instead of
subscriptions so it aligns with SubscriptionHandler’s list response.
🧹 Nitpick comments (5)
platform-api/internal/handler/subscription_plan_handler.go (1)

257-265: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Use the generated api.SubscriptionPlanListResponse instead of an ad-hoc map.

Other rewritten handlers in this cohort (ListOrganizations, ListAPIs, ListProjects) return the typed generated response struct, but this builds a raw map[string]any{"list": ..., "count": ..., "pagination": ...}. The generated SubscriptionPlanListResponse (in platform-api/api/generated.go, lines 2419-2426) already models Count/List/Pagination with the same field names — using it here keeps the response type-checked against the OpenAPI contract instead of relying on the map keys staying in sync manually.

♻️ Suggested refactor
-	httputil.WriteJSON(w, http.StatusOK, map[string]any{
-		"list":  items,
-		"count": len(items),
-		"pagination": api.Pagination{
-			Total:  total,
-			Offset: offset,
-			Limit:  limit,
-		},
-	})
+	httputil.WriteJSON(w, http.StatusOK, api.SubscriptionPlanListResponse{
+		List:  items,
+		Count: len(items),
+		Pagination: api.Pagination{
+			Total:  total,
+			Offset: offset,
+			Limit:  limit,
+		},
+	})
🤖 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 `@platform-api/internal/handler/subscription_plan_handler.go` around lines 257
- 265, The subscription plan list handler is returning an ad-hoc map instead of
the generated typed response, so update the ListSubscriptionPlans flow in
subscription_plan_handler to use api.SubscriptionPlanListResponse like
ListOrganizations/ListAPIs/ListProjects do. Replace the raw map in the JSON
write path with the generated response struct, populating Count, List, and
Pagination from the existing items, total, offset, and limit values so the
response stays type-checked against the OpenAPI contract.
platform-api/internal/service/llm_apikey.go (1)

65-120: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated in-memory pagination logic vs. llm_proxy_apikey.go.

ListLLMProviderAPIKeys and ListLLMProxyAPIKeys (in platform-api/internal/service/llm_proxy_apikey.go) are near-identical: fetch keys, filter by CreatedBy == userID, map to api.APIKeyItem, then total := len(items); page := paginateSlice(...). Consider extracting a shared helper (e.g. buildPaginatedAPIKeyItems(keys []*model.APIKey, userID string, identity *IdentityService, limit, offset int) ([]api.APIKeyItem, int)) to avoid maintaining two copies of this logic.

🤖 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 `@platform-api/internal/service/llm_apikey.go` around lines 65 - 120,
`ListLLMProviderAPIKeys` duplicates the same in-memory filtering, identity
resolution, item mapping, and pagination flow used by `ListLLMProxyAPIKeys`, so
extract that shared logic into a common helper. Move the `CreatedBy == userID`
filter, `ResolveIdentityField`, `api.APIKeyItem` construction, and
`paginateSlice`/total calculation into a reusable function (for example, a
helper that takes the fetched keys, `userID`, and the identity service). Then
have both service methods call the helper and keep only the
provider/proxy-specific repository fetch and error handling in each method.
platform-api/api/generated.go (1)

432-442: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Bare enum constant names risk future collisions; inconsistent with sibling enums.

ListRESTAPIsParamsSortBy/ListRESTAPIsParamsSortOrder constants are generated as unprefixed CreatedAt, Name, Asc, Desc, while the equivalent enums for Applications/Gateways/Projects (lines 359-382, 420-431) are consistently prefixed (ListApplicationsParamsSortByCreatedAt, etc.). oapi-codegen normally prefixes enum constants with their type name to avoid collisions, only emitting bare names when an extension like x-enum-varnames/x-enumNames explicitly overrides them. This is likely a spec inconsistency in openapi.yaml for the ListRESTAPIs sortBy/sortOrder parameters. Bare top-level identifiers like Name, Asc, Desc in a package this large are a latent naming-collision risk for future additions.

🔧 Likely spec fix (in openapi.yaml, not shown in this batch)
- x-enum-varnames: [CreatedAt, Name]
+ x-enum-varnames: [ListRESTAPIsParamsSortByCreatedAt, ListRESTAPIsParamsSortByName]
🤖 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 `@platform-api/api/generated.go` around lines 432 - 442, The
`ListRESTAPIsParamsSortBy` and `ListRESTAPIsParamsSortOrder` enum constants are
inconsistently generated as bare names (`CreatedAt`, `Name`, `Asc`, `Desc`)
instead of the prefixed style used by sibling enums. Update the OpenAPI spec for
the `ListRESTAPIs` sort parameters so oapi-codegen emits prefixed constants
matching `ListApplicationsParamsSortBy...` and related enums, avoiding top-level
name collisions. Locate the affected generation by `ListRESTAPIsParamsSortBy`
and `ListRESTAPIsParamsSortOrder` in the generated API definitions and align
their enum var names with the existing prefixed convention.
platform-api/internal/handler/pagination.go (1)

93-108: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate generic pagination-window helper.

pageWindow here is functionally identical to paginateSlice in platform-api/internal/service/pagination.go (same clamping logic, same signature shape). Consider exporting one implementation (e.g. from a shared internal pagination package) and having both handler and service import it, to avoid the two copies drifting apart under future edits.

🤖 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 `@platform-api/internal/handler/pagination.go` around lines 93 - 108, The
generic pagination helper is duplicated between pageWindow in the handler and
paginateSlice in the service, so consolidate the shared clamping/slicing logic
into one reusable internal helper and have both call it. Move the implementation
to a common internal pagination location (or otherwise reuse one symbol), then
update the handler’s pageWindow and the service’s paginateSlice references to
delegate to that single function so the behavior cannot drift.
platform-api/internal/handler/gateway.go (1)

507-522: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider using a typed response struct instead of map[string]any.

Other list handlers in this PR use generated typed structs (GatewayListResponse, GatewayTokenListResponse, etc.) with proper JSON tags. The map[string]any approach here works but is less type-safe — a key typo would silently break the JSON contract. If no generated CustomPolicyListResponse type exists, consider defining a local DTO struct to match the standardized envelope.

🤖 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 `@platform-api/internal/handler/gateway.go` around lines 507 - 522, The custom
policies list handler currently returns a map, which is less type-safe than the
other list handlers in gateway.go. Update the response in the ListCustomPolicies
path to use a typed DTO/response struct (prefer a generated
CustomPolicyListResponse if available, otherwise define a local struct) and keep
the same fields and JSON tags as the existing count/list/pagination envelope.
Use the existing httputil.WriteJSON call site and the ListCustomPolicies flow to
locate and replace the map-based response.
🤖 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 `@platform-api/internal/handler/pagination.go`:
- Around line 43-65: The `parsePagination` limit handling is asymmetric: values
below `minPageLimit` fall back to `defaultPageLimit`, but values above
`maxPageLimit` are clamped instead of using the same fallback behavior. Update
`parsePagination` in the pagination handler so out-of-range `limit` values are
handled consistently on both sides, using one clear rule for invalid limits
rather than mixing defaulting and clamping. Keep the existing `offset` parsing
unchanged.

In `@platform-api/resources/openapi.yaml`:
- Around line 8633-8644: The shared limit-Q query parameter now changes the GET
/secrets default page size from 25 to 20, so verify whether this behavioral
change is intended. Check the GET /secrets operation’s parameter reference and
the limit-Q component in openapi.yaml, then either restore the previous default
to 25 or update the API definition and related consumers/docs if 20 is the new
expected default.

---

Outside diff comments:
In `@platform-api/internal/handler/subscription_handler.go`:
- Around line 206-213: The remaining devportal list consumer still expects the
old subscriptions envelope, so update the integration fixture to match the new
list response shape. In tests/integration-e2e/steps_devportal_lifecycle_test.go,
adjust the GET /subscriptions mock/unmarshal payload to use the list field
instead of subscriptions so it aligns with SubscriptionHandler’s list response.

---

Nitpick comments:
In `@platform-api/api/generated.go`:
- Around line 432-442: The `ListRESTAPIsParamsSortBy` and
`ListRESTAPIsParamsSortOrder` enum constants are inconsistently generated as
bare names (`CreatedAt`, `Name`, `Asc`, `Desc`) instead of the prefixed style
used by sibling enums. Update the OpenAPI spec for the `ListRESTAPIs` sort
parameters so oapi-codegen emits prefixed constants matching
`ListApplicationsParamsSortBy...` and related enums, avoiding top-level name
collisions. Locate the affected generation by `ListRESTAPIsParamsSortBy` and
`ListRESTAPIsParamsSortOrder` in the generated API definitions and align their
enum var names with the existing prefixed convention.

In `@platform-api/internal/handler/gateway.go`:
- Around line 507-522: The custom policies list handler currently returns a map,
which is less type-safe than the other list handlers in gateway.go. Update the
response in the ListCustomPolicies path to use a typed DTO/response struct
(prefer a generated CustomPolicyListResponse if available, otherwise define a
local struct) and keep the same fields and JSON tags as the existing
count/list/pagination envelope. Use the existing httputil.WriteJSON call site
and the ListCustomPolicies flow to locate and replace the map-based response.

In `@platform-api/internal/handler/pagination.go`:
- Around line 93-108: The generic pagination helper is duplicated between
pageWindow in the handler and paginateSlice in the service, so consolidate the
shared clamping/slicing logic into one reusable internal helper and have both
call it. Move the implementation to a common internal pagination location (or
otherwise reuse one symbol), then update the handler’s pageWindow and the
service’s paginateSlice references to delegate to that single function so the
behavior cannot drift.

In `@platform-api/internal/handler/subscription_plan_handler.go`:
- Around line 257-265: The subscription plan list handler is returning an ad-hoc
map instead of the generated typed response, so update the ListSubscriptionPlans
flow in subscription_plan_handler to use api.SubscriptionPlanListResponse like
ListOrganizations/ListAPIs/ListProjects do. Replace the raw map in the JSON
write path with the generated response struct, populating Count, List, and
Pagination from the existing items, total, offset, and limit values so the
response stays type-checked against the OpenAPI contract.

In `@platform-api/internal/service/llm_apikey.go`:
- Around line 65-120: `ListLLMProviderAPIKeys` duplicates the same in-memory
filtering, identity resolution, item mapping, and pagination flow used by
`ListLLMProxyAPIKeys`, so extract that shared logic into a common helper. Move
the `CreatedBy == userID` filter, `ResolveIdentityField`, `api.APIKeyItem`
construction, and `paginateSlice`/total calculation into a reusable function
(for example, a helper that takes the fetched keys, `userID`, and the identity
service). Then have both service methods call the helper and keep only the
provider/proxy-specific repository fetch and error handling in each method.
🪄 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

Run ID: 1abee8ef-5333-497f-9384-eb7ba4a5b855

📥 Commits

Reviewing files that changed from the base of the PR and between 737bef5 and f51a820.

📒 Files selected for processing (41)
  • platform-api/api/generated.go
  • platform-api/internal/dto/secret.go
  • platform-api/internal/handler/api.go
  • platform-api/internal/handler/api_deployment.go
  • platform-api/internal/handler/apikey_user.go
  • platform-api/internal/handler/application.go
  • platform-api/internal/handler/gateway.go
  • platform-api/internal/handler/llm.go
  • platform-api/internal/handler/llm_apikey.go
  • platform-api/internal/handler/llm_deployment.go
  • platform-api/internal/handler/llm_proxy_apikey.go
  • platform-api/internal/handler/mcp.go
  • platform-api/internal/handler/mcp_deployment.go
  • platform-api/internal/handler/organization.go
  • platform-api/internal/handler/pagination.go
  • platform-api/internal/handler/project.go
  • platform-api/internal/handler/secret.go
  • platform-api/internal/handler/secret_integration_test.go
  • platform-api/internal/handler/subscription_handler.go
  • platform-api/internal/handler/subscription_plan_handler.go
  • platform-api/internal/repository/api.go
  • platform-api/internal/repository/application.go
  • platform-api/internal/repository/gateway.go
  • platform-api/internal/repository/interfaces.go
  • platform-api/internal/repository/pagination.go
  • platform-api/internal/repository/pagination_test.go
  • platform-api/internal/repository/project.go
  • platform-api/internal/repository/subscription_plan_repository.go
  • platform-api/internal/service/api.go
  • platform-api/internal/service/apikey_user.go
  • platform-api/internal/service/application.go
  • platform-api/internal/service/application_test.go
  • platform-api/internal/service/custom_policy_test.go
  • platform-api/internal/service/gateway.go
  • platform-api/internal/service/llm_apikey.go
  • platform-api/internal/service/llm_proxy_apikey.go
  • platform-api/internal/service/pagination.go
  • platform-api/internal/service/project.go
  • platform-api/internal/service/secret_service.go
  • platform-api/internal/service/subscription_plan_service.go
  • platform-api/resources/openapi.yaml

Comment thread platform-api/internal/handler/pagination.go
Comment thread platform-api/resources/openapi.yaml
This commit updates the API key retrieval functions across multiple modules to utilize a new pagination mechanism. The `fetchAllPages` utility is introduced to streamline the fetching of paginated data, ensuring that all pages of API keys are collected efficiently. Additionally, the response structure has been modified to use `list` instead of `items`, and pagination details are now included in the responses, enhancing the overall data handling and user experience.
malinthaprasan
malinthaprasan previously approved these changes Jul 9, 2026
This commit refines the pagination logic by introducing a new `pagination` package that centralizes the windowing functionality. The `parsePagination` function has been updated to clamp out-of-range values, ensuring robust handling of `limit` and `offset` parameters. Additionally, various service methods have been modified to utilize this new pagination mechanism, enhancing code clarity and maintainability. The response structures in API key retrieval functions have also been updated to align with the new pagination approach.
@Thushani-Jayasekera Thushani-Jayasekera merged commit e33cf15 into wso2:main Jul 9, 2026
12 of 13 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

Development

Successfully merging this pull request may close these issues.

2 participants