From 81b76d9782aa84cfb8e5a9dbf5b7342456b8139f Mon Sep 17 00:00:00 2001 From: tom27052006 <83423411+tom27052006@users.noreply.github.com> Date: Wed, 8 Jul 2026 18:29:52 +0200 Subject: [PATCH] Persist manage_* permission flags on invite send_invite computed access_all from the invite permissions but never wrote the manage_users / manage_groups / manage_policies flags onto the new membership, so a Custom member invited with a management permission checked was created without it (the web-vault sends everything in a single invite POST, with no follow-up edit). Mirror the handling in edit_member and persist the flags at invite time. Only Owners can invite Custom members, so the caller is always authorized to grant these; the flags are gated on the Custom type and forced false for every other type. --- src/api/core/organizations.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/api/core/organizations.rs b/src/api/core/organizations.rs index e0776826..9528a756 100644 --- a/src/api/core/organizations.rs +++ b/src/api/core/organizations.rs @@ -1095,6 +1095,14 @@ async fn send_invite( && data.permissions.get("deleteAnyCollection") == Some(&json!(true)) && data.permissions.get("createNewCollections") == Some(&json!(true))); + // Read the explicit Custom-role management permissions. These only apply to the + // Custom type; for every other type they are forced to false. Only Owners can invite + // Custom members (checked above), so the caller is always authorized to grant these. + let perm = |key: &str| new_type == MembershipType::Custom && data.permissions.get(key) == Some(&json!(true)); + let manage_users = perm("manageUsers"); + let manage_groups = perm("manageGroups"); + let manage_policies = perm("managePolicies"); + let mut user_created: bool = false; for email in &data.emails { let mut member_status = MembershipStatus::Invited as i32; @@ -1137,6 +1145,9 @@ async fn send_invite( let mut new_member = Membership::new(user.uuid.clone(), org_id.clone(), Some(headers.user.email.clone())); new_member.access_all = access_all; new_member.atype = new_type as i32; + new_member.manage_users = manage_users; + new_member.manage_groups = manage_groups; + new_member.manage_policies = manage_policies; new_member.status = member_status; new_member.save(&conn).await?;