Skip to content

A system admin can make another user a system admin - #1234

Merged
WaylandYang merged 8 commits into
deeplethe:devfrom
gedaiu:feat/system-admin-toggle
Oct 15, 2026
Merged

WaylandYang merged 8 commits into
deeplethe:devfrom
gedaiu:feat/system-admin-toggle

Conversation

@gedaiu

@gedaiu gedaiu commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Closes #1233

Only the first user to register ever became a system admin, and nothing could change that afterwards, so a deployment had exactly one person who could open Administration. Making people workspace owners or admins doesn't help, because those roles don't reach it.

Now a system admin can tick "System admin" in another user's member dialog. It goes through PUT /api/v1/admin/users/{id} with { "is_admin": bool }, which only a system admin may call, and each change is written to the audit log as user.admin_granted or user.admin_revoked. You can't remove your own flag; the checkbox is locked on your own row and the store refuses it too. Because of that, the org always keeps at least one admin, so there's no separate last-admin check. A deactivated or unknown user is a 404.

The dialog now saves only what changed (memberChanges), so a role edit and a flag edit can go out together or alone.

Tests: store cases for grant, self-revoke and not-found (an_admin_grants_system_admin.rs), a route test for the 403, the 200 and the audit row (system_admin_tests.rs), and memberChanges.test.ts. The full store and server suites pass against Postgres, along with the web build and vitest.

🤖 Generated with Claude Code

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

Thank you for turning this around so quickly. The route is admin-only, the store refuses a self-revoke and unknown or deactivated users, the flag is read fresh on every request so a revoke takes effect at once, and each change is audited. I ran the store, route and web tests on a fresh database: all pass.

Merging. Thanks again.

@WaylandYang
WaylandYang merged commit 70bf7a7 into deeplethe:dev Oct 15, 2026
6 checks passed
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.

2 participants