github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/web/files/referencedby.go (about) 1 package files 2 3 import ( 4 "net/http" 5 6 "github.com/cozy/cozy-stack/model/instance" 7 "github.com/cozy/cozy-stack/model/permission" 8 "github.com/cozy/cozy-stack/model/vfs" 9 "github.com/cozy/cozy-stack/pkg/config/config" 10 "github.com/cozy/cozy-stack/pkg/couchdb" 11 "github.com/cozy/cozy-stack/pkg/jsonapi" 12 "github.com/cozy/cozy-stack/web/middlewares" 13 "github.com/labstack/echo/v4" 14 ) 15 16 func lockVFS(inst *instance.Instance) func() { 17 mu := config.Lock().ReadWrite(inst, "vfs") 18 _ = mu.Lock() 19 return mu.Unlock 20 } 21 22 // AddReferencedHandler is the echo.handler for adding referenced_by to 23 // a file 24 // POST /files/:file-id/relationships/referenced_by 25 func AddReferencedHandler(c echo.Context) error { 26 instance := middlewares.GetInstance(c) 27 28 fileID := c.Param("file-id") 29 fs := instance.VFS() 30 dir, file, err := fs.DirOrFileByID(fileID) 31 if err != nil { 32 return WrapVfsError(err) 33 } 34 35 err = checkPerm(c, permission.PATCH, dir, file) 36 if err != nil { 37 return err 38 } 39 40 references, err := jsonapi.BindRelations(c.Request()) 41 if err != nil { 42 return WrapVfsError(err) 43 } 44 45 var oldFile *vfs.FileDoc 46 if file != nil { 47 oldFile = file.Clone().(*vfs.FileDoc) 48 // Ensure the fullpaths are filled to realtime 49 _, _ = file.Path(fs) 50 _, _ = oldFile.Path(fs) 51 } 52 defer lockVFS(instance)() 53 54 var newRev string 55 var refs []couchdb.DocReference 56 if dir != nil { 57 dir.AddReferencedBy(references...) 58 updateDirCozyMetadata(c, dir) 59 err = couchdb.UpdateDoc(instance, dir) 60 newRev = dir.Rev() 61 refs = dir.ReferencedBy 62 } else { 63 file.AddReferencedBy(references...) 64 updateFileCozyMetadata(c, file, false) 65 err = couchdb.UpdateDocWithOld(instance, file, oldFile) 66 newRev = file.Rev() 67 refs = file.ReferencedBy 68 } 69 70 if err != nil { 71 return WrapVfsError(err) 72 } 73 74 count := len(refs) 75 meta := jsonapi.Meta{Rev: newRev, Count: &count} 76 77 return jsonapi.DataRelations(c, http.StatusOK, refs, &meta, nil, nil) 78 } 79 80 // RemoveReferencedHandler is the echo.handler for removing referenced_by to 81 // a file 82 // DELETE /files/:file-id/relationships/referenced_by 83 func RemoveReferencedHandler(c echo.Context) error { 84 instance := middlewares.GetInstance(c) 85 86 fileID := c.Param("file-id") 87 fs := instance.VFS() 88 dir, file, err := fs.DirOrFileByID(fileID) 89 if err != nil { 90 return WrapVfsError(err) 91 } 92 93 err = checkPerm(c, permission.DELETE, nil, file) 94 if err != nil { 95 return err 96 } 97 98 references, err := jsonapi.BindRelations(c.Request()) 99 if err != nil { 100 return WrapVfsError(err) 101 } 102 103 var oldFile *vfs.FileDoc 104 if file != nil { 105 oldFile = file.Clone().(*vfs.FileDoc) 106 // Ensure the fullpaths are filled to realtime 107 _, _ = file.Path(fs) 108 _, _ = oldFile.Path(fs) 109 } 110 defer lockVFS(instance)() 111 112 var newRev string 113 var refs []couchdb.DocReference 114 if dir != nil { 115 dir.RemoveReferencedBy(references...) 116 updateDirCozyMetadata(c, dir) 117 err = couchdb.UpdateDoc(instance, dir) 118 newRev = dir.Rev() 119 refs = dir.ReferencedBy 120 } else { 121 file.RemoveReferencedBy(references...) 122 updateFileCozyMetadata(c, file, false) 123 err = couchdb.UpdateDocWithOld(instance, file, oldFile) 124 newRev = file.Rev() 125 refs = file.ReferencedBy 126 } 127 128 if err != nil { 129 return WrapVfsError(err) 130 } 131 132 count := len(refs) 133 meta := jsonapi.Meta{Rev: newRev, Count: &count} 134 135 return jsonapi.DataRelations(c, http.StatusOK, refs, &meta, nil, nil) 136 }