Skip to content

[Customer Entity] Add filters, sort, and ServiceNow support to POST /users/search - #973

Merged
Rashmika998 merged 9 commits into
wso2-open-operations:v2from
cloby99:task/entity-service
Jun 29, 2026
Merged

[Customer Entity] Add filters, sort, and ServiceNow support to POST /users/search#973
Rashmika998 merged 9 commits into
wso2-open-operations:v2from
cloby99:task/entity-service

Conversation

@cloby99

@cloby99 cloby99 commented Jun 29, 2026

Copy link
Copy Markdown
Member

Summary

  • Restructures POST /users/search request from a flat searchQuery field to a nested filters object (searchQuery, roles, userNames, emails, active) with an optional sortBy (field, order)
  • Adds ServiceNow data source support: when DataSource == ServiceNow, the endpoint is backed by Choreo /users/search and returns SearchSNUsersResponse with SNUser items (name, timeZone, active, roles) instead of the postgres User shape
  • Postgres data source continues to work as before, with additional userNames and emails filter support added to the repository layer

Changes

Layer Change
Domain New UserRole, UserSortField, UserSortOrder types; SearchUsersFilters, UserSortBy; SNUser, SearchSNUsersResponse
Service normalizeUserPagination (default 10, max 50); SNUserService interface; snUserService backed by Choreo
Repository Postgres SearchUsers extended with userNames and emails filters
Handler SNUserHandler added alongside existing postgres UserHandler
Routes POST /users/search conditionally routes to SN or postgres handler based on DataSource
OpenAPI SearchUsersRequest, UserPagination, SearchUsersFilters, UserSortBy, SNUser, SearchSNUsersResponse schemas added/updated

Test plan

  • POST /users/search with postgres data source returns existing User shape with firstName, lastName, userType
  • POST /users/search with ServiceNow data source returns SNUser shape with name, timeZone, active, roles
  • roles filter with an invalid value returns 400
  • sortBy.field with an invalid value returns 400
  • pagination.limit > 50 returns 400
  • userNames and emails filters correctly narrow postgres results
  • Missing x-user-id-token header on SN data source returns 401

Summary by CodeRabbit

  • New Features

    • Expanded user search to support filters, sorting, and updated pagination defaults.
    • Added support for ServiceNow-backed user search results alongside the existing user list.
  • Bug Fixes

    • Search requests now handle additional criteria like roles, names, emails, and active status more consistently.
    • Pagination limits and defaults were tightened for safer, more predictable results.

cloby99 added 8 commits June 29, 2026 21:19
…eld, UserSortOrder, SearchUsersFilters, UserSortBy, SNUser, SearchSNUsersResponse; restructure SearchUsersRequest to use nested filters and sortBy; update Pagination docs (default 10, max 50)
…d switch SearchUsers to use req.Filters.SearchQuery
…and emails; update searchQuery reference to req.Filters.SearchQuery
…th role and sortBy validation, sysid↔UUID conversion, and nil-safe roles slice
…ource is ServiceNow, postgres handler otherwise
…archUsersFilters (searchQuery, roles, userNames, emails, active), UserSortBy, UserPagination (default 10, max 50), SNUser schema, and SearchSNUsersResponse; replace flat searchQuery with nested filters structure
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@cloby99, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dd35460e-2bec-4cfe-a661-07a17e51c53f

📥 Commits

Reviewing files that changed from the base of the PR and between 27a6925 and 1d7435b.

📒 Files selected for processing (3)
  • entity-service/internal/service/sn_user_service.go
  • entity-service/internal/service/user_service.go
  • entity-service/openapi.yaml
📝 Walkthrough

Walkthrough

Expands the POST /users/search endpoint to support richer filter/sort contracts (UserRole, SearchUsersFilters, UserSortBy) and adds a ServiceNow-backed search path (SNUserHandler, snUserService) alongside the existing Postgres path. The Postgres repository gains UserNames/Emails filter predicates. Pagination limits are tightened to 10/50. The OpenAPI spec is updated to reflect the dual-source response shape.

Changes

ServiceNow User Search Feature

Layer / File(s) Summary
Domain contracts: enums, filters, sort, SN types
entity-service/internal/domain/entity.go
Adds UserRole, UserSortField, UserSortOrder enums, SearchUsersFilters and UserSortBy structs, reshapes SearchUsersRequest to {pagination, filters, sortBy}, and introduces SNUser and SearchSNUsersResponse types.
Service interfaces and pagination normalization
entity-service/internal/service/interfaces.go, entity-service/internal/service/user_service.go
Adds SNUserService interface returning SearchSNUsersResponse; introduces defaultUserLimit/maxUserLimit constants and normalizeUserPagination; updates userService.SearchUsers to use new pagination and Filters.SearchQuery.
ServiceNow user service implementation
entity-service/internal/service/sn_user_service.go
Implements snUserService with Choreo payload structs, role/sort allowlists, NewServiceNowUserService constructor, and SearchUsers covering validation, auth-token extraction, Choreo HTTP call, JSON mapping to domain SNUser, and SearchSNUsersResponse assembly.
Postgres repository filter predicates
entity-service/internal/repository/user_repo.go
Switches free-text source to req.Filters.SearchQuery; adds ANY(ARRAY[...]) predicates for UserNames and Emails lists in the dynamic SQL WHERE clause.
HTTP handlers and route wiring
entity-service/internal/handler/user_handler.go, entity-service/internal/server/routes.go
Adds SNUserHandler with SearchUsers HTTP handler; conditionally routes POST /users/search to SNUserHandler when cfg.DataSource == ServiceNow, otherwise falls back to userHandler.
OpenAPI spec: dual-source contracts
entity-service/openapi.yaml
Updates /users/search description and 200 response to oneOf[SearchUsersResponse, SearchSNUsersResponse]; adds UserPagination, SearchUsersFilters, UserSortBy, SNUser, and SearchSNUsersResponse component schemas.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • wso2-open-operations/cs-tools#729: Implements the original POST /users/search flow with SearchUsersRequest/domain model and handler/service/repository logic that this PR extends with filters, sorting, and ServiceNow support.

