Skip to content

Commit 8edab9f

Browse files
committed
fix(sharing): preserve group removals on conflicts
1 parent 6ce71b4 commit 8edab9f

4 files changed

Lines changed: 59 additions & 29 deletions

File tree

model/sharing/group.go

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,9 @@ func (s *Sharing) RevokeGroup(inst *instance.Instance, index int) error {
9090
if !inGroup {
9191
continue
9292
}
93-
if len(m.Groups) == 1 {
94-
s.Members[i].Groups = nil
95-
} else {
96-
var groups []int
97-
for _, idx := range m.Groups {
98-
if idx != index {
99-
groups = append(groups, idx)
100-
}
101-
}
102-
s.Members[i].Groups = groups
103-
}
93+
removeGroupFromMember(&s.Members[i], index)
10494
if m.OnlyInGroups && len(s.Members[i].Groups) == 0 {
105-
if err := s.RevokeRecipient(inst, i); err != nil {
95+
if err := s.revokeRecipientAfterRemovingGroup(inst, i, index); err != nil {
10696
errm = multierror.Append(errm, err)
10797
}
10898
}
@@ -304,6 +294,16 @@ func addGroupToMember(member *Member, groupIndex int) bool {
304294
return true
305295
}
306296

297+
func removeGroupFromMember(member *Member, groupIndex int) {
298+
var groups []int
299+
for _, index := range member.Groups {
300+
if index != groupIndex {
301+
groups = append(groups, index)
302+
}
303+
}
304+
member.Groups = groups
305+
}
306+
307307
func (s *Sharing) contactIsMemberOfGroup(groupIndex int, c *contact.Contact) bool {
308308
var email string
309309
if addr, err := c.ToMailAddress(); err == nil {
@@ -354,16 +354,10 @@ func (s *Sharing) RemoveMemberFromGroup(inst *instance.Instance, groupIndex int,
354354
continue
355355
}
356356

357-
var groups []int
358-
for _, idx := range m.Groups {
359-
if idx != groupIndex {
360-
groups = append(groups, idx)
361-
}
362-
}
363-
s.Members[i].Groups = groups
357+
removeGroupFromMember(&s.Members[i], groupIndex)
364358

365359
if m.OnlyInGroups && len(s.Members[i].Groups) == 0 {
366-
return s.RevokeRecipient(inst, i)
360+
return s.revokeRecipientAfterRemovingGroup(inst, i, groupIndex)
367361
} else {
368362
return couchdb.UpdateDoc(inst, s)
369363
}
@@ -425,16 +419,10 @@ func (s *Sharing) SendRemoveMemberFromGroup(inst *instance.Instance, groupIndex,
425419
}
426420

427421
func (s *Sharing) DelegatedRemoveMemberFromGroup(inst *instance.Instance, groupIndex, memberIndex int) error {
428-
var groups []int
429-
for _, idx := range s.Members[memberIndex].Groups {
430-
if idx != groupIndex {
431-
groups = append(groups, idx)
432-
}
433-
}
434-
s.Members[memberIndex].Groups = groups
422+
removeGroupFromMember(&s.Members[memberIndex], groupIndex)
435423

436424
if s.Members[memberIndex].OnlyInGroups && len(s.Members[memberIndex].Groups) == 0 {
437-
return s.RevokeRecipient(inst, memberIndex)
425+
return s.revokeRecipientAfterRemovingGroup(inst, memberIndex, groupIndex)
438426
} else {
439427
return couchdb.UpdateDoc(inst, s)
440428
}

model/sharing/group_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,33 @@ func TestGroups(t *testing.T) {
360360
assert.False(t, s.Groups[0].Revoked)
361361
})
362362

363+
t.Run("RemoveMemberFromGroupPreservesRemovalAfterConflict", func(t *testing.T) {
364+
team := createGroup(t, inst, "Conflicting Drive Team")
365+
otherTeam := createGroup(t, inst, "Remaining Drive Team")
366+
alice := createContactInGroups(t, inst, "ConflictAlice", []string{team.ID()})
367+
368+
s := createDriveSharingForGroupTest(t, inst, "Conflicting group removal")
369+
s.OrgDrive = true
370+
sid := s.SID
371+
require.NoError(t, s.AddGroup(inst, team.ID(), false))
372+
require.NoError(t, s.AddGroup(inst, otherTeam.ID(), false))
373+
require.NoError(t, couchdb.UpdateDoc(inst, s))
374+
375+
concurrent := &Sharing{}
376+
require.NoError(t, couchdb.GetDoc(inst, consts.Sharings, sid, concurrent))
377+
concurrent.Description = "Updated concurrently"
378+
require.NoError(t, couchdb.UpdateDoc(inst, concurrent))
379+
380+
require.NoError(t, s.RemoveMemberFromGroup(inst, 0, alice))
381+
382+
stored := &Sharing{}
383+
require.NoError(t, couchdb.GetDoc(inst, consts.Sharings, sid, stored))
384+
require.Len(t, stored.Members, 2)
385+
assert.Equal(t, MemberStatusRevoked, stored.Members[1].Status)
386+
assert.Empty(t, stored.Members[1].Groups)
387+
assert.Equal(t, "Updated concurrently", stored.Description)
388+
})
389+
363390
t.Run("RevokeLastDriveGroupDeletesSharing", func(t *testing.T) {
364391
team := createGroup(t, inst, "Drive Group")
365392
_ = createContactInGroups(t, inst, "DriveGroupAlice", []string{team.ID()})

model/sharing/member.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,10 @@ func (s *Sharing) DelegateRevokeRecipient(inst *instance.Instance, index int) er
11881188

11891189
// RevokeMember revoke the access granted to a member and contact it
11901190
func (s *Sharing) RevokeMember(inst *instance.Instance, index int) error {
1191+
return s.revokeMember(inst, index, nil)
1192+
}
1193+
1194+
func (s *Sharing) revokeMember(inst *instance.Instance, index int, removedGroupIndex *int) error {
11911195
m := &s.Members[index]
11921196

11931197
// skip if member is already revoked
@@ -1220,6 +1224,9 @@ func (s *Sharing) RevokeMember(inst *instance.Instance, index int) error {
12201224
// operation several times.
12211225
leftRetries := 3
12221226
for {
1227+
if removedGroupIndex != nil {
1228+
removeGroupFromMember(m, *removedGroupIndex)
1229+
}
12231230
m.Status = MemberStatusRevoked
12241231
// Do not remove the credentials from the array to preserve the members /
12251232
// credentials order, just empty them

model/sharing/sharing.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,10 +758,18 @@ func (s *Sharing) RemoveInteractPermissionsForAMember(inst *instance.Instance, m
758758
// sharing has still at least one active member, we keep it as is. Else, we
759759
// disable the sharing.
760760
func (s *Sharing) RevokeRecipient(inst *instance.Instance, index int) error {
761+
return s.revokeRecipient(inst, index, nil)
762+
}
763+
764+
func (s *Sharing) revokeRecipientAfterRemovingGroup(inst *instance.Instance, index, groupIndex int) error {
765+
return s.revokeRecipient(inst, index, &groupIndex)
766+
}
767+
768+
func (s *Sharing) revokeRecipient(inst *instance.Instance, index int, removedGroupIndex *int) error {
761769
if !s.Owner {
762770
return ErrInvalidSharing
763771
}
764-
if err := s.RevokeMember(inst, index); err != nil {
772+
if err := s.revokeMember(inst, index, removedGroupIndex); err != nil {
765773
return err
766774
}
767775
m := &s.Members[index]

0 commit comments

Comments
 (0)