Browse Source

Keep per-collection manage working for Custom members

The manage flag in collection JSON was gated on atype == Manager, a raw
comparison that now excludes Custom (4). A Custom member holding an
explicit per-collection manage assignment (or full read/write access)
would have lost the manage capability in /sync and the collection
details endpoints - before this PR they were stored as Manager and
matched. Compare by access level (>= Manager, which Manager and Custom
share) instead, restoring the exact pre-PR behavior for migrated
members. Admins/Owners are unaffected: they are caught by the earlier
has_full_access / >= Admin arms.
pull/7397/head
tom27052006 2 weeks ago
parent
commit
84b8de124e
  1. 11
      src/db/models/collection.rs
  2. 2
      src/db/models/organization.rs

11
src/db/models/collection.rs

@ -102,8 +102,9 @@ impl Collection {
// Owners and Admins always have true. Users are not able to have full access
Some(m) if m.has_full_access() => (false, false, m.atype >= MembershipType::Manager),
Some(m) => {
// Only let a manager manage collections when the have full read/write access
let is_manager = m.atype == MembershipType::Manager;
// Only let a manager-level member (Manager or Custom) manage collections
// when they have full read/write access
let is_manager = m.atype >= MembershipType::Manager;
if let Some(cu) = cipher_sync_data.user_collections.get(&self.uuid) {
(
cu.read_only,
@ -125,11 +126,11 @@ impl Collection {
} else {
match Membership::find_confirmed_by_user_and_org(user_uuid, &self.org_uuid, conn).await {
Some(m) if m.has_full_access() => (false, false, m.atype >= MembershipType::Manager),
Some(m) if m.atype == MembershipType::Manager && self.is_manageable_by_user(user_uuid, conn).await => {
Some(m) if m.atype >= MembershipType::Manager && self.is_manageable_by_user(user_uuid, conn).await => {
(false, false, true)
}
Some(m) => {
let is_manager = m.atype == MembershipType::Manager;
let is_manager = m.atype >= MembershipType::Manager;
let read_only = !self.is_writable_by_user(user_uuid, conn).await;
let hide_passwords = self.hide_passwords_for_user(user_uuid, conn).await;
(read_only, hide_passwords, is_manager && !read_only && !hide_passwords)
@ -945,7 +946,7 @@ impl CollectionMembership {
"hidePasswords": self.hide_passwords,
"manage": membership_type >= MembershipType::Admin
|| self.manage
|| (membership_type == MembershipType::Manager
|| (membership_type >= MembershipType::Manager
&& !self.read_only
&& !self.hide_passwords),
})

2
src/db/models/organization.rs

@ -584,7 +584,7 @@ impl Membership {
(
cu.read_only,
cu.hide_passwords,
cu.manage || (self.atype == MembershipType::Manager && !cu.read_only && !cu.hide_passwords),
cu.manage || (self.atype >= MembershipType::Manager && !cu.read_only && !cu.hide_passwords),
)
// If previous checks failed it might be that this user has access via a group, but we should not return those elements here
// Those are returned via a special group endpoint

Loading…
Cancel
Save