github.com/cs3org/reva/v2@v2.27.7/pkg/storage/fs/owncloudsql/filecache/filecache_test.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package filecache_test 20 21 import ( 22 "context" 23 "database/sql" 24 "os" 25 "strconv" 26 27 _ "github.com/mattn/go-sqlite3" 28 29 "github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/filecache" 30 31 . "github.com/onsi/ginkgo/v2" 32 . "github.com/onsi/gomega" 33 ) 34 35 var _ = Describe("Filecache", func() { 36 var ( 37 cache *filecache.Cache 38 testDbFile *os.File 39 sqldb *sql.DB 40 ctx context.Context 41 ) 42 43 BeforeEach(func() { 44 ctx = context.Background() 45 46 var err error 47 testDbFile, err = os.CreateTemp("", "example") 48 Expect(err).ToNot(HaveOccurred()) 49 50 dbData, err := os.ReadFile("test.db") 51 Expect(err).ToNot(HaveOccurred()) 52 53 _, err = testDbFile.Write(dbData) 54 Expect(err).ToNot(HaveOccurred()) 55 err = testDbFile.Close() 56 Expect(err).ToNot(HaveOccurred()) 57 58 sqldb, err = sql.Open("sqlite3", testDbFile.Name()) 59 Expect(err).ToNot(HaveOccurred()) 60 61 cache, err = filecache.New("sqlite3", sqldb) 62 Expect(err).ToNot(HaveOccurred()) 63 }) 64 65 AfterEach(func() { 66 os.Remove(testDbFile.Name()) 67 }) 68 69 Describe("ListStorages", func() { 70 It("returns all storages", func() { 71 storages, err := cache.ListStorages(ctx, false) 72 Expect(err).ToNot(HaveOccurred()) 73 Expect(len(storages)).To(Equal(2)) 74 ids := []string{} 75 numericIDs := []int{} 76 for _, s := range storages { 77 ids = append(ids, s.ID) 78 numericIDs = append(numericIDs, s.NumericID) 79 } 80 Expect(numericIDs).To(ConsistOf([]int{1, 2})) 81 Expect(ids).To(ConsistOf([]string{"home::admin", "local::/mnt/data/files/"})) 82 }) 83 84 It("returns all home storages", func() { 85 storages, err := cache.ListStorages(ctx, true) 86 Expect(err).ToNot(HaveOccurred()) 87 Expect(len(storages)).To(Equal(1)) 88 Expect(storages[0].ID).To(Equal("home::admin")) 89 Expect(storages[0].NumericID).To(Equal(1)) 90 }) 91 }) 92 93 Describe("GetStorage", func() { 94 It("returns an error when the id is invalid", func() { 95 s, err := cache.GetStorage(ctx, "foo") 96 Expect(err).To(HaveOccurred()) 97 Expect(s).To(BeNil()) 98 }) 99 100 It("returns an error when the id doesn't exist", func() { 101 s, err := cache.GetStorage(ctx, 100) 102 Expect(err).To(HaveOccurred()) 103 Expect(s).To(BeNil()) 104 }) 105 106 It("returns the storage", func() { 107 s, err := cache.GetStorage(ctx, 1) 108 Expect(err).ToNot(HaveOccurred()) 109 Expect(s.ID).To(Equal("home::admin")) 110 Expect(s.NumericID).To(Equal(1)) 111 }) 112 113 It("takes string ids", func() { 114 s, err := cache.GetStorage(ctx, "1") 115 Expect(err).ToNot(HaveOccurred()) 116 Expect(s.ID).To(Equal("home::admin")) 117 Expect(s.NumericID).To(Equal(1)) 118 }) 119 }) 120 121 Describe("GetNumericStorageID", func() { 122 It("returns the proper storage id", func() { 123 nid, err := cache.GetNumericStorageID(ctx, "home::admin") 124 Expect(err).ToNot(HaveOccurred()) 125 Expect(nid).To(Equal(1)) 126 }) 127 }) 128 129 Describe("GetStorageOwner", func() { 130 It("returns the owner", func() { 131 owner, err := cache.GetStorageOwner(ctx, "1") 132 Expect(err).ToNot(HaveOccurred()) 133 Expect(owner).To(Equal("admin")) 134 }) 135 }) 136 137 Describe("CreateStorage", func() { 138 It("creates the storage and a root item", func() { 139 id, err := cache.CreateStorage(ctx, "bar") 140 Expect(err).ToNot(HaveOccurred()) 141 Expect(id > 0).To(BeTrue()) 142 143 owner, err := cache.GetStorageOwner(ctx, id) 144 Expect(err).ToNot(HaveOccurred()) 145 Expect(owner).To(Equal("bar")) 146 147 file, err := cache.Get(ctx, 1, "") 148 Expect(err).ToNot(HaveOccurred()) 149 Expect(file).ToNot(BeNil()) 150 }) 151 }) 152 Describe("GetStorageOwnerByFileID", func() { 153 It("returns the owner", func() { 154 owner, err := cache.GetStorageOwnerByFileID(ctx, "10") 155 Expect(err).ToNot(HaveOccurred()) 156 Expect(owner).To(Equal("admin")) 157 }) 158 }) 159 160 Describe("Get", func() { 161 It("gets existing files", func() { 162 path := "files/Photos/Portugal.jpg" 163 file, err := cache.Get(ctx, 1, path) 164 Expect(err).ToNot(HaveOccurred()) 165 Expect(file).ToNot(BeNil()) 166 Expect(file.ID).To(Equal(10)) 167 Expect(file.Storage).To(Equal(1)) 168 Expect(file.Path).To(Equal(path)) 169 Expect(file.Parent).To(Equal(9)) 170 Expect(file.MimeType).To(Equal(6)) 171 Expect(file.MimePart).To(Equal(5)) 172 Expect(file.MimeTypeString).To(Equal("image/jpeg")) 173 Expect(file.Size).To(Equal(243733)) 174 Expect(file.MTime).To(Equal(1619007009)) 175 Expect(file.StorageMTime).To(Equal(1619007009)) 176 Expect(file.Encrypted).To(BeFalse()) 177 Expect(file.UnencryptedSize).To(Equal(0)) 178 Expect(file.Name).To(Equal("Portugal.jpg")) 179 Expect(file.Etag).To(Equal("13cf411aefccd7183d3b117ccd0ac5f8")) 180 Expect(file.Checksum).To(Equal("SHA1:872adcabcb4e06bea6265200c0d71b12defe2df1 MD5:01b38c622feac31652d738a94e15e86b ADLER32:6959358d")) 181 }) 182 }) 183 184 Describe("List", func() { 185 It("lists all entries", func() { 186 list, err := cache.List(ctx, 1, "") 187 Expect(err).ToNot(HaveOccurred()) 188 Expect(len(list)).To(Equal(3)) 189 }) 190 191 It("filters", func() { 192 list, err := cache.List(ctx, 1, "files_trashbin/") 193 Expect(err).ToNot(HaveOccurred()) 194 Expect(len(list)).To(Equal(3)) 195 }) 196 197 It("filters deep", func() { 198 list, err := cache.List(ctx, 1, "files/Photos/") 199 Expect(err).ToNot(HaveOccurred()) 200 Expect(len(list)).To(Equal(3)) 201 }) 202 }) 203 204 Describe("Path", func() { 205 It("returns the path", func() { 206 path, err := cache.Path(ctx, 10) 207 Expect(err).ToNot(HaveOccurred()) 208 Expect(path).To(Equal("files/Photos/Portugal.jpg")) 209 }) 210 211 It("returns the path when given a string id", func() { 212 path, err := cache.Path(ctx, "10") 213 Expect(err).ToNot(HaveOccurred()) 214 Expect(path).To(Equal("files/Photos/Portugal.jpg")) 215 }) 216 }) 217 218 Describe("InsertOrUpdate", func() { 219 Context("when inserting a new recored", func() { 220 It("checks for required fields", func() { 221 data := map[string]interface{}{ 222 "mimetype": "httpd/unix-directory", 223 "etag": "abcdefg", 224 } 225 _, err := cache.InsertOrUpdate(ctx, 3, data, false) 226 Expect(err).To(MatchError("missing required data")) 227 228 data = map[string]interface{}{ 229 "path": "files/Photos/foo.jpg", 230 "etag": "abcdefg", 231 } 232 _, err = cache.InsertOrUpdate(ctx, 3, data, false) 233 Expect(err).To(MatchError("missing required data")) 234 235 data = map[string]interface{}{ 236 "path": "files/Photos/foo.jpg", 237 "mimetype": "httpd/unix-directory", 238 } 239 _, err = cache.InsertOrUpdate(ctx, 3, data, false) 240 Expect(err).To(MatchError("missing required data")) 241 }) 242 243 It("inserts a new minimal entry", func() { 244 data := map[string]interface{}{ 245 "path": "files/Photos/foo.jpg", 246 "mimetype": "httpd/unix-directory", 247 "etag": "abcdefg", 248 } 249 id, err := cache.InsertOrUpdate(ctx, 1, data, false) 250 Expect(err).ToNot(HaveOccurred()) 251 Expect(id).To(Equal(18)) 252 253 entry, err := cache.Get(ctx, 1, "files/Photos/foo.jpg") 254 Expect(err).ToNot(HaveOccurred()) 255 Expect(entry.Path).To(Equal("files/Photos/foo.jpg")) 256 Expect(entry.Name).To(Equal("foo.jpg")) 257 Expect(entry.MimeType).To(Equal(2)) 258 Expect(entry.MimePart).To(Equal(1)) 259 Expect(entry.Etag).To(Equal("abcdefg")) 260 }) 261 262 It("inserts a complete entry", func() { 263 data := map[string]interface{}{ 264 "path": "files/Photos/foo.jpg", 265 "checksum": "SHA1: abcdefg", 266 "etag": "abcdefg", 267 "size": 1234, 268 "mimetype": "image/jpeg", 269 "mtime": 1617702482, 270 "storage_mtime": 1617702483, 271 "encrypted": true, 272 "unencrypted_size": 2000, 273 } 274 _, err := cache.InsertOrUpdate(ctx, 1, data, false) 275 Expect(err).ToNot(HaveOccurred()) 276 277 entry, err := cache.Get(ctx, 1, "files/Photos/foo.jpg") 278 Expect(err).ToNot(HaveOccurred()) 279 Expect(entry.Path).To(Equal("files/Photos/foo.jpg")) 280 Expect(entry.Name).To(Equal("foo.jpg")) 281 Expect(entry.Checksum).To(Equal("SHA1: abcdefg")) 282 Expect(entry.Etag).To(Equal("abcdefg")) 283 Expect(entry.Size).To(Equal(1234)) 284 Expect(entry.MimeType).To(Equal(6)) 285 Expect(entry.MimePart).To(Equal(5)) 286 Expect(entry.MTime).To(Equal(1617702482)) 287 Expect(entry.StorageMTime).To(Equal(1617702483)) 288 Expect(entry.Encrypted).To(BeTrue()) 289 Expect(entry.UnencryptedSize).To(Equal(2000)) 290 }) 291 292 It("sets the parent", func() { 293 data := map[string]interface{}{ 294 "path": "files/Photos/foo.jpg", 295 "mimetype": "httpd/unix-directory", 296 "etag": "abcdefg", 297 } 298 299 _, err := cache.InsertOrUpdate(ctx, 1, data, false) 300 Expect(err).ToNot(HaveOccurred()) 301 302 entry, err := cache.Get(ctx, 1, "files/Photos/foo.jpg") 303 Expect(err).ToNot(HaveOccurred()) 304 Expect(entry.Parent).To(Equal(9)) 305 }) 306 307 It("sets the mtime storage_mtime if not set", func() { 308 data := map[string]interface{}{ 309 "path": "files/Photos/foo.jpg", 310 "mimetype": "httpd/unix-directory", 311 "etag": "abcdefg", 312 "storage_mtime": 1617702483, 313 } 314 315 _, err := cache.InsertOrUpdate(ctx, 1, data, false) 316 Expect(err).ToNot(HaveOccurred()) 317 318 entry, err := cache.Get(ctx, 1, "files/Photos/foo.jpg") 319 Expect(err).ToNot(HaveOccurred()) 320 Expect(entry.MTime).To(Equal(1617702483)) 321 }) 322 323 It("sets the mimetype and part ids from the mimetype string", func() { 324 data := map[string]interface{}{ 325 "path": "files/Photos/foo.jpg", 326 "checksum": "SHA1: abcdefg", 327 "etag": "abcdefg", 328 "mimetype": "image/jpeg", 329 } 330 331 _, err := cache.InsertOrUpdate(ctx, 1, data, false) 332 Expect(err).ToNot(HaveOccurred()) 333 334 entry, err := cache.Get(ctx, 1, "files/Photos/foo.jpg") 335 Expect(err).ToNot(HaveOccurred()) 336 Expect(entry.MimeType).To(Equal(6)) 337 Expect(entry.MimePart).To(Equal(5)) 338 }) 339 340 It("adds unknown mimetypes to the database", func() { 341 data := map[string]interface{}{ 342 "path": "files/Photos/foo.tiff", 343 "checksum": "SHA1: abcdefg", 344 "etag": "abcdefg", 345 "mimetype": "image/tiff", 346 } 347 348 _, err := cache.InsertOrUpdate(ctx, 1, data, false) 349 Expect(err).ToNot(HaveOccurred()) 350 351 entry, err := cache.Get(ctx, 1, "files/Photos/foo.tiff") 352 Expect(err).ToNot(HaveOccurred()) 353 Expect(entry.MimeType).To(Equal(9)) 354 Expect(entry.MimePart).To(Equal(5)) 355 }) 356 357 It("does not add a . as the name for root entries", func() { 358 data := map[string]interface{}{ 359 "path": "", 360 "checksum": "SHA1: abcdefg", 361 "etag": "abcdefg", 362 "mimetype": "image/tiff", 363 } 364 365 _, err := cache.InsertOrUpdate(ctx, 1, data, false) 366 Expect(err).ToNot(HaveOccurred()) 367 368 file, err := cache.Get(ctx, 1, "") 369 Expect(err).ToNot(HaveOccurred()) 370 Expect(file).ToNot(BeNil()) 371 Expect(file.Name).To(Equal("")) 372 }) 373 }) 374 375 Context("when updating an existing record", func() { 376 var ( 377 data map[string]interface{} 378 ) 379 380 BeforeEach(func() { 381 data = map[string]interface{}{ 382 "path": "files/Photos/foo.jpg", 383 "mimetype": "httpd/unix-directory", 384 "etag": "abcdefg", 385 } 386 _, err := cache.InsertOrUpdate(ctx, 1, data, false) 387 Expect(err).ToNot(HaveOccurred()) 388 }) 389 390 It("updates the record", func() { 391 recordBefore, err := cache.Get(ctx, 1, data["path"].(string)) 392 Expect(err).ToNot(HaveOccurred()) 393 394 data["etag"] = "12345" 395 id, err := cache.InsertOrUpdate(ctx, 1, data, false) 396 Expect(err).ToNot(HaveOccurred()) 397 Expect(id).To(Equal(recordBefore.ID)) 398 399 recordAfter, err := cache.Get(ctx, 1, data["path"].(string)) 400 Expect(err).ToNot(HaveOccurred()) 401 402 Expect(recordBefore.Etag).To(Equal("abcdefg")) 403 Expect(recordAfter.Etag).To(Equal("12345")) 404 }) 405 406 }) 407 }) 408 409 Describe("Move", func() { 410 It("moves a file", func() { 411 err := cache.Move(ctx, 1, "files/Photos/Portugal.jpg", "files/Documents/Portugal.jpg") 412 Expect(err).ToNot(HaveOccurred()) 413 414 _, err = cache.Get(ctx, 1, "files/Photos/Portugal.jpg") 415 Expect(err).To(HaveOccurred()) 416 417 newEntry, err := cache.Get(ctx, 1, "files/Documents/Portugal.jpg") 418 Expect(err).ToNot(HaveOccurred()) 419 Expect(newEntry.Path).To(Equal("files/Documents/Portugal.jpg")) 420 }) 421 422 It("moves a file while changing its name", func() { 423 err := cache.Move(ctx, 1, "files/Photos/Portugal.jpg", "files/Documents/Spain.jpg") 424 Expect(err).ToNot(HaveOccurred()) 425 426 _, err = cache.Get(ctx, 1, "files/Photos/Portugal.jpg") 427 Expect(err).To(HaveOccurred()) 428 429 newEntry, err := cache.Get(ctx, 1, "files/Documents/Spain.jpg") 430 Expect(err).ToNot(HaveOccurred()) 431 Expect(newEntry.Path).To(Equal("files/Documents/Spain.jpg")) 432 Expect(newEntry.Name).To(Equal("Spain.jpg")) 433 }) 434 435 It("moves a directory", func() { 436 err := cache.Move(ctx, 1, "files/Photos", "files/Foo") 437 Expect(err).ToNot(HaveOccurred()) 438 439 _, err = cache.Get(ctx, 1, "files/Photos") 440 Expect(err).To(HaveOccurred()) 441 442 _, err = cache.Get(ctx, 1, "files/Photos/Portugal.jpg") 443 Expect(err).To(HaveOccurred()) 444 newEntry, err := cache.Get(ctx, 1, "files/Foo/Portugal.jpg") 445 Expect(err).ToNot(HaveOccurred()) 446 Expect(newEntry.Path).To(Equal("files/Foo/Portugal.jpg")) 447 }) 448 }) 449 450 Describe("SetEtag", func() { 451 It("updates the etag", func() { 452 entry, err := cache.Get(ctx, 1, "files/Photos/Portugal.jpg") 453 Expect(err).ToNot(HaveOccurred()) 454 Expect(entry.Etag).To(Equal("13cf411aefccd7183d3b117ccd0ac5f8")) 455 456 err = cache.SetEtag(ctx, 1, "files/Photos/Portugal.jpg", "foo") 457 Expect(err).ToNot(HaveOccurred()) 458 459 entry, err = cache.Get(ctx, 1, "files/Photos/Portugal.jpg") 460 Expect(err).ToNot(HaveOccurred()) 461 Expect(entry.Etag).To(Equal("foo")) 462 }) 463 }) 464 465 Context("trash", func() { 466 var ( 467 filePath = "files/Photos/Portugal.jpg" 468 469 data = map[string]interface{}{ 470 "path": "files_trashbin/files/Photos", 471 "mimetype": "httpd/unix-directory", 472 "etag": "abcdefg", 473 } 474 trashPathBase = "Portugal.jpg" 475 trashPathTimestamp = 1619007109 476 trashPath = "files_trashbin/files/" + trashPathBase + ".d" + strconv.Itoa(trashPathTimestamp) 477 ) 478 479 BeforeEach(func() { 480 _, err := cache.InsertOrUpdate(ctx, 1, data, false) 481 Expect(err).ToNot(HaveOccurred()) 482 }) 483 484 Describe("Delete", func() { 485 It("deletes an item", func() { 486 err := cache.Delete(ctx, 1, "admin", filePath, trashPath) 487 Expect(err).ToNot(HaveOccurred()) 488 489 _, err = cache.Get(ctx, 1, "files/Photos/Portugal.jpg") 490 Expect(err).To(HaveOccurred()) 491 _, err = cache.Get(ctx, 1, "files_trashbin/files/Portugal.jpg.d1619007109") 492 Expect(err).ToNot(HaveOccurred()) 493 }) 494 495 It("creates an entry in the trash table", func() { 496 _, err := cache.GetRecycleItem(ctx, "admin", trashPathBase, trashPathTimestamp) 497 Expect(err).To(HaveOccurred()) 498 499 err = cache.Delete(ctx, 1, "admin", filePath, trashPath) 500 Expect(err).ToNot(HaveOccurred()) 501 502 item, err := cache.GetRecycleItem(ctx, "admin", trashPathBase, trashPathTimestamp) 503 Expect(err).ToNot(HaveOccurred()) 504 Expect(item.Path).To(Equal("Photos")) 505 }) 506 507 It("rewrites the path of the children", func() { 508 err := cache.Delete(ctx, 1, "admin", "files/Photos", "files_trashbin/files/Photos.d1619007109") 509 Expect(err).ToNot(HaveOccurred()) 510 }) 511 }) 512 513 Describe("EmptyRecycle", func() { 514 It("clears the recycle bin", func() { 515 err := cache.Delete(ctx, 1, "admin", filePath, trashPath) 516 Expect(err).ToNot(HaveOccurred()) 517 518 err = cache.EmptyRecycle(ctx, "admin") 519 Expect(err).ToNot(HaveOccurred()) 520 521 _, err = cache.GetRecycleItem(ctx, "admin", trashPathBase, trashPathTimestamp) 522 Expect(err).To(HaveOccurred()) 523 }) 524 }) 525 526 Describe("DeleteRecycleItem", func() { 527 It("removes the item from the trash", func() { 528 err := cache.Delete(ctx, 1, "admin", filePath, trashPath) 529 Expect(err).ToNot(HaveOccurred()) 530 531 err = cache.DeleteRecycleItem(ctx, "admin", trashPathBase, trashPathTimestamp) 532 Expect(err).ToNot(HaveOccurred()) 533 534 _, err = cache.GetRecycleItem(ctx, "admin", trashPathBase, trashPathTimestamp) 535 Expect(err).To(HaveOccurred()) 536 }) 537 538 It("does not remove the item from the file cache", func() { 539 err := cache.Delete(ctx, 1, "admin", filePath, trashPath) 540 Expect(err).ToNot(HaveOccurred()) 541 542 err = cache.DeleteRecycleItem(ctx, "admin", trashPathBase, trashPathTimestamp) 543 Expect(err).ToNot(HaveOccurred()) 544 545 _, err = cache.Get(ctx, 1, trashPath) 546 Expect(err).ToNot(HaveOccurred()) 547 }) 548 }) 549 550 Describe("PurgeRecycleItem", func() { 551 It("removes the item from the database", func() { 552 err := cache.Delete(ctx, 1, "admin", filePath, trashPath) 553 Expect(err).ToNot(HaveOccurred()) 554 555 _, err = cache.GetRecycleItem(ctx, "admin", trashPathBase, trashPathTimestamp) 556 Expect(err).ToNot(HaveOccurred()) 557 558 err = cache.PurgeRecycleItem(ctx, "admin", trashPathBase, trashPathTimestamp, false) 559 Expect(err).ToNot(HaveOccurred()) 560 561 _, err = cache.GetRecycleItem(ctx, "admin", trashPathBase, trashPathTimestamp) 562 Expect(err).To(HaveOccurred()) 563 }) 564 565 It("removes the item from the filecache table", func() { 566 err := cache.Delete(ctx, 1, "admin", filePath, trashPath) 567 Expect(err).ToNot(HaveOccurred()) 568 569 err = cache.PurgeRecycleItem(ctx, "admin", trashPathBase, trashPathTimestamp, false) 570 Expect(err).ToNot(HaveOccurred()) 571 572 _, err = cache.Get(ctx, 1, trashPath) 573 Expect(err).To(HaveOccurred()) 574 }) 575 576 It("removes children from the filecache table", func() { 577 err := cache.Delete(ctx, 1, "admin", "files/Photos", "files_trashbin/files/Photos.d1619007109") 578 Expect(err).ToNot(HaveOccurred()) 579 580 _, err = cache.Get(ctx, 1, "files_trashbin/files/Photos.d1619007109/Portugal.jpg") 581 Expect(err).ToNot(HaveOccurred()) 582 583 err = cache.PurgeRecycleItem(ctx, "admin", "Photos", 1619007109, false) 584 Expect(err).ToNot(HaveOccurred()) 585 586 _, err = cache.Get(ctx, 1, "files_trashbin/files/Photos.d1619007109/Portugal.jpg") 587 Expect(err).To(HaveOccurred()) 588 }) 589 }) 590 }) 591 592 Describe("Copy", func() { 593 It("copies the entry", func() { 594 for _, dir := range []string{"files_versions", "files_versions/Photos"} { 595 parentData := map[string]interface{}{ 596 "path": dir, 597 "mimetype": "httpd/unix-directory", 598 "etag": "abcdefg", 599 } 600 _, err := cache.InsertOrUpdate(ctx, 1, parentData, false) 601 Expect(err).ToNot(HaveOccurred()) 602 } 603 604 existingEntry, err := cache.Get(ctx, 1, "files/Photos/Portugal.jpg") 605 Expect(err).ToNot(HaveOccurred()) 606 _, err = cache.Copy(ctx, 1, "files/Photos/Portugal.jpg", "files_versions/Photos/Portugal.jpg.v1619528083") 607 Expect(err).ToNot(HaveOccurred()) 608 609 newEntry, err := cache.Get(ctx, 1, "files_versions/Photos/Portugal.jpg.v1619528083") 610 Expect(err).ToNot(HaveOccurred()) 611 Expect(newEntry.ID).ToNot(Equal(existingEntry.ID)) 612 Expect(newEntry.MimeType).To(Equal(existingEntry.MimeType)) 613 }) 614 }) 615 616 Describe("Permissions", func() { 617 It("returns the permissions", func() { 618 perms, err := cache.Permissions(ctx, 1, "files/Photos/Portugal.jpg") 619 Expect(err).ToNot(HaveOccurred()) 620 Expect(perms).ToNot(BeNil()) 621 Expect(perms.InitiateFileUpload).To(BeTrue()) 622 623 perms, err = cache.Permissions(ctx, 1, "files/Photos/Teotihuacan.jpg") 624 Expect(err).ToNot(HaveOccurred()) 625 Expect(perms).ToNot(BeNil()) 626 Expect(perms.InitiateFileUpload).To(BeFalse()) 627 }) 628 }) 629 })