Repository navigation
Reader role: an administrator made on the user page or through POST /admin/users stays a reader after a demotion - #852
Merged
Conversation
…admin/users stays a reader after a demotion An administrator made after the upgrade held `admin` alone: the user page's switch to Admin unassigned `reader`, and `POST /admin/users` with `"role": "admin"` assigned `admin` only. An OIDC or credential-forwarding realm that later took `admin` away (`sync_admin_role(false)`) left the account with no built-in role, unlike the administrators migration 0013 found, who keep `reader` (#792). - `insert_with_role` assigns `reader` next to `admin` for user accounts. A service account never holds `admin` and gets no `reader`. - The user page's Admin level is `admin` plus `reader`: switching to it assigns both and unassigns only writer; switching back to Reader takes `admin` alone. Fixes #812 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012e6DJXgdmBmbEhT2HcZAv5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #812
Problem
#792 (#810) gave the built-in
readerrole to every administrator migration 0013 finds.docs/changes/2.2.0/733.upgrade.mdpromises the same for accounts made after the upgrade: an admin "stays a reader, as an account created after the upgrade does". Admins made on 2.2 through the admin UI or API did not get it:UserAccess,web/src/routes/admin/users/Edit.tsx) assignedadmin, then unassigned every other level role,readerincluded.POST /admin/userswith"role": "admin"(insert_with_role), assignedadminonly.An OIDC realm with admin groups or claim, or a credential-forwarding realm with
admin_group, demotes throughsync_admin_role(false), which removesadminand nothing else. So the account was left Roles only and lost all read access.Change
I picked the first option from the issue: keep
readernext toadmin.insert_with_role(crates/server/src/admin/users.rs) also assignsreaderwhenroleisadmin, in the same transaction, for user accounts. Service accounts are refusedadminalready. They get noreadereither way and stay Roles only.UserAccesstreats the Admin level asadmin+reader. Switching to Admin assigns both, skipping roles the user already holds, then unassigns onlywriter. Switching from Admin to Reader takesadminalone, and to Roles only takes both. Assign-before-unassign is unchanged, so the last-admin 409 still leaves the user with nothing lost.Create.tsx) already sendsrole: admin, so the server change covers it. The user list needed no change:accessLevelshows the highest built-in role (admin), andRoleBadgesleavesreaderout like the other level roles. A test now checks both.Why not the second option (
sync_admin_role(false)assigns the realm'snew_account_access):reader. With this change every admin matches that, however they became one.sync_admin_rolea pure admin toggle. It would not givereaderback to an account an administrator deliberately set to Roles only, which a demotion path cannot tell apart.The admin API itself is unchanged (
POST /admin/usersgives one extra role on the existingrole: adminvalue), and its screens are updated in this PR. Changelog fragment:docs/changes/2.2.0/812.fixed.md.Tests
crates/server/tests/auth_realms.rs,an_admin_demoted_by_the_upstream_stays_a_reader: a credential-forwarding realm withgroups_path/admin_groupwhose mock upstream lists no admin group."role": "admin"holdsadmin+reader.admin+reader.readeronly.role: adminis 400, and one without a role holds no role.insert_with_rolethis test fails (["admin"]instead of["admin", "reader"]).crates/server/tests/oidc_routes.rs,a_user_made_admin_on_the_user_page_stays_a_reader_after_an_idp_demotion: an IdP-provisioned reader is switched to Admin through the page's call (PUT admin; reader is kept). The next login without the admin group leavesreader.web/src/routes/admin/users/userRoles.test.tsx:reader, and the list shows them as admin with no extra role badge.Edit.tsx.cargo fmt --all -- --check: okcargo clippy -p forge-server --all-targets -- -D warnings: okcargo test -p forge-server --test auth_realms --test oidc_routes --test admin_rbac --test service_accounts --test admin --test invitations --test trusted_header: all pass (Postgres frommirror.gcr.io/library/postgres)cargo xtask changelog --check: okpnpm run tsc: okpnpm exec vitest run src/routes/admin/users src/routes/admin/service-accounts: 49 passedweb/package.jsonhas no lint script.Generated by Claude Code