Suggested labels

Type/Improvement, Area/Backend, Entity Service

Suggested reviewers

  • shayanmalinda
  • dilshanfardil

🐇 A rabbit hops through routes and repos,
Sorting users by name as the query flows,
ServiceNow or Postgres, it checks the config key,
Filters for roles, emails — all in the WHERE array,
The spec says oneOf, and the bunny says "hooray!" 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is relevant but largely incomplete against the required template, missing most mandated sections like Purpose, Goals, Approach, and Release note. Fill in the required template sections, especially Purpose, Goals, Approach, Release note, Documentation, Testing, and other applicable fields.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: new filters, sorting, and ServiceNow support for POST /users/search.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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: 5

🤖 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 `@entity-service/internal/service/interfaces.go`:
- Around line 37-43: Remove the redundant SNUserService interface from
interfaces.go, since the same interface is already declared in SNUserService in
sn_user_service.go and both live in package service. Keep only one definition of
SNUserService (prefer the existing one in sn_user_service.go) and update any
references in the service package to use that single interface so the package
compiles without redeclaration.

In `@entity-service/internal/service/sn_user_service.go`:
- Around line 114-138: The SearchSNUsers flow in sn_user_service.go accepts
sortBy.order even when sortBy.field is empty, but the snSortBy builder only uses
sorting when a field is provided, so the order becomes a no-op. Update the
validation in the SearchSNUsers method to reject any non-empty req.SortBy.Order
when req.SortBy.Field is empty, alongside the existing validUserSortField and
validUserSortOrder checks. Keep the behavior consistent with the snSortBy
construction so only meaningful field+order combinations are accepted.

In `@entity-service/openapi.yaml`:
- Around line 42-44: The `oneOf` in the search response is ambiguous because
`SearchUsersResponse` and `SearchSNUsersResponse` can both validate the same
payload. Update the referenced response schemas, especially the
`SearchUsersResponse`/`SearchSNUsersResponse` components and their item schemas
(`User` and `SNUser`), so each branch has distinct required fields or a
discriminator-like distinction that prevents overlap. Apply the same
disambiguation to the other `oneOf` block referenced in the spec so
`/users/search` and related responses validate unambiguously for generated
clients.
- Around line 24-28: The user search contract currently advertises
filters/sorting that the Postgres implementation does not honor, so update the
OpenAPI schema and the Postgres handling together. In the user search flow (the
shared request schema plus the Postgres path used by the search endpoint),
either implement support for roles, active, and sortBy in the Postgres query
logic or explicitly reject them there; if they remain ServiceNow-only, remove or
clearly scope them in the contract to match the actual behavior. Keep the
ServiceNow and Postgres request/response models aligned with the endpoint
documentation and the backend code that builds the Postgres query.
- Around line 1354-1369: The array filters for roles, userNames, and emails in
the OpenAPI schema are unbounded, which allows oversized request lists to flow
into SQL and external payload builders. Add explicit maxItems limits to these
schema fields in the OpenAPI definition and mirror the same bounds in the
service-side validation logic that handles these filters, using the existing
filter definitions for roles, userNames, and emails as the places to update.
🪄 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: da8d4ce0-9c29-4098-a1a1-9598106eca59

📥 Commits

Reviewing files that changed from the base of the PR and between 6025b9b and 27a6925.

📒 Files selected for processing (8)
  • entity-service/internal/domain/entity.go
  • entity-service/internal/handler/user_handler.go
  • entity-service/internal/repository/user_repo.go
  • entity-service/internal/server/routes.go
  • entity-service/internal/service/interfaces.go
  • entity-service/internal/service/sn_user_service.go
  • entity-service/internal/service/user_service.go
  • entity-service/openapi.yaml

Comment thread entity-service/internal/service/interfaces.go
Comment thread entity-service/internal/service/sn_user_service.go
Comment thread entity-service/openapi.yaml
Comment thread entity-service/openapi.yaml
Comment thread entity-service/openapi.yaml
…nly filters in postgres, enforce sortBy.order requires field, add maxItems bounds, and disambiguate oneOf response schemas
@Rashmika998
Rashmika998 merged commit 6f17364 into wso2-open-operations:v2 Jun 29, 2026
1 check passed
Comment thread entity-service/openapi.yaml
Comment thread entity-service/internal/domain/entity.go
Comment thread entity-service/internal/service/user_service.go
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.

3 participants