feat(users): admin user lifecycle (VAPP-11) #16

Merged
David merged 2 commits from feat/user-management into main 2026-06-06 23:45:09 +02:00
Owner

Closes VAPP-11.

What

Replace the read-only Users table (the old "edit" link was href="#", with no create or remove) with a full admin user lifecycle backed by the control channel. Every mutation goes through a #[server] fn that proxies one vervain-server control action and renders the server's result inline on failure.

Server fns

  • control.rs grows request_ack(): send a write-style action and resolve its {action:"ack", for, result, id} frame, treating result == "ok" as success and mapping known result codes (not-authorized, user-exists, bad-username, bad-password, not-found) to UI messages while passing unknown codes through verbatim.
  • create_user (admin checkbox maps to the full 0xFFFFFFFF siteadmin mask, matching list_users' role mapping; adduser), remove_user (deleteuser), set_user_password (changeuserpass), set_mesh_membership (addmeshuser / removemeshuser).
  • list_users now also surfaces each account's mesh grants from the links map (mesh entries only), which survive the server's clone-safe scrub.

UI

  • "New user" dialog: username, initial password, site-admin checkbox. States that passwords are handed over out of band, since there is no invite-email path yet.
  • Per-row edit drawer: reset-password section, plus a mesh-membership editor (current grants with remove, and an add row offering a mesh select and a rights preset: full / desktop-no-tools / read-only, mapping to the MESHRIGHT_* bitmap in vervain-server's rights.rs).
  • Per-row remove dialog requiring the login name typed to confirm.

Acceptance criteria mapping

  • Create user, log in as that user in a second session: create_user -> adduser.
  • Reset password forces the new credential: set_user_password -> changeuserpass (server rehashes and stamps passchange, so the old credential stops working).
  • Mesh membership add/remove changes what the target user sees on /devices: set_mesh_membership -> addmeshuser / removemeshuser.
  • Remove user requires typed username and kills login: remove dialog gates the call on the typed login name; deleteuser removes the account doc.
  • All actions admin-only; errors render inline: server gates produce not-authorized (and other) result codes, surfaced inline by request_ack + the dialogs.

Notes

  • addmeshuser / removemeshuser gate on the actor's MANAGE_USERS right on the target mesh (no site-admin bypass on the server), so an admin without that mesh right gets a not-authorized message inline. The mesh select only lists meshes the actor can already see.
  • Rights presets are a UI design choice within the issue's "preset" latitude; the bit values mirror rights.rs and a free-form bitmap editor can grow later without a schema change.

Verification

Not verified end to end here (no live vervain-server in this environment). cargo check (server + wasm32-unknown-unknown), cargo clippy --features server -- -D warnings, cargo fmt --check, and cargo test --features server all pass.

🤖 Generated with Claude Code

Closes VAPP-11. ## What Replace the read-only Users table (the old "edit" link was `href="#"`, with no create or remove) with a full admin user lifecycle backed by the control channel. Every mutation goes through a `#[server]` fn that proxies one vervain-server control action and renders the server's result inline on failure. ## Server fns - `control.rs` grows `request_ack()`: send a write-style action and resolve its `{action:"ack", for, result, id}` frame, treating `result == "ok"` as success and mapping known result codes (`not-authorized`, `user-exists`, `bad-username`, `bad-password`, `not-found`) to UI messages while passing unknown codes through verbatim. - `create_user` (admin checkbox maps to the full `0xFFFFFFFF` siteadmin mask, matching `list_users`' role mapping; `adduser`), `remove_user` (`deleteuser`), `set_user_password` (`changeuserpass`), `set_mesh_membership` (`addmeshuser` / `removemeshuser`). - `list_users` now also surfaces each account's mesh grants from the `links` map (mesh entries only), which survive the server's clone-safe scrub. ## UI - "New user" dialog: username, initial password, site-admin checkbox. States that passwords are handed over out of band, since there is no invite-email path yet. - Per-row edit drawer: reset-password section, plus a mesh-membership editor (current grants with remove, and an add row offering a mesh select and a rights preset: full / desktop-no-tools / read-only, mapping to the `MESHRIGHT_*` bitmap in vervain-server's `rights.rs`). - Per-row remove dialog requiring the login name typed to confirm. ## Acceptance criteria mapping - [x] Create user, log in as that user in a second session: `create_user` -> `adduser`. - [x] Reset password forces the new credential: `set_user_password` -> `changeuserpass` (server rehashes and stamps `passchange`, so the old credential stops working). - [x] Mesh membership add/remove changes what the target user sees on /devices: `set_mesh_membership` -> `addmeshuser` / `removemeshuser`. - [x] Remove user requires typed username and kills login: remove dialog gates the call on the typed login name; `deleteuser` removes the account doc. - [x] All actions admin-only; errors render inline: server gates produce `not-authorized` (and other) result codes, surfaced inline by `request_ack` + the dialogs. ## Notes - `addmeshuser` / `removemeshuser` gate on the actor's `MANAGE_USERS` right on the target mesh (no site-admin bypass on the server), so an admin without that mesh right gets a not-authorized message inline. The mesh select only lists meshes the actor can already see. - Rights presets are a UI design choice within the issue's "preset" latitude; the bit values mirror `rights.rs` and a free-form bitmap editor can grow later without a schema change. ## Verification Not verified end to end here (no live vervain-server in this environment). `cargo check` (server + `wasm32-unknown-unknown`), `cargo clippy --features server -- -D warnings`, `cargo fmt --check`, and `cargo test --features server` all pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(users): admin user lifecycle (create, reset, mesh, remove)
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 52s
87d8913d24
Replace the read-only Users table (the old "edit" link was href="#", with no create or remove) with a full admin lifecycle backed by the control channel. Each mutation goes through a #[server] fn that proxies one vervain-server control action and renders the server's result inline on failure, so the admin-only gates surface as friendly messages rather than silent no-ops.

- control.rs grows request_ack(): send a write-style action and resolve its `{action:"ack", for, result, id}` frame, treating result == "ok" as success and mapping known result codes (not-authorized, user-exists, bad-username, bad-password, not-found) to UI messages while passing unknown codes through verbatim.
- New server fns: create_user (admin checkbox maps to the full 0xFFFFFFFF siteadmin mask, matching list_users' role mapping; adduser), remove_user (deleteuser), set_user_password (changeuserpass), set_mesh_membership (addmeshuser / removemeshuser). list_users now also surfaces each account's mesh grants from the `links` map (mesh entries only), which survive the server's clone-safe scrub.
- New model: MeshMembership { mesh_id, rights }; User gains a memberships vec. User, MeshMembership and Mesh gain PartialEq so they can be passed as component props.
- Users page: "New user" dialog (username, initial password, site-admin checkbox; states passwords are handed over out of band since there is no invite email yet); per-row edit drawer with reset-password plus a mesh-membership editor (current grants with remove, an add row offering a mesh select and a rights preset: full / desktop-no-tools / read-only, mapping to the MESHRIGHT_* bitmap in vervain-server's rights.rs); per-row remove dialog requiring the login name typed to confirm.

Behavior note: addmeshuser / removemeshuser gate on the actor's MANAGE_USERS right on the target mesh (no site-admin bypass on the server), so an admin without that mesh right gets a not-authorized message inline. The mesh select only lists meshes the actor can already see.

Not verified end to end here (no live vervain-server in this environment); cargo check (server + wasm32), clippy -D warnings, fmt, and tests all pass.

#VAPP-11

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merge branch 'main' into feat/user-management
All checks were successful
Create release / Create release from merged PR (pull_request) Has been skipped
Check / fmt + clippy + build + tests (pull_request) Successful in 53s
5248394d16
David merged commit e97c77779c into main 2026-06-06 23:45:09 +02:00
David deleted branch feat/user-management 2026-06-06 23:45:09 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-apps!16
No description provided.