github.com/cs3org/reva/v2@v2.27.7/tests/integration/grpc/storageprovider_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 grpc_test 20 21 import ( 22 "context" 23 24 "google.golang.org/grpc/metadata" 25 26 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 27 rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" 28 storagep "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 29 "github.com/cs3org/reva/v2/pkg/auth/scope" 30 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 31 "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" 32 "github.com/cs3org/reva/v2/pkg/storage" 33 "github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud" 34 "github.com/cs3org/reva/v2/pkg/storage/fs/ocis" 35 "github.com/cs3org/reva/v2/pkg/storage/fs/registry" 36 jwt "github.com/cs3org/reva/v2/pkg/token/manager/jwt" 37 "github.com/cs3org/reva/v2/tests/helpers" 38 "github.com/google/uuid" 39 40 . "github.com/onsi/ginkgo/v2" 41 . "github.com/onsi/gomega" 42 ) 43 44 func ref(provider string, path string) *storagep.Reference { 45 r := &storagep.Reference{ 46 Path: path, 47 } 48 if provider == "ocis" { 49 r.ResourceId = &storagep.ResourceId{ 50 SpaceId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", 51 OpaqueId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", 52 } 53 } 54 return r 55 } 56 57 func createFS(provider string, revads map[string]*Revad) (storage.FS, error) { 58 conf := make(map[string]interface{}) 59 var f registry.NewFunc 60 switch provider { 61 case "ocis": 62 conf["root"] = revads["storage"].StorageRoot 63 conf["permissionssvc"] = revads["permissions"].GrpcAddress 64 f = ocis.New 65 case "nextcloud": 66 conf["endpoint"] = "http://localhost:8080/apps/sciencemesh/" 67 conf["mock_http"] = true 68 f = nextcloud.New 69 } 70 return f(conf, nil, nil) 71 } 72 73 // This test suite tests the gprc storageprovider interface using different 74 // storage backends 75 // 76 // It uses the `startRevads` helper to spawn the according reva daemon and 77 // other dependencies like a userprovider if needed. 78 // It also sets up an authenticated context and a service client to the storage 79 // provider to be used in the assertion functions. 80 var _ = Describe("storage providers", func() { 81 var ( 82 dependencies = []RevadConfig{} 83 variables = map[string]string{} 84 revads = map[string]*Revad{} 85 86 ctx context.Context 87 providerClient storagep.ProviderAPIClient 88 spacesClient storagep.SpacesAPIClient 89 user = &userpb.User{ 90 Id: &userpb.UserId{ 91 Idp: "0.0.0.0:19000", 92 OpaqueId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", 93 Type: userpb.UserType_USER_TYPE_PRIMARY, 94 }, 95 Username: "einstein", 96 } 97 98 homePath = "/" 99 filePath = "/file" 100 versionedFilePath = "/versionedFile" 101 subdirPath = "/subdir" 102 subdirRestoredPath = "/subdirRestored" 103 sharesPath = "/Shares" 104 ) 105 106 JustBeforeEach(func() { 107 var err error 108 ctx = context.Background() 109 110 // Add auth token 111 tokenManager, err := jwt.New(map[string]interface{}{"secret": "changemeplease"}) 112 Expect(err).ToNot(HaveOccurred()) 113 scope, err := scope.AddOwnerScope(nil) 114 Expect(err).ToNot(HaveOccurred()) 115 t, err := tokenManager.MintToken(ctx, user, scope) 116 Expect(err).ToNot(HaveOccurred()) 117 ctx = ctxpkg.ContextSetToken(ctx, t) 118 ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, t) 119 ctx = ctxpkg.ContextSetUser(ctx, user) 120 121 revads, err = startRevads(dependencies, variables) 122 Expect(err).ToNot(HaveOccurred()) 123 providerClient, err = pool.GetStorageProviderServiceClient(revads["storage"].GrpcAddress) 124 Expect(err).ToNot(HaveOccurred()) 125 spacesClient, err = pool.GetSpacesProviderServiceClient(revads["storage"].GrpcAddress) 126 Expect(err).ToNot(HaveOccurred()) 127 }) 128 129 AfterEach(func() { 130 for _, r := range revads { 131 Expect(r.Cleanup(CurrentSpecReport().Failed())).To(Succeed()) 132 } 133 }) 134 135 assertCreateHome := func(provider string) { 136 It("creates a home directory", func() { 137 homeRef := ref(provider, homePath) 138 statRes, err := providerClient.Stat(ctx, &storagep.StatRequest{Ref: homeRef}) 139 Expect(err).ToNot(HaveOccurred()) 140 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 141 142 res, err := spacesClient.CreateStorageSpace(ctx, &storagep.CreateStorageSpaceRequest{ 143 Owner: user, 144 Type: "personal", 145 Name: user.Id.OpaqueId, 146 }) 147 Expect(err).ToNot(HaveOccurred()) 148 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 149 150 statRes, err = providerClient.Stat(ctx, &storagep.StatRequest{Ref: ref(provider, homePath)}) 151 Expect(err).ToNot(HaveOccurred()) 152 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 153 154 // ghRes, err := serviceClient.GetHome(ctx, &storagep.GetHomeRequest{}) 155 // Expect(err).ToNot(HaveOccurred()) 156 // Expect(ghRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 157 }) 158 } 159 160 assertCreateContainer := func(provider string) { 161 It("creates a new directory", func() { 162 newRef := ref(provider, "/newdir") 163 _, err := providerClient.Stat(ctx, &storagep.StatRequest{Ref: newRef}) 164 Expect(err).ToNot(HaveOccurred()) 165 // Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 166 167 res, err := providerClient.CreateContainer(ctx, &storagep.CreateContainerRequest{Ref: newRef}) 168 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 169 Expect(err).ToNot(HaveOccurred()) 170 171 statRes, err := providerClient.Stat(ctx, &storagep.StatRequest{Ref: newRef}) 172 Expect(err).ToNot(HaveOccurred()) 173 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 174 }) 175 } 176 177 assertListContainer := func(provider string) { 178 It("lists a directory", func() { 179 listRes, err := providerClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: ref(provider, homePath)}) 180 Expect(err).ToNot(HaveOccurred()) 181 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 182 183 switch provider { 184 case "ocis": 185 Expect(len(listRes.Infos)).To(Equal(1)) // subdir 186 case "nextcloud": 187 Expect(len(listRes.Infos)).To(Equal(1)) // subdir 188 default: 189 Fail("unknown provider") 190 } 191 192 for _, info := range listRes.Infos { 193 switch info.Path { 194 default: 195 Fail("unknown path: " + info.Path) 196 case "/.space": 197 Expect(info.Type).To(Equal(storagep.ResourceType_RESOURCE_TYPE_CONTAINER)) 198 case subdirPath: 199 Expect(info.Type).To(Equal(storagep.ResourceType_RESOURCE_TYPE_CONTAINER)) 200 Expect(info.Owner.OpaqueId).To(Equal("f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c")) 201 202 } 203 } 204 }) 205 } 206 207 assertFileVersions := func(provider string) { 208 It("lists file versions", func() { 209 listRes, err := providerClient.ListFileVersions(ctx, &storagep.ListFileVersionsRequest{Ref: ref(provider, versionedFilePath)}) 210 Expect(err).ToNot(HaveOccurred()) 211 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 212 Expect(len(listRes.Versions)).To(Equal(1)) 213 Expect(listRes.Versions[0].Size).To(Equal(uint64(1))) 214 }) 215 216 // FIXME flaky test?!? 217 It("restores a file version", func() { 218 vRef := ref(provider, versionedFilePath) 219 statRes, err := providerClient.Stat(ctx, &storagep.StatRequest{Ref: vRef}) 220 Expect(err).ToNot(HaveOccurred()) 221 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 222 Expect(statRes.Info.Size).To(Equal(uint64(2))) // second version contains 2 bytes 223 224 listRes, err := providerClient.ListFileVersions(ctx, &storagep.ListFileVersionsRequest{Ref: vRef}) 225 Expect(err).ToNot(HaveOccurred()) 226 restoreRes, err := providerClient.RestoreFileVersion(ctx, 227 &storagep.RestoreFileVersionRequest{ 228 Ref: vRef, 229 Key: listRes.Versions[0].Key, 230 }) 231 Expect(err).ToNot(HaveOccurred()) 232 Expect(restoreRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 233 234 statRes, err = providerClient.Stat(ctx, &storagep.StatRequest{Ref: vRef}) 235 Expect(err).ToNot(HaveOccurred()) 236 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 237 Expect(statRes.Info.Size).To(Equal(uint64(1))) // initial version contains 1 byte 238 }) 239 } 240 241 assertDelete := func(provider string) { 242 It("deletes a directory", func() { 243 subdirRef := ref(provider, subdirPath) 244 statRes, err := providerClient.Stat(ctx, &storagep.StatRequest{Ref: subdirRef}) 245 Expect(err).ToNot(HaveOccurred()) 246 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 247 248 res, err := providerClient.Delete(ctx, &storagep.DeleteRequest{Ref: subdirRef}) 249 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 250 Expect(err).ToNot(HaveOccurred()) 251 252 statRes, err = providerClient.Stat(ctx, &storagep.StatRequest{Ref: subdirRef}) 253 Expect(err).ToNot(HaveOccurred()) 254 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 255 }) 256 } 257 258 assertMove := func(provider string) { 259 It("moves a directory", func() { 260 subdirRef := ref(provider, subdirPath) 261 statRes, err := providerClient.Stat(ctx, &storagep.StatRequest{Ref: subdirRef}) 262 Expect(err).ToNot(HaveOccurred()) 263 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 264 265 targetRef := &storagep.Reference{ResourceId: subdirRef.ResourceId, Path: "/new_subdir"} 266 res, err := providerClient.Move(ctx, &storagep.MoveRequest{Source: subdirRef, Destination: targetRef}) 267 268 Expect(err).ToNot(HaveOccurred()) 269 Expect(res.GetStatus().GetCode()).To(Equal(rpcv1beta1.Code_CODE_OK)) 270 271 statRes, err = providerClient.Stat(ctx, &storagep.StatRequest{Ref: subdirRef}) 272 Expect(err).ToNot(HaveOccurred()) 273 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 274 275 statRes, err = providerClient.Stat(ctx, &storagep.StatRequest{Ref: targetRef}) 276 Expect(err).ToNot(HaveOccurred()) 277 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 278 }) 279 } 280 281 assertGetPath := func(provider string) { 282 It("gets the path to an ID", func() { 283 r := ref(provider, subdirPath) 284 statRes, err := providerClient.Stat(ctx, &storagep.StatRequest{Ref: r}) 285 Expect(err).ToNot(HaveOccurred()) 286 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 287 288 res, err := providerClient.GetPath(ctx, &storagep.GetPathRequest{ResourceId: statRes.Info.Id}) 289 Expect(err).ToNot(HaveOccurred()) 290 291 // TODO: FIXME both cases should work for all providers 292 293 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 294 if provider != "nextcloud" { 295 Expect(res.Path).To(Equal(subdirPath)) 296 } 297 }) 298 } 299 300 assertGrants := func(provider string) { 301 It("lists, adds and removes grants", func() { 302 By("there are no grants initially") 303 subdirRef := ref(provider, subdirPath) 304 listRes, err := providerClient.ListGrants(ctx, &storagep.ListGrantsRequest{Ref: subdirRef}) 305 Expect(err).ToNot(HaveOccurred()) 306 Expect(len(listRes.Grants)).To(Equal(0)) 307 308 By("adding a grant") 309 grant := &storagep.Grant{ 310 Grantee: &storagep.Grantee{ 311 Type: storagep.GranteeType_GRANTEE_TYPE_USER, 312 Id: &storagep.Grantee_UserId{ 313 UserId: &userpb.UserId{ 314 OpaqueId: "4c510ada-c86b-4815-8820-42cdf82c3d51", 315 }, 316 }, 317 }, 318 Permissions: &storagep.ResourcePermissions{ 319 Stat: true, 320 Move: true, 321 Delete: false, 322 InitiateFileDownload: true, 323 }, 324 } 325 addRes, err := providerClient.AddGrant(ctx, &storagep.AddGrantRequest{Ref: subdirRef, Grant: grant}) 326 Expect(err).ToNot(HaveOccurred()) 327 Expect(addRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 328 329 By("listing the new grant") 330 listRes, err = providerClient.ListGrants(ctx, &storagep.ListGrantsRequest{Ref: subdirRef}) 331 Expect(err).ToNot(HaveOccurred()) 332 Expect(len(listRes.Grants)).To(Equal(1)) 333 readGrant := listRes.Grants[0] 334 Expect(readGrant.Permissions.Stat).To(BeTrue()) 335 Expect(readGrant.Permissions.Move).To(BeTrue()) 336 Expect(readGrant.Permissions.Delete).To(BeFalse()) 337 Expect(readGrant.Permissions.InitiateFileDownload).To(BeTrue()) 338 339 By("updating the grant") 340 grant.Permissions.Delete = true 341 updateRes, err := providerClient.UpdateGrant(ctx, &storagep.UpdateGrantRequest{Ref: subdirRef, Grant: grant}) 342 Expect(err).ToNot(HaveOccurred()) 343 Expect(updateRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 344 345 By("listing the update grant") 346 listRes, err = providerClient.ListGrants(ctx, &storagep.ListGrantsRequest{Ref: subdirRef}) 347 Expect(err).ToNot(HaveOccurred()) 348 Expect(len(listRes.Grants)).To(Equal(1)) 349 readGrant = listRes.Grants[0] 350 Expect(readGrant.Permissions.Stat).To(BeTrue()) 351 Expect(readGrant.Permissions.Move).To(BeTrue()) 352 Expect(readGrant.Permissions.Delete).To(BeTrue()) 353 Expect(readGrant.Permissions.InitiateFileDownload).To(BeTrue()) 354 355 By("deleting a grant") 356 delRes, err := providerClient.RemoveGrant(ctx, &storagep.RemoveGrantRequest{Ref: subdirRef, Grant: readGrant}) 357 Expect(err).ToNot(HaveOccurred()) 358 Expect(delRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 359 360 By("the grant is gone") 361 listRes, err = providerClient.ListGrants(ctx, &storagep.ListGrantsRequest{Ref: subdirRef}) 362 Expect(err).ToNot(HaveOccurred()) 363 Expect(len(listRes.Grants)).To(Equal(0)) 364 }) 365 } 366 367 assertUploads := func(provider string) { 368 It("returns upload URLs for simple and tus", func() { 369 fileRef := ref(provider, filePath) 370 res, err := providerClient.InitiateFileUpload(ctx, &storagep.InitiateFileUploadRequest{Ref: fileRef}) 371 Expect(err).ToNot(HaveOccurred()) 372 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 373 Expect(len(res.Protocols)).To(Equal(2)) 374 }) 375 } 376 377 assertDownloads := func(provider string) { 378 It("returns 'simple' download URLs", func() { 379 fileRef := ref(provider, filePath) 380 res, err := providerClient.InitiateFileDownload(ctx, &storagep.InitiateFileDownloadRequest{Ref: fileRef}) 381 Expect(err).ToNot(HaveOccurred()) 382 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 383 Expect(len(res.Protocols)).To(Equal(1)) 384 }) 385 } 386 387 assertRecycle := func(provider string) { 388 It("lists and restores resources", func() { 389 By("deleting an item") 390 subdirRef := ref(provider, subdirPath) 391 res, err := providerClient.Delete(ctx, &storagep.DeleteRequest{Ref: subdirRef}) 392 Expect(err).ToNot(HaveOccurred()) 393 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 394 395 By("listing the recycle items") 396 homeRef := ref(provider, homePath) 397 listRes, err := providerClient.ListRecycle(ctx, &storagep.ListRecycleRequest{Ref: homeRef}) 398 Expect(err).ToNot(HaveOccurred()) 399 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 400 401 Expect(len(listRes.RecycleItems)).To(Equal(1)) 402 item := listRes.RecycleItems[0] 403 Expect(item.Ref.Path).To(Equal(subdirPath)) 404 405 By("restoring a recycle item") 406 statRes, err := providerClient.Stat(ctx, &storagep.StatRequest{Ref: subdirRef}) 407 Expect(err).ToNot(HaveOccurred()) 408 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 409 410 restoreRes, err := providerClient.RestoreRecycleItem(ctx, 411 &storagep.RestoreRecycleItemRequest{ 412 Ref: homeRef, 413 Key: item.Key, 414 }, 415 ) 416 Expect(err).ToNot(HaveOccurred()) 417 Expect(restoreRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 418 419 statRes, err = providerClient.Stat(ctx, &storagep.StatRequest{Ref: subdirRef}) 420 Expect(err).ToNot(HaveOccurred()) 421 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 422 }) 423 424 It("restores resources to a different location", func() { 425 restoreRef := ref(provider, subdirRestoredPath) 426 subdirRef := ref(provider, subdirPath) 427 homeRef := ref(provider, homePath) 428 429 By("deleting an item") 430 res, err := providerClient.Delete(ctx, &storagep.DeleteRequest{Ref: subdirRef}) 431 Expect(err).ToNot(HaveOccurred()) 432 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 433 434 By("listing the recycle items") 435 listRes, err := providerClient.ListRecycle(ctx, &storagep.ListRecycleRequest{Ref: homeRef}) 436 Expect(err).ToNot(HaveOccurred()) 437 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 438 439 Expect(len(listRes.RecycleItems)).To(Equal(1)) 440 item := listRes.RecycleItems[0] 441 Expect(item.Ref.Path).To(Equal(subdirPath)) 442 443 By("restoring the item to a different location") 444 statRes, err := providerClient.Stat(ctx, &storagep.StatRequest{Ref: restoreRef}) 445 Expect(err).ToNot(HaveOccurred()) 446 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 447 448 restoreRes, err := providerClient.RestoreRecycleItem(ctx, 449 &storagep.RestoreRecycleItemRequest{ 450 Ref: homeRef, 451 Key: item.Key, 452 RestoreRef: restoreRef, 453 }, 454 ) 455 Expect(err).ToNot(HaveOccurred()) 456 Expect(restoreRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 457 458 statRes, err = providerClient.Stat(ctx, &storagep.StatRequest{Ref: restoreRef}) 459 Expect(err).ToNot(HaveOccurred()) 460 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 461 }) 462 463 It("purges recycle items resources", func() { 464 subdirRef := ref(provider, subdirPath) 465 homeRef := ref(provider, homePath) 466 467 By("deleting an item") 468 res, err := providerClient.Delete(ctx, &storagep.DeleteRequest{Ref: subdirRef}) 469 Expect(err).ToNot(HaveOccurred()) 470 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 471 472 By("listing recycle items") 473 listRes, err := providerClient.ListRecycle(ctx, &storagep.ListRecycleRequest{Ref: homeRef}) 474 Expect(err).ToNot(HaveOccurred()) 475 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 476 Expect(len(listRes.RecycleItems)).To(Equal(1)) 477 478 By("purging a recycle item") 479 ref := listRes.RecycleItems[0].Ref 480 ref.ResourceId = homeRef.ResourceId 481 purgeRes, err := providerClient.PurgeRecycle(ctx, &storagep.PurgeRecycleRequest{Ref: ref}) 482 Expect(err).ToNot(HaveOccurred()) 483 Expect(purgeRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 484 485 listRes, err = providerClient.ListRecycle(ctx, &storagep.ListRecycleRequest{Ref: homeRef}) 486 Expect(err).ToNot(HaveOccurred()) 487 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 488 Expect(len(listRes.RecycleItems)).To(Equal(0)) 489 }) 490 } 491 492 assertReferences := func(provider string) { 493 It("creates references", func() { 494 if provider == "ocis" { 495 // ocis can't create references like this 496 return 497 } 498 499 sharesRef := ref(provider, sharesPath) 500 listRes, err := providerClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: sharesRef}) 501 Expect(err).ToNot(HaveOccurred()) 502 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_NOT_FOUND)) 503 Expect(len(listRes.Infos)).To(Equal(0)) 504 505 res, err := providerClient.CreateReference(ctx, &storagep.CreateReferenceRequest{ 506 Ref: &storagep.Reference{ 507 Path: "/Shares/reference", 508 }, 509 TargetUri: "scheme://target", 510 }) 511 Expect(err).ToNot(HaveOccurred()) 512 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 513 514 listRes, err = providerClient.ListContainer(ctx, &storagep.ListContainerRequest{Ref: sharesRef}) 515 Expect(err).ToNot(HaveOccurred()) 516 Expect(listRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 517 Expect(len(listRes.Infos)).To(Equal(1)) 518 }) 519 } 520 521 assertMetadata := func(provider string) { 522 It("sets and unsets metadata", func() { 523 subdirRef := ref(provider, subdirPath) 524 statRes, err := providerClient.Stat(ctx, &storagep.StatRequest{Ref: subdirRef}) 525 Expect(err).ToNot(HaveOccurred()) 526 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 527 Expect(statRes.Info.ArbitraryMetadata.Metadata["foo"]).To(BeEmpty()) 528 529 By("setting arbitrary metadata") 530 samRes, err := providerClient.SetArbitraryMetadata(ctx, &storagep.SetArbitraryMetadataRequest{ 531 Ref: subdirRef, 532 ArbitraryMetadata: &storagep.ArbitraryMetadata{Metadata: map[string]string{"foo": "bar"}}, 533 }) 534 Expect(err).ToNot(HaveOccurred()) 535 Expect(samRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 536 537 statRes, err = providerClient.Stat(ctx, &storagep.StatRequest{Ref: subdirRef}) 538 Expect(err).ToNot(HaveOccurred()) 539 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 540 Expect(statRes.Info.ArbitraryMetadata.Metadata["foo"]).To(Equal("bar")) 541 542 By("unsetting arbitrary metadata") 543 uamRes, err := providerClient.UnsetArbitraryMetadata(ctx, &storagep.UnsetArbitraryMetadataRequest{ 544 Ref: subdirRef, 545 ArbitraryMetadataKeys: []string{"foo"}, 546 }) 547 Expect(err).ToNot(HaveOccurred()) 548 Expect(uamRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 549 550 statRes, err = providerClient.Stat(ctx, &storagep.StatRequest{Ref: subdirRef}) 551 Expect(err).ToNot(HaveOccurred()) 552 Expect(statRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 553 Expect(statRes.Info.ArbitraryMetadata.Metadata["foo"]).To(BeEmpty()) 554 }) 555 } 556 557 assertLocking := func(provider string) { 558 var ( 559 subdirRef = ref(provider, subdirPath) 560 lock = &storagep.Lock{ 561 Type: storagep.LockType_LOCK_TYPE_EXCL, 562 User: user.Id, 563 LockId: uuid.New().String(), 564 } 565 ) 566 It("locks, gets, refreshes and unlocks a lock", func() { 567 lockRes, err := providerClient.SetLock(ctx, &storagep.SetLockRequest{ 568 Ref: subdirRef, 569 Lock: lock, 570 }) 571 Expect(err).ToNot(HaveOccurred()) 572 Expect(lockRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 573 574 getRes, err := providerClient.GetLock(ctx, &storagep.GetLockRequest{ 575 Ref: subdirRef, 576 }) 577 Expect(err).ToNot(HaveOccurred()) 578 Expect(getRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 579 Expect(getRes.Lock.Type).To(Equal(lock.Type)) 580 Expect(getRes.Lock.User.Idp).To(Equal(lock.User.Idp)) 581 Expect(getRes.Lock.User.OpaqueId).To(Equal(lock.User.OpaqueId)) 582 Expect(getRes.Lock.User.Type).To(Equal(lock.User.Type)) 583 Expect(getRes.Lock.LockId).To(Equal(lock.LockId)) 584 Expect(getRes.Lock.AppName).To(Equal(lock.AppName)) 585 Expect(getRes.Lock.Expiration).To(Equal(lock.Expiration)) 586 Expect(getRes.Lock.Opaque).To(Equal(lock.Opaque)) 587 588 refreshRes, err := providerClient.RefreshLock(ctx, &storagep.RefreshLockRequest{ 589 Ref: subdirRef, 590 Lock: lock, 591 }) 592 Expect(err).ToNot(HaveOccurred()) 593 Expect(refreshRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 594 595 unlockRes, err := providerClient.Unlock(ctx, &storagep.UnlockRequest{ 596 Ref: subdirRef, 597 Lock: lock, 598 }) 599 Expect(err).ToNot(HaveOccurred()) 600 Expect(unlockRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 601 }) 602 603 Context("with a locked file", func() { 604 JustBeforeEach(func() { 605 lockRes, err := providerClient.SetLock(ctx, &storagep.SetLockRequest{ 606 Ref: subdirRef, 607 Lock: lock, 608 }) 609 Expect(err).ToNot(HaveOccurred()) 610 Expect(lockRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 611 }) 612 613 It("removes the lock when unlocking", func() { 614 delRes, err := providerClient.Delete(ctx, &storagep.DeleteRequest{ 615 Ref: subdirRef, 616 }) 617 Expect(err).ToNot(HaveOccurred()) 618 Expect(delRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_LOCKED)) 619 620 unlockRes, err := providerClient.Unlock(ctx, &storagep.UnlockRequest{ 621 Ref: subdirRef, 622 Lock: lock, 623 }) 624 Expect(err).ToNot(HaveOccurred()) 625 Expect(unlockRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 626 627 delRes, err = providerClient.Delete(ctx, &storagep.DeleteRequest{ 628 Ref: subdirRef, 629 }) 630 Expect(err).ToNot(HaveOccurred()) 631 Expect(delRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 632 633 }) 634 635 // FIXME these tests are all wrong as they use the reference of a directory, but try to lock and upload a file 636 Context("with the owner holding the lock", func() { 637 It("can not initiate an upload that would overwrite a folder", func() { 638 ulRes, err := providerClient.InitiateFileUpload(ctx, &storagep.InitiateFileUploadRequest{ 639 Ref: subdirRef, 640 LockId: lock.LockId, 641 }) 642 Expect(err).ToNot(HaveOccurred()) 643 Expect(ulRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_FAILED_PRECONDITION)) 644 }) 645 646 It("can delete the file", func() { 647 delRes, err := providerClient.Delete(ctx, &storagep.DeleteRequest{ 648 Ref: subdirRef, 649 LockId: lock.LockId, 650 }) 651 Expect(err).ToNot(HaveOccurred()) 652 Expect(delRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 653 654 }) 655 }) 656 Context("with the owner not holding the lock", func() { 657 It("can only delete after unlocking the file", func() { 658 delRes, err := providerClient.Delete(ctx, &storagep.DeleteRequest{ 659 Ref: subdirRef, 660 }) 661 Expect(err).ToNot(HaveOccurred()) 662 Expect(delRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_LOCKED)) 663 }) 664 }) 665 666 }) 667 } 668 669 suite := func(provider string, deps []RevadConfig) { 670 Describe(provider, func() { 671 BeforeEach(func() { 672 dependencies = deps 673 variables = map[string]string{ 674 "enable_home": "true", 675 } 676 }) 677 678 assertCreateHome(provider) 679 680 Context("with a home and a subdirectory", func() { 681 JustBeforeEach(func() { 682 res, err := spacesClient.CreateStorageSpace(ctx, &storagep.CreateStorageSpaceRequest{ 683 Owner: user, 684 Type: "personal", 685 Name: user.Id.OpaqueId, 686 }) 687 Expect(err).ToNot(HaveOccurred()) 688 Expect(res.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 689 690 subdirRes, err := providerClient.CreateContainer(ctx, &storagep.CreateContainerRequest{Ref: ref(provider, subdirPath)}) 691 Expect(err).ToNot(HaveOccurred()) 692 Expect(subdirRes.Status.Code).To(Equal(rpcv1beta1.Code_CODE_OK)) 693 }) 694 695 assertCreateContainer(provider) 696 assertListContainer(provider) 697 assertGetPath(provider) 698 assertDelete(provider) 699 assertMove(provider) 700 assertGrants(provider) 701 assertUploads(provider) 702 assertDownloads(provider) 703 assertRecycle(provider) 704 assertReferences(provider) 705 assertMetadata(provider) 706 if provider == "ocis" { 707 assertLocking(provider) 708 } else { 709 PIt("Locking implementation still pending for provider " + provider) 710 } 711 }) 712 713 Context("with an existing file /versioned_file", func() { 714 JustBeforeEach(func() { 715 fs, err := createFS(provider, revads) 716 Expect(err).ToNot(HaveOccurred()) 717 718 content1 := []byte("1") 719 content2 := []byte("22") 720 721 vRef := ref(provider, versionedFilePath) 722 if provider == "nextcloud" { 723 vRef.ResourceId = &storagep.ResourceId{StorageId: user.Id.OpaqueId} 724 } 725 726 _, err = fs.CreateStorageSpace(ctx, &storagep.CreateStorageSpaceRequest{ 727 Owner: user, 728 Type: "personal", 729 }) 730 Expect(err).ToNot(HaveOccurred()) 731 err = helpers.Upload(ctx, fs, vRef, content1) 732 Expect(err).ToNot(HaveOccurred()) 733 err = helpers.Upload(ctx, fs, vRef, content2) 734 Expect(err).ToNot(HaveOccurred()) 735 }) 736 737 assertFileVersions(provider) 738 }) 739 }) 740 741 } 742 743 suite("nextcloud", []RevadConfig{ 744 { 745 Name: "storage", 746 Config: "storageprovider-nextcloud.toml", 747 }, 748 }) 749 750 suite("ocis", []RevadConfig{ 751 { 752 Name: "storage", Config: "storageprovider-ocis.toml", 753 }, 754 { 755 Name: "permissions", Config: "permissions-ocis-ci.toml", 756 }, 757 }) 758 759 })