refactor(FR-3016): migrate super-admin user list to adminUsersV2 query#7666
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has required the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
Coverage Report for react-coverage (./react)
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||
629154c to
6d9cf71
Compare
There was a problem hiding this comment.
Pull request overview
This PR refactors the super-admin “Users / Credentials” admin area by switching the user list data source from the legacy user_nodes query to the newer adminUsersV2 (UserV2) GraphQL query, updating routing and the related list components accordingly.
Changes:
- Replaces the
/credentialroute page component withAdminUsersPage(Users / Credentials tabs). - Migrates the admin user list component to
AdminUserManagementQuery(adminUsersV2) andBAIUserV2Nodes. - Updates purge/update user modals to accept a plain
{id, email}list instead of Relay fragments (removing the old fragments).
Reviewed changes
Copilot reviewed 10 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| react/src/routes.tsx | Switches /credential route to render AdminUsersPage. |
| react/src/pages/AdminUsersPage.tsx | New/updated page wrapper that renders the migrated admin user list and credential list by tab. |
| react/src/components/AdminUserManagement.tsx | Core migration to adminUsersV2 (v2 filter/order/pagination + BAIUserV2Nodes), and rewires purge/update modal inputs. |
| react/src/components/AdminUserCredentialList.tsx | Renames query/mutations to Admin* variants (keypair list behavior remains v1). |
| react/src/components/UpdateUsersModal.tsx | Changes modal input from Relay fragment to users: {id,email}[]. |
| react/src/components/PurgeUsersModal.tsx | Changes modal input from Relay fragment to users: {id,email}[]. |
| react/src/generated/UserManagementQuery.graphql.ts | Removes legacy generated query artifact (v1 user_nodes). |
| react/src/generated/UpdateUsersModalFragment.graphql.ts | Removes legacy generated fragment (no longer used). |
| react/src/generated/PurgeUsersModalFragment.graphql.ts | Removes legacy generated fragment (no longer used). |
| react/src/generated/AdminUserManagementQuery.graphql.ts | Adds generated artifact for AdminUserManagementQuery (adminUsersV2). |
| react/src/generated/AdminUserManagementModifyMutation.graphql.ts | Updates generated mutation artifact to Admin* naming. |
| react/src/generated/AdminUserCredentialListQuery.graphql.ts | Updates generated query artifact to Admin* naming. |
| react/src/generated/AdminUserCredentialListModifyMutation.graphql.ts | Updates generated mutation artifact to Admin* naming. |
| react/src/generated/AdminUserCredentialListDeleteMutation.graphql.ts | Updates generated mutation artifact to Admin* naming. |
Files not reviewed (4)
- react/src/generated/AdminUserManagementQuery.graphql.ts: Language not supported
- react/src/generated/PurgeUsersModalFragment.graphql.ts: Language not supported
- react/src/generated/UpdateUsersModalFragment.graphql.ts: Language not supported
- react/src/generated/UserManagementQuery.graphql.ts: Language not supported
Comments suppressed due to low confidence (2)
react/src/components/AdminUserManagement.tsx:430
- The bulk-create user action is now always exposed in the UI. This used to be feature-gated via the manager capability
bulk-create-user; without that guard, older managers will show the menu but the bulk-create mutation will fail at runtime.
react/src/components/AdminUserManagement.tsx:370 - Changing the GraphQL property filter can make
selectedUserListrefer to rows that are no longer visible/match the current query, but selection is not cleared here (unlike status/order/pagination changes). Clearing selection on filter change avoids applying Update/Purge actions to stale selections.
6d9cf71 to
3513119
Compare
|
Also addressed the two low-confidence suggestions from the review:
|
Merge activity
|
#7666) Resolves #7664 (FR-3016) ## Summary Migrate the **super-admin user list** (Users tab of the Users & Credentials page) from the legacy `user_nodes` (v1) query to **`adminUsersV2`** (`UserV2Connection`). Per the issue scope, only the list/table is migrated to v2; all modals keep their existing (v1) implementation. - **List query**: `user_nodes` → `adminUsersV2`; component `BAIUserNodes` → `BAIUserV2Nodes`. - **Filter**: `BAIPropertyFilter` (string DSL) → `BAIGraphQLPropertyFilter` (structured `UserV2Filter`), reusing the `ProjectAdminUsersPage` pattern. Only the fields `UserV2Filter` currently supports are exposed: **email, ID (uuid), username, role, project name, Active/Inactive status**. - These v1 filters have **no equivalent in `UserV2Filter`** and were dropped: `full_name`, `resource_policy`, `description`, `status_info`, `need_password_change`, `totp_activated`, `sudo_session_enabled`. They need a backend `UserV2Filter` extension (separate follow-up). - **Sorting**: `convertToOrderBy` + `availableUserV2SorterValues` (v2 `UserV2OrderField`). - **Modals (kept on v1)**: `PurgeUsersModal` / `UpdateUsersModal` now take a plain `{ id, email }[]` `users` prop instead of a `UserNode` GraphQL fragment (they only ever used id/email); Info/Setting modals already key off `userEmail`. No modal mutation was changed. Follow-up to move these modals onto a v2 `UserV2` fragment is tracked in **FR-3019**. - **Capability guards preserved**: the bulk-create-user menu stays gated behind `bailClient.supports('bulk-create-user')`; selection is cleared on filter change as well as on status/order/pagination changes. - All displayed columns remain covered by `UserV2` (incl. UID/GID via `container.*`, `needPasswordChange` via `status.*`). ## Renames (align with `ProjectAdminUsersPage`) - `UserCredentialsPage` → `AdminUsersPage` (page) - `UserManagement` → `AdminUserManagement` (Users tab content) - `UserCredentialList` → `AdminUserCredentialList` Relay query/mutation names and `routes.tsx` import updated accordingly. ## Testing **A ready-to-test backend is already running at `http://10.122.10.117:8090`** with the RBAC schema fix applied. Point the WebUI's API endpoint there and you can test this PR **immediately — no local changes required.** Background: on a *stock* 26.4.3 core, the user list can't even load because of a separate RBAC filter-format mismatch (the `myRoles` query sends `entityType` as a Filter object, but 26.4.3 expects a bare enum). That root cause is tracked in **FR-3017** (#7665) and is intentionally **not** part of this PR. The server above already has the fix applied — the steps below are only needed if you want to point at a *different* 26.4.3 backend that doesn't. <details> <summary>Manual local workaround for an unpatched 26.4.3 backend</summary> Apply these two local edits **without committing them**: 1. `react/src/hooks/useCurrentUserProjectRoles.ts` — myRoles filter: ```diff - filter: { permission: { entityType: { equals: PROJECT_ADMIN_PAGE } } } + filter: { permission: { entityType: PROJECT_ADMIN_PAGE } } ``` 2. `data/schema.graphql` — inside `input PermissionNestedFilter`: ```diff - entityType: RBACElementTypeFilter = null + entityType: RBACElementType = null ``` 3. Run `pnpm relay` (or let the dev watcher recompile), then refresh the dev server. These make `myRoles` send `entityType` as a direct enum (accepted by 26.4.3). They are incompatible with the latest backend's Filter form, so they must not be committed. </details> ## Verification `bash scripts/verify.sh`: Lint / Format / TypeScript **PASS**; Relay artifacts regenerated and committed. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
3513119 to
c30de63
Compare
…st (#7685) Resolves #7683 (FR-3024) ## Summary Expose the newly added `adminUsersV2` (`UserV2Filter`) filters in the super-admin user list's `BAIGraphQLPropertyFilter`. The list migrated to `adminUsersV2` in #7666 (merged) but only exposed 5 filters (email / ID / username / project / role). Backend BA-6247 (lablup/backend.ai#11878) and BA-6249 (lablup/backend.ai#11879) added 10 more filter fields to the v2 schema. These v2 filters are gated behind a capability flag — older managers keep showing just the 5 base filters. ### Added filters (gated, shown only when supported) | Type | Fields | | --- | --- | | String | `fullName`, `description`, `statusInfo`, `resourcePolicy` | | Boolean | `needPasswordChange`, `totpActivated`, `sudoSessionEnabled` | | Integer | `containerUid`, `containerMainGid` | | Integer array | `containerGids` (single-GID membership via `contains`) | ### Version gating - Registers a new capability flag `user-v2-extended-filter` in `packages/backend.ai-client/src/client.ts`, mirroring the existing `model-deployment-extended-filter` / `rbac-element-type-filter` (rc-pinned) pattern. - **Gated at `26.4.4rc6`.** BA-6247 / BA-6249 merged *after* the `26.4.4rc6` tag, so they ship in **26.4.4 (final)**. The flag is pinned to the `rc6` tag so it also activates against the rc6 staging manager (a post-rc6 snapshot reporting `26.4.4rc6`). A `TODO(FR-3024)` notes simplifying to `26.4.4` once rc builds are out of use. - The 10 extended filters live in a single `extendedFilterProperties` array and are conditionally spread into `filterProperties` via `bailClient.supports('user-v2-extended-filter')` — the 5 base filters are always present. ### Schema sync - Syncs `data/schema.graphql` to backend.ai `main`'s composed supergraph (`docs/manager/graphql-reference/supergraph.graphql`) so `UserV2Filter` now defines the new fields. This is a **full schema bump** (+596 lines) and also pulls in other already-merged backend types (RBAC role presets, keypair filters, etc.). - `pnpm relay` regenerated the affected artifacts (`AdminUserManagementQuery` now models the new filter fields; 7 other `__generated__` queries/mutations updated incidentally by the bump). - Note: #7672 (FR-3020) also edits `data/schema.graphql` (surgical, IntArrayFilter + keypair nested filter). Whichever merges second will need a trivial `data/schema.graphql` restack against the other. ### Notes / out of scope - `containerGids` is an `IntArrayFilter` (`contains` / `containsAny` / `containsAll`). `BAIGraphQLPropertyFilter` has no array-operator input, so only the single-GID `contains` operator is exposed via `fixedOperator: 'contains'`. - The three integer filters (`containerUid` / `containerMainGid` / `containerGids`) carry an `integerRule` so non-integer input is rejected before `Number(...)` coercion (avoids `NaN` / invalid `Int` variables). - All labels reuse existing `credential.*` i18n keys (same keys the legacy v1 user list uses) — no new i18n keys, no hardcoded strings. ## Testing - Test against the **`10.82.0.130`** test server (reports `26.4.4rc6`). - With the gate pinned at `26.4.4rc6`, the `user-v2-extended-filter` flag activates directly on this server — **no manual version edit needed**. All 15 filters appear in the super-admin **User Management** list; on a manager older than `26.4.4rc6`, only the 5 base filters. ## Verification `bash scripts/verify.sh` → `=== ALL PASS ===` (Relay, Lint, Format, TypeScript). ## Test plan - [ ] On `10.82.0.130` (26.4.4rc6), all 15 filters are offered and each produces a valid `UserV2Filter` query. - [ ] On a manager older than 26.4.4rc6, only the 5 base filters are offered. - [ ] Boolean filters emit scalar `true` / `false`; `containerUid` / `containerMainGid` emit `{ equals: N }`; `containerGids` emits `{ contains: N }`. - [ ] Non-integer input in `containerUid` / `containerMainGid` / `containerGids` is rejected with an inline error.

Resolves #7664 (FR-3016)
Summary
Migrate the super-admin user list (Users tab of the Users & Credentials page) from the legacy
user_nodes(v1) query toadminUsersV2(UserV2Connection). Per the issue scope, only the list/table is migrated to v2; all modals keep their existing (v1) implementation.user_nodes→adminUsersV2; componentBAIUserNodes→BAIUserV2Nodes.BAIPropertyFilter(string DSL) →BAIGraphQLPropertyFilter(structuredUserV2Filter), reusing theProjectAdminUsersPagepattern. Only the fieldsUserV2Filtercurrently supports are exposed: email, ID (uuid), username, role, project name, Active/Inactive status.UserV2Filterand were dropped:full_name,resource_policy,description,status_info,need_password_change,totp_activated,sudo_session_enabled. They need a backendUserV2Filterextension (separate follow-up).convertToOrderBy+availableUserV2SorterValues(v2UserV2OrderField).PurgeUsersModal/UpdateUsersModalnow take a plain{ id, email }[]usersprop instead of aUserNodeGraphQL fragment (they only ever used id/email); Info/Setting modals already key offuserEmail. No modal mutation was changed. Follow-up to move these modals onto a v2UserV2fragment is tracked in FR-3019.bailClient.supports('bulk-create-user'); selection is cleared on filter change as well as on status/order/pagination changes.UserV2(incl. UID/GID viacontainer.*,needPasswordChangeviastatus.*).Renames (align with
ProjectAdminUsersPage)UserCredentialsPage→AdminUsersPage(page)UserManagement→AdminUserManagement(Users tab content)UserCredentialList→AdminUserCredentialListRelay query/mutation names and
routes.tsximport updated accordingly.Testing
A ready-to-test backend is already running at
http://10.122.10.117:8090with the RBAC schema fix applied. Point the WebUI's API endpoint there and you can test this PR immediately — no local changes required.Background: on a stock 26.4.3 core, the user list can't even load because of a separate RBAC filter-format mismatch (the
myRolesquery sendsentityTypeas a Filter object, but 26.4.3 expects a bare enum). That root cause is tracked in FR-3017 (#7665) and is intentionally not part of this PR. The server above already has the fix applied — the steps below are only needed if you want to point at a different 26.4.3 backend that doesn't.Manual local workaround for an unpatched 26.4.3 backend
Apply these two local edits without committing them:
react/src/hooks/useCurrentUserProjectRoles.ts— myRoles filter:data/schema.graphql— insideinput PermissionNestedFilter:pnpm relay(or let the dev watcher recompile), then refresh the dev server.These make
myRolessendentityTypeas a direct enum (accepted by 26.4.3). They are incompatible with the latest backend's Filter form, so they must not be committed.Verification
bash scripts/verify.sh: Lint / Format / TypeScript PASS; Relay artifacts regenerated and committed.🤖 Generated with Claude Code