github.com/cs3org/reva/v2@v2.27.7/internal/grpc/services/sharesstorageprovider/sharesstorageprovider_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 sharesstorageprovider_test 20 21 import ( 22 "context" 23 "os" 24 25 gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" 26 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 27 rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" 28 collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" 29 sprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 30 types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" 31 provider "github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider" 32 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 33 "github.com/cs3org/reva/v2/pkg/rgrpc/status" 34 "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" 35 _ "github.com/cs3org/reva/v2/pkg/share/manager/loader" 36 "github.com/cs3org/reva/v2/pkg/utils" 37 cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks" 38 "google.golang.org/grpc" 39 40 . "github.com/onsi/ginkgo/v2" 41 . "github.com/onsi/gomega" 42 "github.com/stretchr/testify/mock" 43 ) 44 45 var ( 46 ShareJail *sprovider.ResourceId 47 BaseShare *collaboration.ReceivedShare 48 BaseShareTwo *collaboration.ReceivedShare 49 ShareJailStatRequest *sprovider.StatRequest 50 BaseStatRequest *sprovider.StatRequest 51 BaseListContainerRequest *sprovider.ListContainerRequest 52 ) 53 54 var _ = Describe("Sharesstorageprovider", func() { 55 var ( 56 config = map[string]interface{}{ 57 "gateway_addr": "127.0.0.1:1234", 58 "driver": "json", 59 "usershareprovidersvc": "any", 60 "drivers": map[string]map[string]interface{}{ 61 "json": {}, 62 }, 63 } 64 ctx = ctxpkg.ContextSetUser(context.Background(), &userpb.User{ 65 Id: &userpb.UserId{ 66 OpaqueId: "alice", 67 }, 68 Username: "alice", 69 }) 70 71 s sprovider.ProviderAPIServer 72 gatewayClient *cs3mocks.GatewayAPIClient 73 gatewaySelector pool.Selectable[gateway.GatewayAPIClient] 74 sharingCollaborationClient *cs3mocks.CollaborationAPIClient 75 sharingCollaborationSelector pool.Selectable[collaboration.CollaborationAPIClient] 76 ) 77 78 BeforeEach(func() { 79 ShareJail = &sprovider.ResourceId{ 80 StorageId: utils.ShareStorageProviderID, 81 SpaceId: utils.ShareStorageSpaceID, 82 OpaqueId: utils.ShareStorageSpaceID, 83 } 84 85 BaseShare = &collaboration.ReceivedShare{ 86 State: collaboration.ShareState_SHARE_STATE_ACCEPTED, 87 Share: &collaboration.Share{ 88 Id: &collaboration.ShareId{ 89 OpaqueId: "shareid", 90 }, 91 ResourceId: &sprovider.ResourceId{ 92 StorageId: "storageid", 93 SpaceId: "storageid", 94 OpaqueId: "shareddir", 95 }, 96 Permissions: &collaboration.SharePermissions{ 97 Permissions: &sprovider.ResourcePermissions{ 98 Stat: true, 99 ListContainer: true, 100 InitiateFileUpload: true, 101 }, 102 }, 103 }, 104 MountPoint: &sprovider.Reference{ 105 Path: "share1-shareddir", 106 }, 107 } 108 109 BaseShareTwo = &collaboration.ReceivedShare{ 110 State: collaboration.ShareState_SHARE_STATE_ACCEPTED, 111 Share: &collaboration.Share{ 112 Id: &collaboration.ShareId{ 113 OpaqueId: "shareid2", 114 }, 115 ResourceId: &sprovider.ResourceId{ 116 StorageId: "storageid", 117 SpaceId: "storageid", 118 OpaqueId: "shareddir2", 119 }, 120 Permissions: &collaboration.SharePermissions{ 121 Permissions: &sprovider.ResourcePermissions{ 122 Stat: true, 123 ListContainer: true, 124 InitiateFileUpload: true, 125 }, 126 }, 127 }, 128 MountPoint: &sprovider.Reference{ 129 Path: "share2-shareddir2", 130 }, 131 } 132 133 ShareJailStatRequest = &sprovider.StatRequest{ 134 Ref: &sprovider.Reference{ 135 ResourceId: &sprovider.ResourceId{ 136 StorageId: utils.ShareStorageProviderID, 137 SpaceId: utils.ShareStorageSpaceID, 138 OpaqueId: utils.ShareStorageSpaceID, 139 }, 140 Path: ".", 141 }, 142 } 143 144 BaseStatRequest = &sprovider.StatRequest{ 145 Ref: &sprovider.Reference{ 146 ResourceId: &sprovider.ResourceId{ 147 StorageId: utils.ShareStorageProviderID, 148 SpaceId: utils.ShareStorageSpaceID, 149 OpaqueId: "shareid", 150 }, 151 Path: ".", 152 }, 153 } 154 155 BaseListContainerRequest = &sprovider.ListContainerRequest{ 156 Ref: &sprovider.Reference{ 157 ResourceId: &sprovider.ResourceId{ 158 StorageId: utils.ShareStorageProviderID, 159 SpaceId: utils.ShareStorageSpaceID, 160 OpaqueId: "shareid", 161 }, 162 Path: ".", 163 }, 164 } 165 166 pool.RemoveSelector("GatewaySelector" + "any") 167 gatewayClient = &cs3mocks.GatewayAPIClient{} 168 gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient]( 169 "GatewaySelector", 170 "any", 171 func(cc grpc.ClientConnInterface) gateway.GatewayAPIClient { 172 return gatewayClient 173 }, 174 ) 175 176 pool.RemoveSelector("SharingCollaborationSelector" + "any") 177 sharingCollaborationClient = &cs3mocks.CollaborationAPIClient{} 178 sharingCollaborationSelector = pool.GetSelector[collaboration.CollaborationAPIClient]( 179 "SharingCollaborationSelector", 180 "any", 181 func(cc grpc.ClientConnInterface) collaboration.CollaborationAPIClient { 182 return sharingCollaborationClient 183 }, 184 ) 185 186 // mock stat requests 187 // some-provider-id 188 gatewayClient.On("Stat", mock.Anything, mock.AnythingOfType("*providerv1beta1.StatRequest")).Return( 189 func(_ context.Context, req *sprovider.StatRequest, _ ...grpc.CallOption) *sprovider.StatResponse { 190 switch req.Ref.GetPath() { 191 case "./share1-shareddir", "./share1-shareddir (1)": 192 return &sprovider.StatResponse{ 193 Status: status.NewOK(context.Background()), 194 Info: &sprovider.ResourceInfo{ 195 Type: sprovider.ResourceType_RESOURCE_TYPE_CONTAINER, 196 Path: "share1-shareddir", 197 Id: &sprovider.ResourceId{ 198 StorageId: "share1-storageid", 199 SpaceId: "share1-storageid", 200 OpaqueId: "shareddir", 201 }, 202 PermissionSet: &sprovider.ResourcePermissions{ 203 Stat: true, 204 }, 205 Size: 100, 206 }, 207 } 208 case "./share1-subdir": 209 return &sprovider.StatResponse{ 210 Status: status.NewOK(context.Background()), 211 Info: &sprovider.ResourceInfo{ 212 Type: sprovider.ResourceType_RESOURCE_TYPE_CONTAINER, 213 Path: "share1-subdir", 214 Id: &sprovider.ResourceId{ 215 StorageId: "share1-storageid", 216 SpaceId: "share1-storageid", 217 OpaqueId: "subdir", 218 }, 219 PermissionSet: &sprovider.ResourcePermissions{ 220 Stat: true, 221 }, 222 Size: 10, 223 }, 224 } 225 case "./share1-subdir/share1-subdir-file": 226 return &sprovider.StatResponse{ 227 Status: status.NewOK(context.Background()), 228 Info: &sprovider.ResourceInfo{ 229 Type: sprovider.ResourceType_RESOURCE_TYPE_FILE, 230 Path: "share1-subdir-file", 231 Id: &sprovider.ResourceId{ 232 StorageId: "share1-storageid", 233 SpaceId: "share1-storageid", 234 OpaqueId: "file", 235 }, 236 PermissionSet: &sprovider.ResourcePermissions{ 237 Stat: true, 238 }, 239 Size: 20, 240 }, 241 } 242 case ".": 243 permissionSet := &sprovider.ResourcePermissions{ 244 Stat: true, 245 } 246 if req.Ref.ResourceId.OpaqueId == "shareddir-merged" { 247 permissionSet.ListContainer = true 248 } 249 return &sprovider.StatResponse{ 250 Status: status.NewOK(context.Background()), 251 Info: &sprovider.ResourceInfo{ 252 Type: sprovider.ResourceType_RESOURCE_TYPE_CONTAINER, 253 Path: "share1-shareddir", 254 Id: &sprovider.ResourceId{ 255 StorageId: "share1-storageid", 256 SpaceId: "share1-storageid", 257 OpaqueId: req.Ref.ResourceId.OpaqueId, 258 }, 259 PermissionSet: permissionSet, 260 Size: 100, 261 }, 262 } 263 default: 264 switch req.Ref.ResourceId.OpaqueId { 265 case "shareddir", "shareddir2": 266 permissionSet := &sprovider.ResourcePermissions{ 267 Stat: true, 268 ListContainer: true, 269 } 270 return &sprovider.StatResponse{ 271 Status: status.NewOK(context.Background()), 272 Info: &sprovider.ResourceInfo{ 273 Type: sprovider.ResourceType_RESOURCE_TYPE_CONTAINER, 274 Path: "share1-shareddir", 275 Id: req.Ref.ResourceId, 276 PermissionSet: permissionSet, 277 Size: 100, 278 }, 279 } 280 case "shareddir-merged": 281 permissionSet := &sprovider.ResourcePermissions{ 282 Stat: true, 283 ListContainer: true, 284 } 285 return &sprovider.StatResponse{ 286 Status: status.NewOK(context.Background()), 287 Info: &sprovider.ResourceInfo{ 288 Type: sprovider.ResourceType_RESOURCE_TYPE_CONTAINER, 289 Path: "share1-shareddir", 290 Id: &sprovider.ResourceId{ 291 StorageId: "share1-storageid", 292 SpaceId: "share1-storageid", 293 OpaqueId: req.Ref.ResourceId.OpaqueId, 294 }, 295 PermissionSet: permissionSet, 296 Size: 100, 297 }, 298 } 299 default: 300 return &sprovider.StatResponse{ 301 Status: status.NewNotFound(context.Background(), "not found"), 302 } 303 } 304 } 305 }, 306 nil) 307 308 gatewayClient.On("ListContainer", mock.Anything, mock.AnythingOfType("*providerv1beta1.ListContainerRequest")).Return( 309 func(_ context.Context, req *sprovider.ListContainerRequest, _ ...grpc.CallOption) *sprovider.ListContainerResponse { 310 switch { 311 case utils.ResourceIDEqual(req.Ref.ResourceId, BaseShare.Share.ResourceId): 312 resp := &sprovider.ListContainerResponse{ 313 Status: status.NewOK(context.Background()), 314 Infos: []*sprovider.ResourceInfo{}, 315 } 316 317 switch req.Ref.GetPath() { 318 case ".": 319 resp.Infos = append(resp.Infos, &sprovider.ResourceInfo{ 320 Type: sprovider.ResourceType_RESOURCE_TYPE_CONTAINER, 321 Path: "share1-shareddir/share1-subdir", 322 Id: &sprovider.ResourceId{ 323 StorageId: "share1-storageid", 324 SpaceId: "share1-storageid", 325 OpaqueId: "subdir", 326 }, 327 Size: 1, 328 }) 329 case "./share1-subdir": 330 resp.Infos = append(resp.Infos, &sprovider.ResourceInfo{ 331 Type: sprovider.ResourceType_RESOURCE_TYPE_CONTAINER, 332 Path: "share1-shareddir/share1-subdir/share1-subdir-file", 333 Id: &sprovider.ResourceId{ 334 StorageId: "share1-storageid", 335 SpaceId: "share1-storageid", 336 OpaqueId: "file", 337 }, 338 Size: 1, 339 }) 340 } 341 return resp 342 case utils.ResourceIDEqual(req.Ref.ResourceId, BaseShareTwo.Share.ResourceId): 343 resp := &sprovider.ListContainerResponse{ 344 Status: status.NewOK(context.Background()), 345 Infos: []*sprovider.ResourceInfo{}, 346 } 347 return resp 348 case utils.ResourceIDEqual(req.Ref.ResourceId, BaseShareTwo.Share.ResourceId): 349 return &sprovider.ListContainerResponse{ 350 Status: status.NewOK(context.Background()), 351 Infos: []*sprovider.ResourceInfo{}, 352 } 353 default: 354 return &sprovider.ListContainerResponse{ 355 Status: status.NewOK(context.Background()), 356 Infos: []*sprovider.ResourceInfo{}, 357 } 358 } 359 }, nil) 360 361 }) 362 363 JustBeforeEach(func() { 364 p, err := provider.New(gatewaySelector, sharingCollaborationSelector, 5) 365 Expect(err).ToNot(HaveOccurred()) 366 s = p.(sprovider.ProviderAPIServer) 367 Expect(s).ToNot(BeNil()) 368 }) 369 370 Describe("NewDefault", func() { 371 It("returns a new service instance", func() { 372 tmpfile, err := os.CreateTemp("", "eos-unit-test-shares-*.json") 373 Expect(err).ToNot(HaveOccurred()) 374 defer os.Remove(tmpfile.Name()) 375 376 config["drivers"] = map[string]map[string]interface{}{ 377 "json": { 378 "file": tmpfile.Name(), 379 "mount_id": "shareprovidermountid", 380 }, 381 } 382 s, err := provider.NewDefault(config, nil, nil) 383 Expect(err).ToNot(HaveOccurred()) 384 Expect(s).ToNot(BeNil()) 385 }) 386 }) 387 388 Describe("ListContainer", func() { 389 It("lists accepted shares", func() { 390 sharingCollaborationClient.On("GetReceivedShare", mock.Anything, mock.Anything).Return(&collaboration.GetReceivedShareResponse{ 391 Status: status.NewOK(context.Background()), 392 Share: &collaboration.ReceivedShare{ 393 Share: BaseShare.Share, 394 State: collaboration.ShareState_SHARE_STATE_ACCEPTED, 395 }, 396 }, nil) 397 res, err := s.ListContainer(ctx, BaseListContainerRequest) 398 Expect(err).ToNot(HaveOccurred()) 399 Expect(res).ToNot(BeNil()) 400 Expect(len(res.Infos)).To(Equal(1)) 401 }) 402 It("ignores invalid shares", func() { 403 sharingCollaborationClient.On("GetReceivedShare", mock.Anything, mock.Anything).Return(&collaboration.GetReceivedShareResponse{ 404 Status: status.NewOK(context.Background()), 405 Share: &collaboration.ReceivedShare{ 406 Share: &collaboration.Share{ResourceId: &sprovider.ResourceId{}}, 407 State: collaboration.ShareState_SHARE_STATE_INVALID, 408 }, 409 }, nil) 410 res, err := s.ListContainer(ctx, BaseListContainerRequest) 411 Expect(err).ToNot(HaveOccurred()) 412 Expect(res).ToNot(BeNil()) 413 Expect(len(res.Infos)).To(Equal(0)) 414 }) 415 It("ignores pending shares", func() { 416 sharingCollaborationClient.On("GetReceivedShare", mock.Anything, mock.Anything).Return(&collaboration.GetReceivedShareResponse{ 417 Status: status.NewOK(context.Background()), 418 Share: &collaboration.ReceivedShare{ 419 Share: &collaboration.Share{ResourceId: &sprovider.ResourceId{}}, 420 State: collaboration.ShareState_SHARE_STATE_PENDING, 421 }, 422 }, nil) 423 res, err := s.ListContainer(ctx, BaseListContainerRequest) 424 Expect(err).ToNot(HaveOccurred()) 425 Expect(res).ToNot(BeNil()) 426 Expect(len(res.Infos)).To(Equal(0)) 427 }) 428 It("ignores rejected shares", func() { 429 sharingCollaborationClient.On("GetReceivedShare", mock.Anything, mock.Anything).Return(&collaboration.GetReceivedShareResponse{ 430 Status: status.NewOK(context.Background()), 431 Share: &collaboration.ReceivedShare{ 432 Share: &collaboration.Share{ResourceId: &sprovider.ResourceId{}}, 433 State: collaboration.ShareState_SHARE_STATE_REJECTED, 434 }, 435 }, nil) 436 res, err := s.ListContainer(ctx, BaseListContainerRequest) 437 Expect(err).ToNot(HaveOccurred()) 438 Expect(res).ToNot(BeNil()) 439 Expect(len(res.Infos)).To(Equal(0)) 440 }) 441 }) 442 443 Context("with two accepted shares", func() { 444 BeforeEach(func() { 445 sharingCollaborationClient.On("ListReceivedShares", mock.Anything, mock.Anything).Return(&collaboration.ListReceivedSharesResponse{ 446 Status: status.NewOK(context.Background()), 447 Shares: []*collaboration.ReceivedShare{BaseShare, BaseShareTwo}, 448 }, nil) 449 sharingCollaborationClient.On("GetReceivedShare", mock.Anything, mock.Anything).Return( 450 func(_ context.Context, req *collaboration.GetReceivedShareRequest, _ ...grpc.CallOption) *collaboration.GetReceivedShareResponse { 451 switch req.Ref.GetId().GetOpaqueId() { 452 case BaseShare.Share.Id.OpaqueId: 453 return &collaboration.GetReceivedShareResponse{ 454 Status: status.NewOK(context.Background()), 455 Share: BaseShare, 456 } 457 case BaseShareTwo.Share.Id.OpaqueId: 458 return &collaboration.GetReceivedShareResponse{ 459 Status: status.NewOK(context.Background()), 460 Share: BaseShareTwo, 461 } 462 default: 463 return &collaboration.GetReceivedShareResponse{ 464 Status: status.NewNotFound(context.Background(), "not found"), 465 } 466 } 467 }, nil) 468 }) 469 470 Describe("Stat", func() { 471 It("stats the first share folder", func() { 472 req := ShareJailStatRequest 473 req.Ref.Path = "./share1-shareddir" 474 res, err := s.Stat(ctx, req) 475 Expect(err).ToNot(HaveOccurred()) 476 Expect(res).ToNot(BeNil()) 477 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 478 Expect(res.Info).ToNot(BeNil()) 479 Expect(res.Info.Type).To(Equal(sprovider.ResourceType_RESOURCE_TYPE_CONTAINER)) 480 Expect(res.Info.Path).To(Equal("share1-shareddir")) 481 // Expect(res.Info.Size).To(Equal(uint64(300))) TODO: Why 300? 482 Expect(res.Info.Size).To(Equal(uint64(100))) 483 }) 484 485 It("stats the correct share in the share jail", func() { 486 BaseShare.MountPoint.Path = "share1-shareddir" 487 BaseShareTwo.MountPoint.Path = "share1-shareddir (1)" 488 statReq := ShareJailStatRequest 489 statReq.Ref.Path = "./share1-shareddir (1)" 490 res, err := s.Stat(ctx, statReq) 491 Expect(err).ToNot(HaveOccurred()) 492 Expect(res).ToNot(BeNil()) 493 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 494 Expect(res.Info).ToNot(BeNil()) 495 Expect(res.Info.Type).To(Equal(sprovider.ResourceType_RESOURCE_TYPE_CONTAINER)) 496 Expect(res.Info.Path).To(Equal("share1-shareddir")) 497 Expect(res.Info.Size).To(Equal(uint64(100))) 498 }) 499 500 It("stats a shares folder", func() { 501 statReq := BaseStatRequest 502 res, err := s.Stat(ctx, statReq) 503 Expect(err).ToNot(HaveOccurred()) 504 Expect(res).ToNot(BeNil()) 505 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 506 Expect(res.Info).ToNot(BeNil()) 507 Expect(res.Info.Type).To(Equal(sprovider.ResourceType_RESOURCE_TYPE_CONTAINER)) 508 Expect(res.Info.Path).To(Equal("share1-shareddir")) 509 Expect(res.Info.Size).To(Equal(uint64(100))) 510 }) 511 512 It("stats a subfolder in a share", func() { 513 statReq := BaseStatRequest 514 statReq.Ref.Path = "./share1-subdir" 515 res, err := s.Stat(ctx, statReq) 516 Expect(err).ToNot(HaveOccurred()) 517 Expect(res).ToNot(BeNil()) 518 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 519 Expect(res.Info).ToNot(BeNil()) 520 Expect(res.Info.Type).To(Equal(sprovider.ResourceType_RESOURCE_TYPE_CONTAINER)) 521 Expect(res.Info.Path).To(Equal("share1-subdir")) 522 Expect(res.Info.Size).To(Equal(uint64(10))) 523 }) 524 525 It("stats a shared file", func() { 526 statReq := BaseStatRequest 527 statReq.Ref.Path = "./share1-subdir/share1-subdir-file" 528 res, err := s.Stat(ctx, statReq) 529 Expect(err).ToNot(HaveOccurred()) 530 Expect(res).ToNot(BeNil()) 531 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 532 Expect(res.Info).ToNot(BeNil()) 533 Expect(res.Info.Type).To(Equal(sprovider.ResourceType_RESOURCE_TYPE_FILE)) 534 Expect(res.Info.Path).To(Equal("share1-subdir-file")) 535 Expect(res.Info.Size).To(Equal(uint64(20))) 536 }) 537 }) 538 539 Describe("ListContainer", func() { 540 It("traverses into specific shares", func() { 541 req := BaseListContainerRequest 542 res, err := s.ListContainer(ctx, req) 543 Expect(err).ToNot(HaveOccurred()) 544 Expect(res).ToNot(BeNil()) 545 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 546 Expect(len(res.Infos)).To(Equal(1)) 547 548 entry := res.Infos[0] 549 Expect(entry.Path).To(Equal("share1-shareddir/share1-subdir")) 550 }) 551 552 It("traverses into subfolders of specific shares", func() { 553 req := BaseListContainerRequest 554 req.Ref.Path = "./share1-subdir" 555 res, err := s.ListContainer(ctx, req) 556 Expect(err).ToNot(HaveOccurred()) 557 Expect(res).ToNot(BeNil()) 558 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 559 Expect(len(res.Infos)).To(Equal(1)) 560 561 entry := res.Infos[0] 562 Expect(entry.Path).To(Equal("share1-shareddir/share1-subdir/share1-subdir-file")) 563 }) 564 }) 565 566 Describe("InitiateFileDownload", func() { 567 It("returns not found when not found", func() { 568 gatewayClient.On("InitiateFileDownload", mock.Anything, mock.Anything).Return(&gateway.InitiateFileDownloadResponse{ 569 Status: status.NewNotFound(ctx, "gateway: file not found"), 570 }, nil) 571 572 req := &sprovider.InitiateFileDownloadRequest{ 573 Ref: &sprovider.Reference{ 574 ResourceId: ShareJail, 575 Path: "./share1-shareddir/does-not-exist", 576 }, 577 } 578 res, err := s.InitiateFileDownload(ctx, req) 579 Expect(err).ToNot(HaveOccurred()) 580 Expect(res).ToNot(BeNil()) 581 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_NOT_FOUND)) 582 }) 583 584 It("initiates the download of an existing file", func() { 585 gatewayClient.On("InitiateFileDownload", mock.Anything, mock.Anything).Return(&gateway.InitiateFileDownloadResponse{ 586 Status: status.NewOK(ctx), 587 Protocols: []*gateway.FileDownloadProtocol{ 588 { 589 Opaque: &types.Opaque{}, 590 Protocol: "simple", 591 DownloadEndpoint: "https://localhost:9200/data", 592 Token: "thetoken", 593 }, 594 }, 595 }, nil) 596 req := &sprovider.InitiateFileDownloadRequest{ 597 Ref: &sprovider.Reference{ 598 ResourceId: ShareJail, 599 Path: "./share1-shareddir/share1-subdir/share1-subdir-file", 600 }, 601 } 602 res, err := s.InitiateFileDownload(ctx, req) 603 Expect(err).ToNot(HaveOccurred()) 604 Expect(res).ToNot(BeNil()) 605 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 606 Expect(res.Protocols[0].Protocol).To(Equal("simple")) 607 Expect(res.Protocols[0].DownloadEndpoint).To(Equal("https://localhost:9200/data/thetoken")) 608 }) 609 }) 610 611 Describe("CreateContainer", func() { 612 BeforeEach(func() { 613 gatewayClient.On("CreateContainer", mock.Anything, mock.Anything).Return(&sprovider.CreateContainerResponse{ 614 Status: status.NewOK(ctx), 615 }, nil) 616 }) 617 618 It("refuses to create a top-level container which doesn't belong to a share", func() { 619 req := &sprovider.CreateContainerRequest{ 620 Ref: &sprovider.Reference{ 621 Path: "/shares/invalid-top-level-subdir", 622 }, 623 } 624 res, err := s.CreateContainer(ctx, req) 625 gatewayClient.AssertNotCalled(GinkgoT(), "CreateContainer", mock.Anything, mock.Anything) 626 Expect(err).ToNot(HaveOccurred()) 627 Expect(res).ToNot(BeNil()) 628 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 629 }) 630 631 It("creates a directory", func() { 632 req := &sprovider.CreateContainerRequest{ 633 Ref: &sprovider.Reference{ 634 ResourceId: ShareJail, 635 Path: "./share1-shareddir/share1-newsubdir", 636 }, 637 } 638 res, err := s.CreateContainer(ctx, req) 639 gatewayClient.AssertCalled(GinkgoT(), "CreateContainer", mock.Anything, mock.Anything) 640 Expect(err).ToNot(HaveOccurred()) 641 Expect(res).ToNot(BeNil()) 642 }) 643 }) 644 645 Describe("TouchFile", func() { 646 BeforeEach(func() { 647 gatewayClient.On("TouchFile", mock.Anything, mock.Anything).Return( 648 &sprovider.TouchFileResponse{Status: status.NewOK(ctx)}, nil) 649 }) 650 651 It("touches a file", func() { 652 req := &sprovider.TouchFileRequest{ 653 Ref: &sprovider.Reference{ 654 ResourceId: ShareJail, 655 Path: "./share1-shareddir/newfile.txt", 656 }, 657 } 658 res, err := s.TouchFile(ctx, req) 659 gatewayClient.AssertCalled(GinkgoT(), "TouchFile", mock.Anything, mock.Anything) 660 Expect(err).ToNot(HaveOccurred()) 661 Expect(res).ToNot(BeNil()) 662 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 663 }) 664 }) 665 666 Describe("Delete", func() { 667 BeforeEach(func() { 668 gatewayClient.On("Delete", mock.Anything, mock.Anything).Return( 669 &sprovider.DeleteResponse{Status: status.NewOK(ctx)}, nil) 670 }) 671 672 It("rejects the share when deleting a share", func() { 673 sharingCollaborationClient.On("UpdateReceivedShare", mock.Anything, mock.Anything).Return( 674 &collaboration.UpdateReceivedShareResponse{Status: status.NewOK(ctx)}, nil) 675 req := &sprovider.DeleteRequest{ 676 Ref: &sprovider.Reference{ 677 ResourceId: &sprovider.ResourceId{ 678 StorageId: utils.ShareStorageProviderID, 679 SpaceId: utils.ShareStorageSpaceID, 680 OpaqueId: BaseShare.Share.Id.OpaqueId, 681 }, 682 Path: ".", 683 }, 684 } 685 res, err := s.Delete(ctx, req) 686 gatewayClient.AssertNotCalled(GinkgoT(), "Delete", mock.Anything, mock.Anything) 687 Expect(err).ToNot(HaveOccurred()) 688 Expect(res).ToNot(BeNil()) 689 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 690 691 sharingCollaborationClient.AssertCalled(GinkgoT(), "UpdateReceivedShare", mock.Anything, mock.Anything) 692 }) 693 694 It("deletes a file", func() { 695 req := &sprovider.DeleteRequest{ 696 Ref: &sprovider.Reference{ 697 ResourceId: ShareJail, 698 Path: "./share1-shareddir/share1-subdir/share1-subdir-file", 699 }, 700 } 701 res, err := s.Delete(ctx, req) 702 gatewayClient.AssertCalled(GinkgoT(), "Delete", mock.Anything, mock.Anything) 703 Expect(err).ToNot(HaveOccurred()) 704 Expect(res).ToNot(BeNil()) 705 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 706 }) 707 }) 708 709 Describe("Move", func() { 710 BeforeEach(func() { 711 gatewayClient.On("Move", mock.Anything, mock.Anything).Return(&sprovider.MoveResponse{ 712 Status: status.NewOK(ctx), 713 }, nil) 714 }) 715 716 It("renames a share", func() { 717 sharingCollaborationClient.On("UpdateReceivedShare", mock.Anything, mock.Anything).Return(nil, nil) 718 719 req := &sprovider.MoveRequest{ 720 Source: &sprovider.Reference{ 721 ResourceId: &sprovider.ResourceId{ 722 StorageId: utils.ShareStorageProviderID, 723 SpaceId: utils.ShareStorageSpaceID, 724 OpaqueId: BaseShare.Share.Id.OpaqueId, 725 }, 726 Path: ".", 727 }, 728 Destination: &sprovider.Reference{ 729 ResourceId: ShareJail, 730 Path: "./newname", 731 }, 732 } 733 res, err := s.Move(ctx, req) 734 gatewayClient.AssertNotCalled(GinkgoT(), "Move", mock.Anything, mock.Anything) 735 Expect(err).ToNot(HaveOccurred()) 736 Expect(res).ToNot(BeNil()) 737 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 738 sharingCollaborationClient.AssertCalled(GinkgoT(), "UpdateReceivedShare", mock.Anything, mock.Anything) 739 }) 740 741 It("renames a sharejail entry", func() { 742 sharingCollaborationClient.On("UpdateReceivedShare", mock.Anything, mock.Anything).Return(nil, nil) 743 744 req := &sprovider.MoveRequest{ 745 Source: &sprovider.Reference{ 746 ResourceId: ShareJail, 747 Path: "./share1-shareddir", 748 }, 749 Destination: &sprovider.Reference{ 750 ResourceId: ShareJail, 751 Path: "./share1-shareddir-renamed", 752 }, 753 } 754 res, err := s.Move(ctx, req) 755 gatewayClient.AssertNotCalled(GinkgoT(), "Move", mock.Anything, mock.Anything) 756 Expect(err).ToNot(HaveOccurred()) 757 Expect(res).ToNot(BeNil()) 758 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 759 sharingCollaborationClient.AssertCalled(GinkgoT(), "UpdateReceivedShare", mock.Anything, mock.Anything) 760 }) 761 762 It("refuses to move a file between shares", func() { 763 req := &sprovider.MoveRequest{ 764 Source: &sprovider.Reference{ 765 ResourceId: ShareJail, 766 Path: "./share1-shareddir/share1-shareddir-file", 767 }, 768 Destination: &sprovider.Reference{ 769 ResourceId: ShareJail, 770 Path: "./share2-shareddir2/share1-shareddir-file", 771 }, 772 } 773 res, err := s.Move(ctx, req) 774 gatewayClient.AssertNotCalled(GinkgoT(), "Move", mock.Anything, mock.Anything) 775 Expect(err).ToNot(HaveOccurred()) 776 Expect(res).ToNot(BeNil()) 777 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_UNIMPLEMENTED)) 778 }) 779 780 It("refuses to move a file between shares resolving to the same space", func() { 781 req := &sprovider.MoveRequest{ 782 Source: &sprovider.Reference{ 783 ResourceId: ShareJail, 784 Path: "./share1-shareddir/share1-shareddir-file", 785 }, 786 Destination: &sprovider.Reference{ 787 ResourceId: ShareJail, 788 Path: "./share2-shareddir2/share1-shareddir-file", 789 }, 790 } 791 res, err := s.Move(ctx, req) 792 gatewayClient.AssertNotCalled(GinkgoT(), "Move", mock.Anything, mock.Anything) 793 Expect(err).ToNot(HaveOccurred()) 794 Expect(res).ToNot(BeNil()) 795 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_UNIMPLEMENTED)) 796 }) 797 798 It("moves a file", func() { 799 req := &sprovider.MoveRequest{ 800 Source: &sprovider.Reference{ 801 ResourceId: ShareJail, 802 Path: "./share1-shareddir/share1-shareddir-file", 803 }, 804 Destination: &sprovider.Reference{ 805 ResourceId: ShareJail, 806 Path: "./share1-shareddir/share1-shareddir-filenew", 807 }, 808 } 809 res, err := s.Move(ctx, req) 810 gatewayClient.AssertCalled(GinkgoT(), "Move", mock.Anything, mock.Anything) 811 Expect(err).ToNot(HaveOccurred()) 812 Expect(res).ToNot(BeNil()) 813 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 814 }) 815 }) 816 817 Describe("ListFileVersions", func() { 818 BeforeEach(func() { 819 gatewayClient.On("ListFileVersions", mock.Anything, mock.Anything).Return( 820 &sprovider.ListFileVersionsResponse{ 821 Status: status.NewOK(ctx), 822 Versions: []*sprovider.FileVersion{ 823 { 824 Size: 10, 825 Mtime: 1, 826 Etag: "1", 827 Key: "1", 828 }, 829 { 830 Size: 20, 831 Mtime: 2, 832 Etag: "2", 833 Key: "2", 834 }, 835 }, 836 }, nil) 837 }) 838 839 It("does not try to list versions of shares or the top-level dir", func() { 840 req := &sprovider.ListFileVersionsRequest{ 841 Ref: &sprovider.Reference{ 842 Path: "/shares", 843 }, 844 } 845 res, err := s.ListFileVersions(ctx, req) 846 gatewayClient.AssertNotCalled(GinkgoT(), "ListFileVersions", mock.Anything, mock.Anything) 847 Expect(err).ToNot(HaveOccurred()) 848 Expect(res).ToNot(BeNil()) 849 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 850 851 req = &sprovider.ListFileVersionsRequest{ 852 Ref: &sprovider.Reference{ 853 Path: "/shares/share1-shareddir/", 854 }, 855 } 856 res, err = s.ListFileVersions(ctx, req) 857 gatewayClient.AssertNotCalled(GinkgoT(), "ListFileVersions", mock.Anything, mock.Anything) 858 Expect(err).ToNot(HaveOccurred()) 859 Expect(res).ToNot(BeNil()) 860 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 861 }) 862 863 It("lists versions", func() { 864 req := &sprovider.ListFileVersionsRequest{ 865 Ref: &sprovider.Reference{ 866 ResourceId: ShareJail, 867 Path: "./share1-shareddir/share1-shareddir-file", 868 }, 869 } 870 res, err := s.ListFileVersions(ctx, req) 871 gatewayClient.AssertCalled(GinkgoT(), "ListFileVersions", mock.Anything, mock.Anything) 872 Expect(err).ToNot(HaveOccurred()) 873 Expect(res).ToNot(BeNil()) 874 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 875 Expect(len(res.Versions)).To(Equal(2)) 876 version := res.Versions[0] 877 Expect(version.Key).To(Equal("1")) 878 Expect(version.Etag).To(Equal("1")) 879 Expect(version.Mtime).To(Equal(uint64(1))) 880 Expect(version.Size).To(Equal(uint64(10))) 881 }) 882 }) 883 884 Describe("RestoreFileVersion", func() { 885 BeforeEach(func() { 886 gatewayClient.On("RestoreFileVersion", mock.Anything, mock.Anything).Return( 887 &sprovider.RestoreFileVersionResponse{ 888 Status: status.NewOK(ctx), 889 }, nil) 890 }) 891 892 It("restores a file version", func() { 893 req := &sprovider.RestoreFileVersionRequest{ 894 Ref: &sprovider.Reference{ 895 ResourceId: ShareJail, 896 Path: "./share1-shareddir/share1-shareddir-file", 897 }, 898 Key: "1", 899 } 900 res, err := s.RestoreFileVersion(ctx, req) 901 gatewayClient.AssertCalled(GinkgoT(), "RestoreFileVersion", mock.Anything, mock.Anything) 902 Expect(err).ToNot(HaveOccurred()) 903 Expect(res).ToNot(BeNil()) 904 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 905 }) 906 }) 907 908 Describe("InitiateFileUpload", func() { 909 BeforeEach(func() { 910 gatewayClient.On("InitiateFileUpload", mock.Anything, mock.Anything).Return( 911 &gateway.InitiateFileUploadResponse{ 912 Status: status.NewOK(ctx), 913 Protocols: []*gateway.FileUploadProtocol{ 914 { 915 Opaque: &types.Opaque{}, 916 Protocol: "simple", 917 UploadEndpoint: "https://localhost:9200/data", 918 Token: "thetoken", 919 }, 920 }, 921 }, nil) 922 }) 923 924 It("initiates a file upload", func() { 925 req := &sprovider.InitiateFileUploadRequest{ 926 Ref: &sprovider.Reference{ 927 ResourceId: ShareJail, 928 Path: "./share1-shareddir/share1-shareddir-file", 929 }, 930 } 931 res, err := s.InitiateFileUpload(ctx, req) 932 gatewayClient.AssertCalled(GinkgoT(), "InitiateFileUpload", mock.Anything, mock.Anything) 933 Expect(err).ToNot(HaveOccurred()) 934 Expect(res).ToNot(BeNil()) 935 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 936 Expect(len(res.Protocols)).To(Equal(1)) 937 Expect(res.Protocols[0].Protocol).To(Equal("simple")) 938 Expect(res.Protocols[0].UploadEndpoint).To(Equal("https://localhost:9200/data/thetoken")) 939 }) 940 }) 941 942 Describe("SetArbitraryMetadata", func() { 943 BeforeEach(func() { 944 gatewayClient.On("SetArbitraryMetadata", mock.Anything, mock.Anything).Return(&sprovider.SetArbitraryMetadataResponse{ 945 Status: status.NewOK(ctx), 946 }, nil) 947 }) 948 949 It("sets the metadata", func() { 950 req := &sprovider.SetArbitraryMetadataRequest{ 951 Ref: &sprovider.Reference{ 952 ResourceId: ShareJail, 953 Path: "./share1-shareddir/share1-subdir/share1-subdir-file", 954 }, 955 ArbitraryMetadata: &sprovider.ArbitraryMetadata{ 956 Metadata: map[string]string{ 957 "foo": "bar", 958 }, 959 }, 960 } 961 res, err := s.SetArbitraryMetadata(ctx, req) 962 gatewayClient.AssertCalled(GinkgoT(), "SetArbitraryMetadata", mock.Anything, mock.Anything) 963 Expect(err).ToNot(HaveOccurred()) 964 Expect(res).ToNot(BeNil()) 965 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 966 }) 967 }) 968 }) 969 Context("with two accepted shares for the same resource", func() { 970 BeforeEach(func() { 971 BaseShare.Share.Id.OpaqueId = "multishare1" 972 BaseShare.Share.ResourceId = &sprovider.ResourceId{ 973 StorageId: "share1-storageid", 974 SpaceId: "share1-storageid", 975 OpaqueId: "shareddir-merged", 976 } 977 BaseShare.Share.Permissions = &collaboration.SharePermissions{ 978 Permissions: &sprovider.ResourcePermissions{ 979 Stat: true, 980 }, 981 } 982 BaseShare.Share.Ctime = utils.TSNow() 983 BaseShare.MountPoint = &sprovider.Reference{Path: "share1-shareddir"} 984 BaseShareTwo.Share.Id.OpaqueId = "multishare2" 985 BaseShareTwo.Share.ResourceId = BaseShare.Share.ResourceId 986 BaseShareTwo.Share.Permissions = &collaboration.SharePermissions{ 987 Permissions: &sprovider.ResourcePermissions{ 988 ListContainer: true, 989 }, 990 } 991 BaseShareTwo.MountPoint = BaseShare.MountPoint 992 BaseShareTwo.Share.Ctime = utils.TSNow() 993 994 sharingCollaborationClient.On("ListReceivedShares", mock.Anything, mock.Anything).Return(&collaboration.ListReceivedSharesResponse{ 995 Status: status.NewOK(context.Background()), 996 Shares: []*collaboration.ReceivedShare{BaseShare, BaseShareTwo}, 997 }, nil) 998 sharingCollaborationClient.On("GetReceivedShare", mock.Anything, mock.Anything).Return( 999 func(_ context.Context, req *collaboration.GetReceivedShareRequest, _ ...grpc.CallOption) *collaboration.GetReceivedShareResponse { 1000 switch req.Ref.GetId().GetOpaqueId() { 1001 case BaseShare.Share.Id.OpaqueId: 1002 return &collaboration.GetReceivedShareResponse{ 1003 Status: status.NewOK(context.Background()), 1004 Share: BaseShare, 1005 } 1006 case BaseShareTwo.Share.Id.OpaqueId: 1007 return &collaboration.GetReceivedShareResponse{ 1008 Status: status.NewOK(context.Background()), 1009 Share: BaseShareTwo, 1010 } 1011 default: 1012 return &collaboration.GetReceivedShareResponse{ 1013 Status: status.NewNotFound(context.Background(), "not found"), 1014 } 1015 } 1016 }, nil) 1017 }) 1018 Describe("Stat", func() { 1019 It("merges permissions from multiple shares", func() { 1020 BaseStatRequest.Ref.ResourceId.OpaqueId = "multishare2" 1021 res, err := s.Stat(ctx, BaseStatRequest) 1022 Expect(err).ToNot(HaveOccurred()) 1023 Expect(res).ToNot(BeNil()) 1024 Expect(res.Info).ToNot(BeNil()) 1025 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 1026 Expect(res.Info.Type).To(Equal(sprovider.ResourceType_RESOURCE_TYPE_CONTAINER)) 1027 Expect(res.Info.Path).To(Equal("share1-shareddir")) 1028 Expect(res.Info.PermissionSet.Stat).To(BeTrue()) 1029 Expect(res.Info.PermissionSet.ListContainer).To(BeTrue()) 1030 }) 1031 }) 1032 Describe("ListContainer", func() { 1033 It("Returns just one item", func() { 1034 req := BaseListContainerRequest 1035 req.Ref.ResourceId.OpaqueId = utils.ShareStorageSpaceID 1036 req.Ref.Path = "" 1037 res, err := s.ListContainer(ctx, req) 1038 Expect(err).ToNot(HaveOccurred()) 1039 Expect(res).ToNot(BeNil()) 1040 Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) 1041 Expect(len(res.Infos)).To(Equal(1)) 1042 1043 entry := res.Infos[0] 1044 Expect(entry.Path).To(Equal("share1-shareddir")) 1045 }) 1046 }) 1047 1048 }) 1049 })