github.com/cozy/cozy-stack@v0.0.0-20240327093429-939e4a21320e/docs/references-docs-in-vfs.md (about) 1 [Table of contents](README.md#table-of-contents) 2 3 # References of documents in the Virtual File System 4 5 ## What we want? 6 7 Cozy applications can use data from the Data System and files from the Virtual 8 File System. Of course, sometimes a link between data and files can be useful. 9 For example, the application can have an album with photos. The album will be a 10 document in CouchDB (with a title and other fields), but il will also list the 11 files to use as photos. 12 13 A direct way to do that is storing the files IDs in the album document. It's 14 simple and will work pretty well if the files are manipulated only from this 15 application. But, files are often accessed from other apps, like cozy-desktop 16 and cozy-drive. To improve the User eXperience, it should be nice to alert the 17 user when a file in an album is modified or deleted. 18 19 When a file is modified, we can offer the user the choice between keeping the 20 original version in the album, or using the new modified file. When a file is 21 moved to the trash, we can alert the user and let him/her restore the file. 22 23 Cozy-desktop, cozy-drive, and the other apps can't scan all the documents with 24 many different doctypes to find all the references to a file to detect such 25 cases. The goal of this document is to offer a way to do that, and it is called 26 _References_. 27 28 The references of a file are listed in its JSON-API representation in the 29 `references` field, within the `relationships` object of `data`. 30 31 ### Example 32 33 ```json 34 { 35 "data": { 36 "type": "io.cozy.files", 37 "id": "9152d568-7e7c-11e6-a377-37cbfb190b4b", 38 "meta": { 39 "rev": "1-0e6d5b72" 40 }, 41 "attributes": { 42 "type": "file", 43 "name": "hello.txt", 44 "md5sum": "ODZmYjI2OWQxOTBkMmM4NQo=", 45 "created_at": "2016-09-19T12:38:04Z", 46 "updated_at": "2016-09-19T12:38:04Z", 47 "tags": [], 48 "size": 12, 49 "executable": false, 50 "class": "document", 51 "mime": "text/plain" 52 }, 53 "relationships": { 54 "parent": { 55 "links": { 56 "related": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 57 }, 58 "data": { 59 "type": "io.cozy.files", 60 "id": "fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81" 61 } 62 }, 63 "referenced_by": { 64 "links": { 65 "self": "/files/fce1a6c0-dfc5-11e5-8d1a-1f854d4aaf81/relationships/references" 66 }, 67 "data": [ 68 { 69 "type": "io.cozy.playlists", 70 "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4" 71 } 72 ] 73 } 74 }, 75 "links": { 76 "self": "/files/9152d568-7e7c-11e6-a377-37cbfb190b4b" 77 } 78 } 79 } 80 ``` 81 82 ## Routes 83 84 ### POST /files/:file-id/relationships/referenced_by 85 86 Add on a file one or more references to documents 87 88 #### Request 89 90 ```http 91 POST /files/9152d568-7e7c-11e6-a377-37cbfb190b4b/relationships/referenced_by HTTP/1.1 92 Content-Type: application/vnd.api+json 93 Accept: application/vnd.api+json 94 ``` 95 96 ```json 97 { 98 "data": [ 99 { 100 "type": "io.cozy.playlists", 101 "id": "f2625cc0-e2d6-11e6-a0d5-cfbbfb141af0" 102 } 103 ] 104 } 105 ``` 106 107 #### Response 108 109 ```http 110 HTTP/1.1 200 OK 111 Content-Type: application/vnd.api+json 112 ``` 113 114 ```json 115 { 116 "meta": { 117 "rev": "2-de8d0ba2", 118 "count": 2 119 }, 120 "data": [ 121 { 122 "type": "io.cozy.playlists", 123 "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4" 124 }, 125 { 126 "type": "io.cozy.playlists", 127 "id": "f2625cc0-e2d6-11e6-a0d5-cfbbfb141af0" 128 } 129 ] 130 } 131 ``` 132 133 ### DELETE /files/:file-id/relationships/referenced_by 134 135 Remove one or more references to documents on a file 136 137 #### Request 138 139 ```http 140 DELETE /files/9152d568-7e7c-11e6-a377-37cbfb190b4b/relationships/referenced_by HTTP/1.1 141 Content-Type: application/vnd.api+json 142 Accept: application/vnd.api+json 143 ``` 144 145 ```json 146 { 147 "data": [ 148 { 149 "type": "io.cozy.playlists", 150 "id": "f2625cc0-e2d6-11e6-a0d5-cfbbfb141af0" 151 } 152 ] 153 } 154 ``` 155 156 #### Response 157 158 ```http 159 HTTP/1.1 200 OK 160 Content-Type: application/vnd.api+json 161 ``` 162 163 ```json 164 { 165 "meta": { 166 "rev": "3-7ab812c0", 167 "count": 1 168 }, 169 "data": [ 170 { 171 "type": "io.cozy.playlists", 172 "id": "94375086-e2e2-11e6-81b9-5bc0b9dd4aa4" 173 } 174 ] 175 } 176 ``` 177 178 ### GET /data/:type/:doc-id/relationships/references 179 180 Returns all the files id associated to an album or playlist. 181 182 Contents is paginated following [jsonapi conventions](http-api.md#pagination). 183 The default limit is 100 entries. The maximal number of entries per page is 184 1000. 185 186 It's also possible to sort the files by their datetime (for photos) with the 187 `sort` query parameter: `?sort=datetime`. 188 189 #### Request 190 191 ```http 192 GET /data/io.cozy.playlists/e9308dc2-e2e3-11e6-b685-fb88662613d4/relationships/references HTTP/1.1 193 Content-Type: application/vnd.api+json 194 Accept: application/vnd.api+json 195 ``` 196 197 #### Response 198 199 ```http 200 HTTP/1.1 200 OK 201 Content-Type: application/vnd.api+json 202 ``` 203 204 ```json 205 { 206 "data": [ 207 { 208 "type": "io.cozy.files", 209 "id": "417c4e58-e2e4-11e6-b7dc-2b68ed7b77f4" 210 }, 211 { 212 "type": "io.cozy.files", 213 "id": "4504f55c-e2e4-11e6-88f2-d77aeecab549" 214 }, 215 { 216 "type": "io.cozy.files", 217 "id": "4587727a-e2e4-11e6-bfe9-ef1be7df7f26" 218 }, 219 { 220 "type": "io.cozy.files", 221 "id": "45d591d0-e2e4-11e6-ab9a-ff3b218e31cc" 222 } 223 ] 224 } 225 ``` 226 227 ### POST /data/:type/:doc-id/relationships/references 228 229 When creating an album or a playlist, it's tedious to add the references to it 230 for each file individually. This route allows to make it in bulk. 231 232 #### Request 233 234 ```http 235 POST /data/io.cozy.playlists/e9308dc2-e2e3-11e6-b685-fb88662613d4/relationships/references HTTP/1.1 236 Content-Type: application/vnd.api+json 237 Accept: application/vnd.api+json 238 ``` 239 240 ```json 241 { 242 "data": [ 243 { 244 "type": "io.cozy.files", 245 "id": "417c4e58-e2e4-11e6-b7dc-2b68ed7b77f4" 246 }, 247 { 248 "type": "io.cozy.files", 249 "id": "4504f55c-e2e4-11e6-88f2-d77aeecab549" 250 }, 251 { 252 "type": "io.cozy.files", 253 "id": "4587727a-e2e4-11e6-bfe9-ef1be7df7f26" 254 }, 255 { 256 "type": "io.cozy.files", 257 "id": "45d591d0-e2e4-11e6-ab9a-ff3b218e31cc" 258 } 259 ] 260 } 261 ``` 262 263 #### Response 264 265 ```http 266 HTTP/1.1 204 No Content 267 Content-Type: application/vnd.api+json 268 ``` 269 270 ### DELETE /data/:type/:doc-id/relationships/references 271 272 This bulk deletion of references on many files can be useful when an album or 273 playlist is deleted. 274 275 #### Request 276 277 ```http 278 DELETE /data/io.cozy.playlists/e9308dc2-e2e3-11e6-b685-fb88662613d4/relationships/references HTTP/1.1 279 Content-Type: application/vnd.api+json 280 Accept: application/vnd.api+json 281 ``` 282 283 ```json 284 { 285 "data": [ 286 { 287 "type": "io.cozy.files", 288 "id": "417c4e58-e2e4-11e6-b7dc-2b68ed7b77f4" 289 }, 290 { 291 "type": "io.cozy.files", 292 "id": "4504f55c-e2e4-11e6-88f2-d77aeecab549" 293 }, 294 { 295 "type": "io.cozy.files", 296 "id": "4587727a-e2e4-11e6-bfe9-ef1be7df7f26" 297 }, 298 { 299 "type": "io.cozy.files", 300 "id": "45d591d0-e2e4-11e6-ab9a-ff3b218e31cc" 301 } 302 ] 303 } 304 ``` 305 306 #### Response 307 308 ```http 309 HTTP/1.1 204 No Content 310 Content-Type: application/vnd.api+json 311 ``` 312 313 ## Usage 314 315 ### Modification of a referenced file 316 317 Before an application updates a file, it can check if the file has some 318 references. If it is the case, it may offer to the user two choices: 319 320 - update the file with the new version (the albums and playlists will use the 321 new version) 322 - save the new version as a new file and preserve the old file (the old file 323 may be moved to a `originals` directory). 324 325 ### Moving a referenced file to the trash 326 327 Before an application moves a file to the trash, if the file has some 328 references, it should ask the user if they really want to trash the file. And 329 it should also removes the references before trashing the file. 330 331 ## Implementation 332 333 The references are persisted in the `io.cozy.files` documents in CouchDB. A 334 mango index is used to fetch all the files that are associated to a given 335 document (for `GET /data/:type/:doc-id/relationships/references`). 336 337 For request to update or move to trash a file, it is easy to fetch its CouchDB 338 document to see if it has a reference. But it is more difficult when moving a 339 folder to trash. To do that, we need two requests to fetch the number of 340 references in a folder. 341 342 1/ Get all descendant folders from a given folder, with a CouchDB View: 343 344 ```js 345 map = function(doc) { 346 if (doc.type === "folder") emit(doc.path); 347 }; 348 query = { 349 startkey: parent_folder_path + "/", 350 endkey: parent_folder_path + "/\uFFFF" 351 }; 352 ``` 353 354 2/ Get the total number of "referenced" file for this folders list, with a 355 map/reduce CouchDB view: 356 357 ```js 358 map = function(doc) { if(doc.referenced != null) emit(doc.parentID) } 359 reduce = count 360 query = {keys: [list from above]} 361 ```