dotCMS / dotCMS/core

[Task] Users API: `GET /v1/users/filter` should be able to return each user's direct roles

Open
#37,233 1 comment 0 reactions 1 assignee View on GitHub

@hassandotcms is already working on this.

Since Aug 26, 2026.

Team : Modernization Type : Task
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Context

The Angular Users portlet list (#36930 arc) shows each user's roles beyond the default access roles in a column. GET /api/v1/users/filter returns no role data — items are user.toMap() plus an optional requestPassword flag (UserPaginator#addRequestPasswordAttr).

The FE therefore fans out one GET /api/v1/roles/users/{userId} per row after every list load (dot-users-list.store.ts:107-124): 40 extra requests per page at the default per_page=40, each paying REST auth init. That endpoint also returns explicit and implicit roles (loadRolesForUser(userId) defaults includeImplicitRoles=true), so the FE filters access roles and the personal role out client-side.

Legacy reference: the Dojo Users portlet list grid had no roles column; its Roles tab listed direct memberships only (UserAjax#getUserRolesloadRolesForUser(userId, false)).

Requirements

  • A single GET /api/v1/users/filter request can return, per user, the user's directly assigned roles — inherited/implicit roles excluded (legacy parity with the Roles tab, and consistent with the direct-membership semantics of the /v1/roles/{roleid}/users* endpoints from #37077 and #37070; inherited roles cannot be removed from a user, so listing them alongside a Remove action would mislead)
  • Each role entry must carry at least id, name, and roleKey. id is required because roles created in the Roles portlet may have no key (#37209)
  • The behavior is opt-in: callers that do not ask for roles get a byte-identical response to today. UserPaginator is shared; no extra payload or DB work for callers that don't need roles
  • All existing filter parameters (query, roleKey, paging, sorting, includeAnonymous, includeDefault, assetInode/permission) keep working unchanged in combination
  • No change to authorization of the endpoint
  • OpenAPI documents the new option and the per-item role shape; regenerated openapi.yaml committed

Acceptance Criteria

  • Roles returned per user when requested; absent when not requested (existing payload unchanged)
  • Only direct memberships are listed; a role held via inheritance (child of a held role, or the implicit CMS Anonymous role) is not
  • Keyless roles appear with id and name, roleKey null/absent
  • Integration tests: opt-in on/off, direct-vs-inherited, keyless role, combined with roleKey filter and paging
  • Existing UserResourceIntegrationTest and Postman UserResource collection still green
  • OpenAPI updated and regenerated

Out of scope

  • Changing GET /v1/roles/users/{userIdOrEmail}
  • Inherited/implicit role expansion in the list (could be a later opt-in if a use case appears)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.