Skip to content

Commit e1ff361

Browse files
committed
fix: remove a repair flow on share-interact permission creation
1 parent 177a476 commit e1ff361

2 files changed

Lines changed: 125 additions & 38 deletions

File tree

model/permission/permissions.go

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -827,50 +827,51 @@ func CreateShareInteractSet(db prefixer.Prefixer, sharingID string, codes map[st
827827
defer mu.Unlock()
828828

829829
return utils.RetryWithBackoffValue(context.Background(), shareInteractRetryOptions(), func() (*Permission, error) {
830-
existing, err := getOrRepairShareInteractPermissionsOnce(db, sharingID)
831-
if err != nil && !couchdb.IsNotFoundError(err) {
832-
return nil, err
833-
}
834-
if err == nil {
835-
merged := existing.Clone().(*Permission)
836-
merged.Type = TypeShareInteract
837-
merged.SourceID = consts.Sharings + "/" + sharingID
838-
merged.SetID(ShareInteractPermissionID(sharingID))
839-
if len(subdoc.Permissions) > 0 {
840-
// Callers pass the complete interact rule set, so replace instead of merging rules.
841-
merged.Permissions = subdoc.Permissions
842-
}
843-
if merged.Metadata == nil && subdoc.Metadata != nil {
844-
merged.Metadata = subdoc.Metadata.Clone()
845-
}
846-
if merged.Metadata != nil {
847-
merged.Metadata.ChangeUpdatedAt()
830+
existing, err := GetPermissionByIDIncludingExpired(db, ShareInteractPermissionID(sharingID))
831+
if err != nil {
832+
if !couchdb.IsNotFoundError(err) {
833+
return nil, err
848834
}
849-
if merged.Codes == nil {
850-
merged.Codes = make(map[string]string)
835+
err = couchdb.CreateNamedDoc(db, doc)
836+
if err == nil {
837+
return doc, nil
851838
}
852-
for key, code := range codes {
853-
if key == "" {
854-
continue
855-
}
856-
if existingCode, ok := merged.Codes[key]; ok && existingCode != code {
857-
logger.WithDomain(db.DomainName()).WithNamespace("permissions").
858-
Warnf("keeping existing share-interact code for %s in sharing %s", key, sharingID)
859-
continue
860-
}
861-
merged.Codes[key] = code
839+
return nil, err
840+
}
841+
842+
merged := existing.Clone().(*Permission)
843+
merged.Type = TypeShareInteract
844+
merged.SourceID = consts.Sharings + "/" + sharingID
845+
merged.SetID(ShareInteractPermissionID(sharingID))
846+
merged.ExpiresAt = nil
847+
if len(subdoc.Permissions) > 0 {
848+
// Callers pass the complete interact rule set, so replace instead of merging rules.
849+
merged.Permissions = subdoc.Permissions
850+
}
851+
if merged.Metadata == nil && subdoc.Metadata != nil {
852+
merged.Metadata = subdoc.Metadata.Clone()
853+
}
854+
if merged.Metadata != nil {
855+
merged.Metadata.ChangeUpdatedAt()
856+
}
857+
if merged.Codes == nil {
858+
merged.Codes = make(map[string]string)
859+
}
860+
for key, code := range codes {
861+
if key == "" {
862+
continue
862863
}
863-
if err := couchdb.UpdateDoc(db, merged); err != nil {
864-
return nil, err
864+
if existingCode, ok := merged.Codes[key]; ok && existingCode != code {
865+
logger.WithDomain(db.DomainName()).WithNamespace("permissions").
866+
Warnf("keeping existing share-interact code for %s in sharing %s", key, sharingID)
867+
continue
865868
}
866-
return merged, nil
869+
merged.Codes[key] = code
867870
}
868-
869-
err = couchdb.CreateNamedDoc(db, doc)
870-
if err == nil {
871-
return doc, nil
871+
if err := couchdb.UpdateDoc(db, merged); err != nil {
872+
return nil, err
872873
}
873-
return nil, err
874+
return merged, nil
874875
})
875876
}
876877

model/permission/permissions_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,92 @@ func TestCreateShareInteractSetUsesCanonicalDoc(t *testing.T) {
597597
require.Equal(t, ShareInteractPermissionID(sharingID), all[0].ID())
598598
}
599599

600+
func TestCreateShareInteractSetReactivatesExpiredCanonicalDoc(t *testing.T) {
601+
if testing.Short() {
602+
t.Skip("an instance is required for this test: test skipped due to the use of --short flag")
603+
}
604+
605+
config.UseTestFile(t)
606+
db := testPrefix(t)
607+
require.NoError(t, couchdb.ResetDB(db, consts.Permissions))
608+
609+
const sharingID = "sharing-expired-canonical-interact-permissions"
610+
rules := Set{{
611+
Title: "Shared drive",
612+
Type: consts.Files,
613+
Values: []string{"shared-drive-root"},
614+
Verbs: ALL,
615+
}}
616+
expiredAt := time.Now().Add(-time.Hour).Format(time.RFC3339)
617+
618+
err := couchdb.CreateNamedDoc(db, &Permission{
619+
PID: ShareInteractPermissionID(sharingID),
620+
Type: TypeShareInteract,
621+
Permissions: rules,
622+
Codes: map[string]string{
623+
"alice@example.test": "alice-token",
624+
},
625+
ExpiresAt: expiredAt,
626+
SourceID: consts.Sharings + "/" + sharingID,
627+
})
628+
require.NoError(t, err)
629+
630+
updated, err := CreateShareInteractSet(db, sharingID, map[string]string{
631+
"bob@example.test": "bob-token",
632+
}, Permission{Permissions: rules})
633+
require.NoError(t, err)
634+
require.Nil(t, updated.ExpiresAt)
635+
require.Equal(t, map[string]string{
636+
"alice@example.test": "alice-token",
637+
"bob@example.test": "bob-token",
638+
}, updated.Codes)
639+
640+
stored, err := GetForShareInteract(db, sharingID)
641+
require.NoError(t, err)
642+
require.Nil(t, stored.ExpiresAt)
643+
}
644+
645+
func TestCreateShareInteractSetDoesNotRepairLegacyDuplicates(t *testing.T) {
646+
if testing.Short() {
647+
t.Skip("an instance is required for this test: test skipped due to the use of --short flag")
648+
}
649+
650+
config.UseTestFile(t)
651+
db := testPrefix(t)
652+
require.NoError(t, couchdb.ResetDB(db, consts.Permissions))
653+
654+
const sharingID = "sharing-create-with-legacy-duplicate"
655+
rules := Set{{
656+
Title: "Shared drive",
657+
Type: consts.Files,
658+
Values: []string{"shared-drive-root"},
659+
Verbs: ALL,
660+
}}
661+
662+
err := couchdb.CreateDoc(db, &Permission{
663+
Type: TypeShareInteract,
664+
Permissions: rules,
665+
Codes: map[string]string{
666+
"alice@example.test": "alice-token",
667+
},
668+
SourceID: consts.Sharings + "/" + sharingID,
669+
})
670+
require.NoError(t, err)
671+
672+
created, err := CreateShareInteractSet(db, sharingID, map[string]string{
673+
"bob@example.test": "bob-token",
674+
}, Permission{Permissions: rules})
675+
require.NoError(t, err)
676+
require.Equal(t, ShareInteractPermissionID(sharingID), created.ID())
677+
require.Equal(t, map[string]string{
678+
"bob@example.test": "bob-token",
679+
}, created.Codes)
680+
681+
all, err := getShareInteractPermissions(db, sharingID)
682+
require.NoError(t, err)
683+
require.Len(t, all, 2)
684+
}
685+
600686
func TestCreateShareSetBlocklist(t *testing.T) {
601687
s := Set{Rule{Type: "io.cozy.notifications"}}
602688
subdoc := Permission{

0 commit comments

Comments
 (0)