Skip to content

Commit

Permalink
Revert "Remove an old hack for migration path on references" (#4238)
Browse files Browse the repository at this point in the history
This reverts commit 21e94d2.

The hack is still needed, as some Cozy instances have references in the
bogus format in production.
  • Loading branch information
nono committed Nov 27, 2023
2 parents 11860ab + 0963cb3 commit 0fe7813
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 1 deletion.
59 changes: 58 additions & 1 deletion web/data/references_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestReferences(t *testing.T) {
},
})

t.Run("ListNotSynchronizedOn", func(t *testing.T) {
t.Run("ListReferencesHandler", func(t *testing.T) {
e := testutils.CreateTestClient(t, ts.URL)

// Make doc
Expand Down Expand Up @@ -230,6 +230,41 @@ func TestReferences(t *testing.T) {
obj.Value("data").Array().Length().Equal(1)
obj.Path("$.data[0].id").Equal(fdoc.ID())

// Add dummy references on io.cozy.apps%2ffoobaz and io.cozy.apps%2Ffooqux
foobazRef := couchdb.DocReference{
ID: "io.cozy.apps%2ffoobaz",
Type: Type,
}
fooquxRef := couchdb.DocReference{
ID: "io.cozy.apps%2Ffooqux",
Type: Type,
}
fdoc.ReferencedBy = append(fdoc.ReferencedBy, foobazRef, fooquxRef)
err = couchdb.UpdateDoc(testInstance, fdoc)
assert.NoError(t, err)

// Check that we can find the reference with %2f
obj = e.GET("/data/"+Type+"/io.cozy.apps%2ffoobar/relationships/references").
WithHeader("Authorization", "Bearer "+token).
Expect().Status(200).
JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}).
Object()

obj.Path("$.meta.count").Equal(1)
obj.Value("data").Array().Length().Equal(1)
obj.Path("$.data[0].id").Equal(fdoc.ID())

// Check that we can find the reference with %2F
obj = e.GET("/data/"+Type+"/io.cozy.apps%2Ffoobar/relationships/references").
WithHeader("Authorization", "Bearer "+token).
Expect().Status(200).
JSON(httpexpect.ContentOpts{MediaType: "application/vnd.api+json"}).
Object()

obj.Path("$.meta.count").Equal(1)
obj.Value("data").Array().Length().Equal(1)
obj.Path("$.data[0].id").Equal(fdoc.ID())

// Remove the reference with a /
e.DELETE("/data/"+Type+"/io.cozy.apps%2Ffoobar/relationships/references").
WithHeader("Authorization", "Bearer "+token).
Expand All @@ -241,6 +276,28 @@ func TestReferences(t *testing.T) {
}`)).
Expect().Status(204)

// Remove the reference with a %2f
e.DELETE("/data/"+Type+"/io.cozy.apps%2ffoobaz/relationships/references").
WithHeader("Authorization", "Bearer "+token).
WithHeader("Content-Type", "application/vnd.api+json").
WithBytes([]byte(`{
"data": [
{"id": "` + fdoc.ID() + `", "type": "` + consts.Files + `"}
]
}`)).
Expect().Status(204)

// Remove the reference with a %2F
e.DELETE("/data/"+Type+"/io.cozy.apps%2Ffooqux/relationships/references").
WithHeader("Authorization", "Bearer "+token).
WithHeader("Content-Type", "application/vnd.api+json").
WithBytes([]byte(`{
"data": [
{"id": "` + fdoc.ID() + `", "type": "` + consts.Files + `"}
]
}`)).
Expect().Status(204)

// Check that all the references have been removed
fdoc2, err := testInstance.VFS().FileByID(fdoc.ID())
assert.NoError(t, err)
Expand Down
28 changes: 28 additions & 0 deletions web/files/references.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ func ListReferencesHandler(c echo.Context) error {
if len(resCount.Rows) > 0 {
count = int(resCount.Rows[0].Value.(float64))
}

// XXX Some references can contain `%2f` instead of `/` in the id (legacy),
// and to preserve compatibility, we try to find those documents if no
// documents with the correct reference are found.
if count == 0 && strings.Contains(id, "/") {
key[1] = c.Param("docid")
err = couchdb.ExecView(instance, couchdb.FilesReferencedByView, reqCount, &resCount)
if err == nil && len(resCount.Rows) > 0 {
count = int(resCount.Rows[0].Value.(float64))
}
}
meta := &jsonapi.Meta{Count: &count}

sort := c.QueryParam("sort")
Expand Down Expand Up @@ -242,6 +253,17 @@ func RemoveReferencesHandler(c echo.Context) error {
ID: id,
}

// XXX References with an ID that contains a / could have it encoded as %2F
// (legacy). We delete the references for both versions to preserve
// compatibility.
var altRef *couchdb.DocReference
if strings.Contains(id, "/") {
altRef = &couchdb.DocReference{
Type: doctype,
ID: c.Param("docid"),
}
}

if err := middlewares.AllowTypeAndID(c, permission.DELETE, doctype, id); err != nil {
if middlewares.AllowWholeType(c, permission.PATCH, consts.Files) != nil {
return err
Expand All @@ -259,12 +281,18 @@ func RemoveReferencesHandler(c echo.Context) error {
if dir != nil {
oldDir := dir.Clone()
dir.RemoveReferencedBy(docRef)
if altRef != nil {
dir.RemoveReferencedBy(*altRef)
}
updateDirCozyMetadata(c, dir)
docs[i] = dir
oldDocs[i] = oldDir
} else {
oldFile := file.Clone().(*vfs.FileDoc)
file.RemoveReferencedBy(docRef)
if altRef != nil {
file.RemoveReferencedBy(*altRef)
}
updateFileCozyMetadata(c, file, false)
_, _ = file.Path(fs) // Ensure the fullpath is filled to realtime
_, _ = oldFile.Path(fs) // Ensure the fullpath is filled to realtime
Expand Down

0 comments on commit 0fe7813

Please sign in to comment.