feat(plugin-perms): enforce per-user plugin permissions on dispatch (VS-6) #20

Merged
David merged 2 commits from feat/plugin-permissions-vs-6 into main 2026-05-17 14:36:31 +02:00
Owner

Summary

Closes the gap between the persistence layer (already wired) and the dispatch path (admin-only gate) for plugin permissions.

Changes

  • plugin_dispatch_allowed(state, user, is_admin, plugin_name): site-admin bypass, then permission intersection check against user.pluginPermissions.
  • ControlIn::Plugin dispatch arm: replaces the raw if !is_admin early-return with the new gate; denied callers get a result:"denied" ack.
  • Refreshed serde docs on GetPluginPermissions and SetPluginPermissions.
  • New PluginCatalog::for_test(manifests) test helper.
  • 5 new unit tests on the gate (admin/non-admin x perms-required/not-required, unknown plugin).

Test plan

  • cargo test -p meshcentral-web --lib plugin_dispatch_allowed (5/5 passing).
  • cargo check -p meshcentral-web clean.
  • Reviewer: grant a non-admin a plugin permission via setpluginpermissions, confirm they can now invoke a Plugin that declares it.

Closes VS-6.

## Summary Closes the gap between the persistence layer (already wired) and the dispatch path (admin-only gate) for plugin permissions. ## Changes - `plugin_dispatch_allowed(state, user, is_admin, plugin_name)`: site-admin bypass, then permission intersection check against `user.pluginPermissions`. - `ControlIn::Plugin` dispatch arm: replaces the raw `if !is_admin` early-return with the new gate; denied callers get a `result:"denied"` ack. - Refreshed serde docs on `GetPluginPermissions` and `SetPluginPermissions`. - New `PluginCatalog::for_test(manifests)` test helper. - 5 new unit tests on the gate (admin/non-admin x perms-required/not-required, unknown plugin). ## Test plan - [x] `cargo test -p meshcentral-web --lib plugin_dispatch_allowed` (5/5 passing). - [x] `cargo check -p meshcentral-web` clean. - [ ] Reviewer: grant a non-admin a plugin permission via `setpluginpermissions`, confirm they can now invoke a Plugin that declares it. Closes VS-6.
feat(plugin-perms): enforce per-user plugin permissions on Plugin dispatch (VS-6)
Some checks failed
Check / fmt + clippy + build + tests (pull_request) Failing after 3s
297b25112f
`get_plugin_permissions` and `set_plugin_permissions` already persisted the per-user grant map (`user.pluginPermissions`), but the `Plugin` control action only checked the site-admin bit before invoking the wasm guest. Two gaps:

1. The serde doc comments still claimed both were stubs; ROADMAP filed VS-6 off that.
2. Non-admin grant entries were dead weight: a granted user was still rejected by the admin gate.

Adds `plugin_dispatch_allowed(state, user, is_admin, plugin_name)`. Plugins that declare no `permissions` field in their manifest stay admin-only (status quo). Plugins that declare permissions admit any caller whose `user.pluginPermissions[<perm>]==true` intersects the declared list; admins bypass. Denials now ack with `result:"denied"` so the SPA renders an actionable status instead of timing out on a silent admin-gate drop.

Adds a `PluginCatalog::for_test(manifests)` helper so the gate tests don't need a tempdir + JSON write per case, plus five unit tests covering: admin / non-admin x permissions-required / permissions-not-required, and unknown-plugin-name.

#VS-6 State Done
Merge branch 'main' into feat/plugin-permissions-vs-6
Some checks failed
Check / fmt + clippy + build + tests (pull_request) Failing after 3s
Create release / Create release from merged PR (pull_request) Has been skipped
9288ffd345
David merged commit cff04cb003 into main 2026-05-17 14:36:31 +02:00
David deleted branch feat/plugin-permissions-vs-6 2026-05-17 14:36:31 +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-server!20
No description provided.