Skip to content

refactor(FR-3016): migrate super-admin user list to adminUsersV2 query#7666

Merged
graphite-app[bot] merged 1 commit into
mainfrom
fr-3016-user-list-v2-migration
Jun 2, 2026
Merged

refactor(FR-3016): migrate super-admin user list to adminUsersV2 query#7666
graphite-app[bot] merged 1 commit into
mainfrom
fr-3016-user-list-v2-migration

Conversation

@ironAiken2

@ironAiken2 ironAiken2 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

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_nodesadminUsersV2; component BAIUserNodesBAIUserV2Nodes.
  • 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)

  • UserCredentialsPageAdminUsersPage (page)
  • UserManagementAdminUserManagement (Users tab content)
  • UserCredentialListAdminUserCredentialList

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.

Manual local workaround for an unpatched 26.4.3 backend

Apply these two local edits without committing them:

  1. react/src/hooks/useCurrentUserProjectRoles.ts — myRoles filter:
    -          filter: { permission: { entityType: { equals: PROJECT_ADMIN_PAGE } } }
    +          filter: { permission: { entityType: PROJECT_ADMIN_PAGE } }
  2. data/schema.graphql — inside input PermissionNestedFilter:
    -  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.

Verification

bash scripts/verify.sh: Lint / Format / TypeScript PASS; Relay artifacts regenerated and committed.

🤖 Generated with Claude Code

@github-actions github-actions Bot added the size:XL 500~ LoC label Jun 1, 2026

ironAiken2 commented Jun 1, 2026

Copy link
Copy Markdown
Contributor Author

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • flow:merge-queue - adds this PR to the back of the merge queue
  • flow:hotfix - for urgent changes, fast-track this PR to the front of 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.

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for react-coverage (./react)

Status Category Percentage Covered / Total
🔵 Lines 6.65% 1808 / 27166
🔵 Statements 5.43% 2004 / 36906
🔵 Functions 5.43% 300 / 5521
🔵 Branches 3.78% 1306 / 34461
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
react/src/routes.tsx 0% 0% 0% 0% 41-1029
react/src/components/PurgeUsersModal.tsx 0% 0% 0% 0% 44-219
react/src/components/UpdateUsersModal.tsx 0% 0% 0% 0% 53-335
Generated in workflow #1328 for commit c30de63 by the Vitest Coverage Report Action

@ironAiken2 ironAiken2 force-pushed the fr-3016-user-list-v2-migration branch from 629154c to 6d9cf71 Compare June 1, 2026 08:17
@ironAiken2 ironAiken2 marked this pull request as ready for review June 1, 2026 08:21
Copilot AI review requested due to automatic review settings June 1, 2026 08:21

Copilot AI 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.

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 /credential route page component with AdminUsersPage (Users / Credentials tabs).
  • Migrates the admin user list component to AdminUserManagementQuery (adminUsersV2) and BAIUserV2Nodes.
  • 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 selectedUserList refer 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.

Comment thread react/src/routes.tsx
@ironAiken2 ironAiken2 force-pushed the fr-3016-user-list-v2-migration branch from 6d9cf71 to 3513119 Compare June 1, 2026 08:31
@ironAiken2

Copy link
Copy Markdown
Contributor Author

Also addressed the two low-confidence suggestions from the review:

  • Restored the bailClient.supports('bulk-create-user') guard on the bulk-create menu (it was unintentionally dropped during the migration, which would have shown the menu on older managers where the mutation fails).
  • Clear selectedUserList on filter change (in addition to status/order/pagination) to avoid applying Update/Purge to stale, no-longer-visible selections.

@nowgnuesLee nowgnuesLee 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.

LGTM

@yomybaby yomybaby left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@graphite-app

graphite-app Bot commented Jun 2, 2026

Copy link
Copy Markdown

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)
@graphite-app graphite-app Bot force-pushed the fr-3016-user-list-v2-migration branch from 3513119 to c30de63 Compare June 2, 2026 08:05
@graphite-app graphite-app Bot merged commit c30de63 into main Jun 2, 2026
12 checks passed
@graphite-app graphite-app Bot deleted the fr-3016-user-list-v2-migration branch June 2, 2026 08:06
graphite-app Bot pushed a commit that referenced this pull request Jun 4, 2026
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500~ LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate super-admin user list to v2 (Relay node) GraphQL query

4 participants