github.com/cs3org/reva/v2@v2.27.7/internal/grpc/services/publicshareprovider/publicshareprovider_test.go (about) 1 package publicshareprovider_test 2 3 import ( 4 "context" 5 "time" 6 7 gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" 8 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 9 permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1" 10 rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" 11 link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" 12 providerpb "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 13 "github.com/cs3org/reva/v2/internal/grpc/services/publicshareprovider" 14 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 15 "github.com/cs3org/reva/v2/pkg/errtypes" 16 "github.com/cs3org/reva/v2/pkg/permission" 17 "github.com/cs3org/reva/v2/pkg/publicshare" 18 "github.com/cs3org/reva/v2/pkg/publicshare/manager/registry" 19 "github.com/cs3org/reva/v2/pkg/publicshare/mocks" 20 "github.com/cs3org/reva/v2/pkg/rgrpc/status" 21 "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" 22 "github.com/cs3org/reva/v2/pkg/utils" 23 cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks" 24 . "github.com/onsi/ginkgo/v2" 25 . "github.com/onsi/gomega" 26 "github.com/pkg/errors" 27 "github.com/stretchr/testify/mock" 28 "google.golang.org/grpc" 29 ) 30 31 func createPublicShareProvider(revaConfig map[string]interface{}, gs pool.Selectable[gateway.GatewayAPIClient], sm publicshare.Manager) (link.LinkAPIServer, error) { 32 config, err := publicshareprovider.ParseConfig(revaConfig) 33 if err != nil { 34 return nil, err 35 } 36 passwordPolicy, err := publicshareprovider.ParsePasswordPolicy(config.PasswordPolicy) 37 if err != nil { 38 return nil, err 39 } 40 publicshareproviderService, err := publicshareprovider.New(gs, sm, config, passwordPolicy) 41 if err != nil { 42 return nil, err 43 } 44 return publicshareproviderService.(link.LinkAPIServer), nil 45 } 46 47 var _ = Describe("PublicShareProvider", func() { 48 // declare in container nodes 49 var ( 50 ctx context.Context 51 checkPermissionResponse *permissions.CheckPermissionResponse 52 statResourceResponse *providerpb.StatResponse 53 provider link.LinkAPIServer 54 manager *mocks.Manager 55 gatewayClient *cs3mocks.GatewayAPIClient 56 gatewaySelector pool.Selectable[gateway.GatewayAPIClient] 57 resourcePermissions *providerpb.ResourcePermissions 58 linkPermissions *providerpb.ResourcePermissions 59 createdLink *link.PublicShare 60 revaConfig map[string]interface{} 61 user *userpb.User 62 ) 63 64 BeforeEach(func() { 65 // initialize in setup nodes 66 manager = mocks.NewManager(GinkgoT()) 67 68 registry.Register("mockManager", func(m map[string]interface{}) (publicshare.Manager, error) { 69 return manager, nil 70 }) 71 72 pool.RemoveSelector("GatewaySelector" + "any") 73 gatewayClient = cs3mocks.NewGatewayAPIClient(GinkgoT()) 74 gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient]( 75 "GatewaySelector", 76 "any", 77 func(cc grpc.ClientConnInterface) gateway.GatewayAPIClient { 78 return gatewayClient 79 }, 80 ) 81 82 checkPermissionResponse = &permissions.CheckPermissionResponse{ 83 Status: status.NewOK(ctx), 84 } 85 86 user = &userpb.User{ 87 Id: &userpb.UserId{ 88 OpaqueId: "alice", 89 }, 90 Username: "alice", 91 } 92 ctx = ctxpkg.ContextSetUser(context.Background(), user) 93 94 resourcePermissions = &providerpb.ResourcePermissions{ 95 // all permissions 96 AddGrant: true, 97 CreateContainer: true, 98 Delete: true, 99 GetPath: true, 100 GetQuota: true, 101 InitiateFileDownload: true, 102 InitiateFileUpload: true, 103 ListContainer: true, 104 ListFileVersions: true, 105 ListGrants: true, 106 ListRecycle: true, 107 Move: true, 108 PurgeRecycle: true, 109 RemoveGrant: true, 110 RestoreFileVersion: true, 111 RestoreRecycleItem: true, 112 Stat: true, 113 UpdateGrant: true, 114 DenyGrant: true, 115 } 116 117 statResourceResponse = &providerpb.StatResponse{ 118 Status: status.NewOK(ctx), 119 Info: &providerpb.ResourceInfo{ 120 Type: providerpb.ResourceType_RESOURCE_TYPE_FILE, 121 Path: "./file.txt", 122 PermissionSet: resourcePermissions, 123 }, 124 } 125 126 linkPermissions = &providerpb.ResourcePermissions{ 127 Stat: true, 128 CreateContainer: true, 129 Delete: true, 130 GetPath: true, 131 InitiateFileDownload: true, 132 InitiateFileUpload: true, 133 } 134 135 revaConfig = map[string]interface{}{ 136 "driver": "mockManager", 137 "drivers": map[string]map[string]interface{}{ 138 "jsoncs3": { 139 "provider_addr": "com.owncloud.api.storage-system", 140 "service_user_idp": "internal", 141 "enable_expired_shares_cleanup": true, 142 "gateway_addr": "https://localhost:9200", 143 }, 144 }, 145 "gateway_addr": "https://localhost:9200", 146 "allowed_paths_for_shares": []string{"/NewFolder"}, 147 "writeable_share_must_have_password": false, 148 "public_share_must_have_password": true, 149 "password_policy": map[string]interface{}{ 150 "min_digits": 1, 151 "min_characters": 8, 152 "min_lowercase_characters": 1, 153 "min_uppercase_characters": 1, 154 "min_special_characters": 1, 155 "banned_passwords_list": map[string]struct{}{ 156 "SecretPassword1!": {}, 157 }, 158 }, 159 } 160 var err error 161 provider, err = createPublicShareProvider(revaConfig, gatewaySelector, manager) 162 Expect(err).ToNot(HaveOccurred()) 163 Expect(provider).ToNot(BeNil()) 164 }) 165 Describe("Creating a PublicShare", func() { 166 BeforeEach(func() { 167 gatewayClient. 168 EXPECT(). 169 CheckPermission( 170 mock.Anything, 171 mock.Anything, 172 ). 173 Return(checkPermissionResponse, nil) 174 175 gatewayClient. 176 EXPECT(). 177 Stat(mock.Anything, mock.Anything). 178 Return(statResourceResponse, nil) 179 180 createdLink = &link.PublicShare{ 181 PasswordProtected: true, 182 Permissions: &link.PublicSharePermissions{ 183 Permissions: linkPermissions, 184 }, 185 Creator: user.Id, 186 } 187 }) 188 It("creates a public share with password", func() { 189 manager. 190 EXPECT(). 191 CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 192 Return(createdLink, nil) 193 194 req := &link.CreatePublicShareRequest{ 195 ResourceInfo: &providerpb.ResourceInfo{ 196 Owner: &userpb.UserId{ 197 OpaqueId: "alice", 198 }, 199 Path: "./NewFolder/file.txt", 200 }, 201 Grant: &link.Grant{ 202 Permissions: &link.PublicSharePermissions{ 203 Permissions: linkPermissions, 204 }, 205 Password: "SecretPassw0rd!", 206 }, 207 Description: "test", 208 } 209 210 res, err := provider.CreatePublicShare(ctx, req) 211 Expect(err).ToNot(HaveOccurred()) 212 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 213 Expect(res.GetShare()).To(Equal(createdLink)) 214 }) 215 It("has no user permission to create public share", func() { 216 gatewayClient. 217 EXPECT(). 218 CheckPermission(mock.Anything, mock.Anything). 219 Unset() 220 checkPermissionResponse = &permissions.CheckPermissionResponse{ 221 Status: status.NewPermissionDenied(ctx, nil, "permission denied"), 222 } 223 gatewayClient. 224 EXPECT(). 225 CheckPermission(mock.Anything, mock.Anything). 226 Return(checkPermissionResponse, nil) 227 228 req := &link.CreatePublicShareRequest{} 229 230 res, err := provider.CreatePublicShare(ctx, req) 231 Expect(err).ToNot(HaveOccurred()) 232 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED)) 233 Expect(res.GetStatus().GetMessage()).To(Equal("no permission to create public links")) 234 }) 235 It("has permission to create internal link", func() { 236 // internal links are created with empty permissions 237 linkPermissions := &providerpb.ResourcePermissions{} 238 manager. 239 EXPECT(). 240 CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 241 Return(createdLink, nil) 242 // internal link creation should not check user permissions 243 gatewayClient.EXPECT().CheckPermission(mock.Anything, mock.Anything).Unset() 244 245 req := &link.CreatePublicShareRequest{ 246 ResourceInfo: &providerpb.ResourceInfo{ 247 Owner: &userpb.UserId{ 248 OpaqueId: "alice", 249 }, 250 Path: "./NewFolder/file.txt", 251 }, 252 Grant: &link.Grant{ 253 Permissions: &link.PublicSharePermissions{ 254 Permissions: linkPermissions, 255 }, 256 }, 257 Description: "test", 258 } 259 260 res, err := provider.CreatePublicShare(ctx, req) 261 Expect(err).ToNot(HaveOccurred()) 262 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 263 Expect(res.GetShare()).To(Equal(createdLink)) 264 }) 265 It("has no share permission on the resource, can create internal link", func() { 266 // internal links are created with empty permissions 267 linkPermissions := &providerpb.ResourcePermissions{} 268 manager. 269 EXPECT(). 270 CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 271 Return(createdLink, nil) 272 273 // internal link creation should not check user permissions 274 gatewayClient.EXPECT().CheckPermission(mock.Anything, mock.Anything).Unset() 275 276 // downgrade user permissions on resource to have no share permission 277 resourcePermissions.AddGrant = false 278 279 req := &link.CreatePublicShareRequest{ 280 ResourceInfo: &providerpb.ResourceInfo{ 281 Owner: &userpb.UserId{ 282 OpaqueId: "alice", 283 }, 284 Path: "./NewFolder/file.txt", 285 }, 286 Grant: &link.Grant{ 287 Permissions: &link.PublicSharePermissions{ 288 Permissions: linkPermissions, 289 }, 290 }, 291 Description: "test", 292 } 293 294 res, err := provider.CreatePublicShare(ctx, req) 295 Expect(err).ToNot(HaveOccurred()) 296 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 297 Expect(res.GetShare()).To(Equal(createdLink)) 298 }) 299 It("fails to check create public share user permission", func() { 300 gatewayClient.EXPECT().CheckPermission(mock.Anything, mock.Anything).Unset() 301 gatewayClient. 302 EXPECT(). 303 CheckPermission(mock.Anything, mock.Anything). 304 Return(nil, errors.New("transport error")) 305 306 req := &link.CreatePublicShareRequest{} 307 308 res, err := provider.CreatePublicShare(ctx, req) 309 Expect(err).To(HaveOccurred()) 310 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 311 Expect(res.GetStatus().GetMessage()).To(Equal("failed check user permission to write public link")) 312 }) 313 It("has no share permission on the resource", func() { 314 req := &link.CreatePublicShareRequest{} 315 316 // downgrade user permissions to have no share permission 317 resourcePermissions.AddGrant = false 318 319 res, err := provider.CreatePublicShare(ctx, req) 320 Expect(err).ToNot(HaveOccurred()) 321 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 322 Expect(res.GetStatus().GetMessage()).To(Equal("no share permission")) 323 }) 324 It("tries to share with higher permissions than granted on the resource", func() { 325 // set resource permissions lower than the requested share permissions 326 resourcePermissions.Delete = false 327 328 req := &link.CreatePublicShareRequest{ 329 Grant: &link.Grant{ 330 Permissions: &link.PublicSharePermissions{ 331 Permissions: linkPermissions, 332 }, 333 }, 334 } 335 336 res, err := provider.CreatePublicShare(ctx, req) 337 Expect(err).ToNot(HaveOccurred()) 338 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 339 Expect(res.GetStatus().GetMessage()).To(Equal("insufficient permissions to create that kind of share")) 340 }) 341 It("tries to share inside a path which is not allowed", func() { 342 req := &link.CreatePublicShareRequest{ 343 ResourceInfo: &providerpb.ResourceInfo{ 344 Owner: &userpb.UserId{ 345 OpaqueId: "alice", 346 }, 347 Path: "./file.txt", 348 }, 349 Grant: &link.Grant{ 350 Permissions: &link.PublicSharePermissions{ 351 Permissions: linkPermissions, 352 }, 353 }, 354 } 355 356 res, err := provider.CreatePublicShare(ctx, req) 357 Expect(err).ToNot(HaveOccurred()) 358 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_FAILED_PRECONDITION)) 359 Expect(res.GetStatus().GetMessage()).To(Equal("share creation is not allowed for the specified path")) 360 }) 361 It("tries to share personal space root", func() { 362 req := &link.CreatePublicShareRequest{ 363 ResourceInfo: &providerpb.ResourceInfo{ 364 Owner: &userpb.UserId{ 365 OpaqueId: "alice", 366 }, 367 Path: "./NewFolder/file.txt", 368 Id: &providerpb.ResourceId{ 369 StorageId: "storage-id", 370 OpaqueId: "admin-id", 371 SpaceId: "admin-id", 372 }, 373 Space: &providerpb.StorageSpace{SpaceType: "personal"}, 374 }, 375 Grant: &link.Grant{ 376 Permissions: &link.PublicSharePermissions{ 377 Permissions: linkPermissions, 378 }, 379 }, 380 } 381 382 res, err := provider.CreatePublicShare(ctx, req) 383 Expect(err).ToNot(HaveOccurred()) 384 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 385 Expect(res.GetStatus().GetMessage()).To(Equal("cannot create link on personal space root")) 386 }) 387 It("tries to share a project space root", func() { 388 manager.EXPECT(). 389 CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 390 Return(createdLink, nil) 391 392 req := &link.CreatePublicShareRequest{ 393 ResourceInfo: &providerpb.ResourceInfo{ 394 Owner: &userpb.UserId{ 395 OpaqueId: "alice", 396 }, 397 Path: "./NewFolder/file.txt", 398 Id: &providerpb.ResourceId{ 399 StorageId: "storage-id", 400 OpaqueId: "project-id", 401 SpaceId: "project-id", 402 }, 403 Space: &providerpb.StorageSpace{SpaceType: "project"}, 404 }, 405 Grant: &link.Grant{ 406 Permissions: &link.PublicSharePermissions{ 407 Permissions: linkPermissions, 408 }, 409 Password: "SecretPassw0rd!", 410 }, 411 } 412 413 res, err := provider.CreatePublicShare(ctx, req) 414 Expect(err).ToNot(HaveOccurred()) 415 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 416 Expect(res.GetShare()).To(Equal(createdLink)) 417 }) 418 It("creates a new quicklink", func() { 419 createdLink.Quicklink = true 420 manager.EXPECT(). 421 CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 422 Return(createdLink, nil) 423 424 // no existing quicklinks 425 var links = []*link.PublicShare{} 426 manager.EXPECT().ListPublicShares(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 427 Return(links, nil) 428 429 req := &link.CreatePublicShareRequest{ 430 ResourceInfo: &providerpb.ResourceInfo{ 431 Owner: &userpb.UserId{ 432 OpaqueId: "alice", 433 }, 434 ArbitraryMetadata: &providerpb.ArbitraryMetadata{Metadata: map[string]string{"quicklink": "true"}}, 435 Path: "./NewFolder/file.txt", 436 }, 437 Grant: &link.Grant{ 438 Permissions: &link.PublicSharePermissions{ 439 Permissions: linkPermissions, 440 }, 441 Password: "SecretPassw0rd!", 442 }, 443 } 444 445 res, err := provider.CreatePublicShare(ctx, req) 446 Expect(err).ToNot(HaveOccurred()) 447 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 448 Expect(res.GetShare()).To(Equal(createdLink)) 449 }) 450 It("creates a quicklink which already exists", func() { 451 // create a quicklink with viewer permissions 452 // there is already a quicklink present for that resource 453 // instead of creating a new quicklink, we return the existing quicklink without updating it 454 existingLink := &link.PublicShare{ 455 PasswordProtected: true, 456 Permissions: &link.PublicSharePermissions{ 457 Permissions: linkPermissions, 458 }, 459 Quicklink: true, 460 Description: "Quicklink", 461 } 462 var links = []*link.PublicShare{} 463 links = append(links, existingLink) 464 465 // confirm that list public shares is called with the correct filters 466 manager. 467 EXPECT(). 468 ListPublicShares( 469 mock.Anything, 470 mock.Anything, 471 mock.MatchedBy(func(filters []*link.ListPublicSharesRequest_Filter) bool { 472 return filters[0].Type == link.ListPublicSharesRequest_Filter_TYPE_RESOURCE_ID && 473 filters[0].GetResourceId().GetOpaqueId() == "project-id" && 474 filters[0].GetResourceId().GetStorageId() == "storage-id" && 475 filters[0].GetResourceId().GetSpaceId() == "project-id" 476 }), 477 mock.Anything). 478 Return(links, nil) 479 480 req := &link.CreatePublicShareRequest{ 481 ResourceInfo: &providerpb.ResourceInfo{ 482 Owner: &userpb.UserId{ 483 OpaqueId: "alice", 484 }, 485 // this should create a quicklink 486 ArbitraryMetadata: &providerpb.ArbitraryMetadata{Metadata: map[string]string{"quicklink": "true"}}, 487 Path: "./NewFolder/file.txt", 488 Id: &providerpb.ResourceId{ 489 StorageId: "storage-id", 490 OpaqueId: "project-id", 491 SpaceId: "project-id", 492 }, 493 Space: &providerpb.StorageSpace{SpaceType: "project"}, 494 }, 495 Grant: &link.Grant{ 496 Permissions: &link.PublicSharePermissions{ 497 Permissions: &providerpb.ResourcePermissions{ 498 Stat: true, 499 InitiateFileDownload: true, 500 ListContainer: true, 501 }, 502 }, 503 Password: "SecretPassw0rd!", 504 }, 505 } 506 507 res, err := provider.CreatePublicShare(ctx, req) 508 Expect(err).ToNot(HaveOccurred()) 509 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 510 Expect(res.GetShare()).To(Equal(existingLink)) 511 }) 512 It("create public share with expiration date in the past", func() { 513 yesterday := time.Now().AddDate(0, 0, -1) 514 req := &link.CreatePublicShareRequest{ 515 ResourceInfo: &providerpb.ResourceInfo{ 516 Owner: &userpb.UserId{ 517 OpaqueId: "alice", 518 }, 519 Path: "./NewFolder/file.txt", 520 }, 521 Grant: &link.Grant{ 522 Permissions: &link.PublicSharePermissions{ 523 Permissions: linkPermissions, 524 }, 525 Expiration: utils.TimeToTS(yesterday), 526 }, 527 } 528 529 res, err := provider.CreatePublicShare(ctx, req) 530 Expect(err).ToNot(HaveOccurred()) 531 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 532 Expect(res.GetStatus().GetMessage()).To(ContainSubstring("expiration date is in the past")) 533 }) 534 It("create public share with valid expiration date", func() { 535 tomorrow := time.Now().AddDate(0, 0, 1) 536 tsTomorrow := utils.TimeToTS(tomorrow) 537 538 createdLink.Expiration = tsTomorrow 539 manager. 540 EXPECT(). 541 CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 542 Return(createdLink, nil) 543 544 req := &link.CreatePublicShareRequest{ 545 ResourceInfo: &providerpb.ResourceInfo{ 546 Owner: &userpb.UserId{ 547 OpaqueId: "alice", 548 }, 549 Path: "./NewFolder/file.txt", 550 }, 551 Grant: &link.Grant{ 552 Permissions: &link.PublicSharePermissions{ 553 Permissions: linkPermissions, 554 }, 555 Expiration: tsTomorrow, 556 Password: "SecretPassw0rd!", 557 }, 558 } 559 560 res, err := provider.CreatePublicShare(ctx, req) 561 Expect(err).ToNot(HaveOccurred()) 562 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 563 Expect(res.GetShare()).To(Equal(createdLink)) 564 }) 565 It("creates a public share without a password", func() { 566 req := &link.CreatePublicShareRequest{ 567 ResourceInfo: &providerpb.ResourceInfo{ 568 Owner: &userpb.UserId{ 569 OpaqueId: "alice", 570 }, 571 Path: "./NewFolder/file.txt", 572 }, 573 Grant: &link.Grant{ 574 Permissions: &link.PublicSharePermissions{ 575 Permissions: linkPermissions, 576 }, 577 }, 578 } 579 580 res, err := provider.CreatePublicShare(ctx, req) 581 Expect(err).ToNot(HaveOccurred()) 582 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 583 Expect(res.GetStatus().GetMessage()).To(Equal("password protection is enforced")) 584 }) 585 It("creates a viewable public share without a password", func() { 586 // set password enforcement only on writeable shares 587 revaConfig["public_share_must_have_password"] = false 588 revaConfig["writeable_share_must_have_password"] = true 589 590 provider, err := createPublicShareProvider(revaConfig, gatewaySelector, manager) 591 Expect(err).ToNot(HaveOccurred()) 592 Expect(provider).ToNot(BeNil()) 593 594 linkPermissions = &providerpb.ResourcePermissions{ 595 Stat: true, 596 ListContainer: true, 597 InitiateFileDownload: true, 598 } 599 createdLink.PasswordProtected = false 600 manager. 601 EXPECT(). 602 CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 603 Return(createdLink, nil) 604 605 req := &link.CreatePublicShareRequest{ 606 ResourceInfo: &providerpb.ResourceInfo{ 607 Owner: &userpb.UserId{ 608 OpaqueId: "alice", 609 }, 610 Path: "./NewFolder/file.txt", 611 }, 612 Grant: &link.Grant{ 613 Permissions: &link.PublicSharePermissions{ 614 Permissions: linkPermissions, 615 }, 616 }, 617 } 618 619 res, err := provider.CreatePublicShare(ctx, req) 620 Expect(err).ToNot(HaveOccurred()) 621 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 622 Expect(res.GetShare()).To(Equal(createdLink)) 623 }) 624 It("creates an editable public share without a password", func() { 625 // set password enforcement to false on all public shares 626 revaConfig["public_share_must_have_password"] = false 627 revaConfig["writeable_share_must_have_password"] = false 628 629 provider, err := createPublicShareProvider(revaConfig, gatewaySelector, manager) 630 Expect(err).ToNot(HaveOccurred()) 631 Expect(provider).ToNot(BeNil()) 632 633 linkPermissions = &providerpb.ResourcePermissions{ 634 Stat: true, 635 ListContainer: true, 636 InitiateFileDownload: true, 637 InitiateFileUpload: true, 638 CreateContainer: true, 639 Delete: true, 640 Move: true, 641 } 642 createdLink.PasswordProtected = false 643 manager. 644 EXPECT(). 645 CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 646 Return(createdLink, nil) 647 648 req := &link.CreatePublicShareRequest{ 649 ResourceInfo: &providerpb.ResourceInfo{ 650 Owner: &userpb.UserId{ 651 OpaqueId: "alice", 652 }, 653 Path: "./NewFolder/file.txt", 654 }, 655 Grant: &link.Grant{ 656 Permissions: &link.PublicSharePermissions{ 657 Permissions: linkPermissions, 658 }, 659 }, 660 } 661 662 res, err := provider.CreatePublicShare(ctx, req) 663 Expect(err).ToNot(HaveOccurred()) 664 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 665 Expect(res.GetShare()).To(Equal(createdLink)) 666 }) 667 It("applies the password policy even if no enforcement is configured", func() { 668 // set password enforcement to false on all public shares 669 revaConfig["public_share_must_have_password"] = false 670 revaConfig["writeable_share_must_have_password"] = false 671 672 provider, err := createPublicShareProvider(revaConfig, gatewaySelector, manager) 673 Expect(err).ToNot(HaveOccurred()) 674 Expect(provider).ToNot(BeNil()) 675 676 linkPermissions = &providerpb.ResourcePermissions{ 677 Stat: true, 678 ListContainer: true, 679 InitiateFileDownload: true, 680 InitiateFileUpload: true, 681 CreateContainer: true, 682 Delete: true, 683 Move: true, 684 } 685 686 req := &link.CreatePublicShareRequest{ 687 ResourceInfo: &providerpb.ResourceInfo{ 688 Owner: &userpb.UserId{ 689 OpaqueId: "alice", 690 }, 691 Path: "./NewFolder/file.txt", 692 }, 693 Grant: &link.Grant{ 694 Permissions: &link.PublicSharePermissions{ 695 Permissions: linkPermissions, 696 }, 697 Password: "SecretPassword1!", 698 }, 699 } 700 701 res, err := provider.CreatePublicShare(ctx, req) 702 Expect(err).ToNot(HaveOccurred()) 703 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 704 Expect(res.GetStatus().GetMessage()).To(Equal("unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety")) 705 }) 706 It("returns internal server error when share manager not functional", func() { 707 manager. 708 EXPECT(). 709 CreatePublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 710 Return(nil, errors.New("transport error")) 711 712 req := &link.CreatePublicShareRequest{ 713 ResourceInfo: &providerpb.ResourceInfo{ 714 Owner: &userpb.UserId{ 715 OpaqueId: "alice", 716 }, 717 Path: "./NewFolder/file.txt", 718 }, 719 Grant: &link.Grant{ 720 Permissions: &link.PublicSharePermissions{ 721 Permissions: linkPermissions, 722 }, 723 Password: "SecretPassw0rd123!", 724 }, 725 } 726 727 res, err := provider.CreatePublicShare(ctx, req) 728 Expect(err).ToNot(HaveOccurred()) 729 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 730 Expect(res.GetStatus().GetMessage()).To(Equal("error persisting public share:transport error")) 731 }) 732 }) 733 Describe("Removing a PublicShare", func() { 734 BeforeEach(func() { 735 createdLink.Id = &link.PublicShareId{ 736 OpaqueId: "share-id", 737 } 738 }) 739 It("cannot load existing share", func() { 740 manager. 741 EXPECT(). 742 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 743 Return(nil, errors.New("transport error")) 744 745 req := &link.RemovePublicShareRequest{ 746 Ref: &link.PublicShareReference{ 747 Spec: &link.PublicShareReference_Id{ 748 Id: &link.PublicShareId{ 749 OpaqueId: "share-id", 750 }, 751 }, 752 }, 753 } 754 res, err := provider.RemovePublicShare(ctx, req) 755 Expect(err).To(HaveOccurred()) 756 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 757 Expect(res.GetStatus().GetMessage()).To(Equal("error loading public share")) 758 }) 759 It("can remove an existing share as a creator", func() { 760 manager. 761 EXPECT(). 762 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 763 Once(). 764 Return( 765 createdLink, nil) 766 767 gatewayClient.EXPECT().Stat(mock.Anything, mock.Anything).Return(statResourceResponse, nil) 768 769 manager. 770 EXPECT(). 771 RevokePublicShare( 772 mock.Anything, 773 mock.MatchedBy(func(callingUser *userpb.User) bool { 774 return callingUser == user 775 }), 776 mock.MatchedBy(func(linkRef *link.PublicShareReference) bool { 777 return linkRef.GetId().GetOpaqueId() == "share-id" 778 })). 779 Once(). 780 Return(nil) 781 782 req := &link.RemovePublicShareRequest{ 783 Ref: &link.PublicShareReference{ 784 Spec: &link.PublicShareReference_Id{ 785 Id: &link.PublicShareId{ 786 OpaqueId: "share-id", 787 }, 788 }, 789 }, 790 } 791 res, err := provider.RemovePublicShare(ctx, req) 792 Expect(err).ToNot(HaveOccurred()) 793 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 794 }) 795 It("can remove an existing share as a space manager", func() { 796 // link is neither owned nor created by the acting user 797 createdLink.Creator = &userpb.UserId{ 798 OpaqueId: "admin", 799 } 800 manager. 801 EXPECT(). 802 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 803 Once().Return(createdLink, nil) 804 805 gatewayClient.EXPECT().Stat(mock.Anything, mock.Anything).Return(statResourceResponse, nil) 806 807 manager. 808 EXPECT(). 809 RevokePublicShare( 810 mock.Anything, 811 mock.MatchedBy( 812 func(callingUser *userpb.User) bool { 813 return callingUser == user 814 }), 815 mock.MatchedBy( 816 func(linkRef *link.PublicShareReference) bool { 817 return linkRef.GetId().GetOpaqueId() == "share-id" 818 })). 819 Once().Return(nil) 820 821 req := &link.RemovePublicShareRequest{ 822 Ref: &link.PublicShareReference{ 823 Spec: &link.PublicShareReference_Id{ 824 Id: &link.PublicShareId{ 825 OpaqueId: "share-id", 826 }, 827 }, 828 }, 829 } 830 res, err := provider.RemovePublicShare(ctx, req) 831 Expect(err).ToNot(HaveOccurred()) 832 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 833 }) 834 Context("when the user is not the owner or creator", func() { 835 BeforeEach(func() { 836 // link is neither owned nor created by the acting user 837 createdLink.Creator = &userpb.UserId{ 838 OpaqueId: "admin", 839 } 840 841 // stat the shared resource to get the users resource permissions 842 gatewayClient. 843 EXPECT(). 844 Stat(mock.Anything, mock.Anything). 845 Return(statResourceResponse, nil) 846 }) 847 It("cannot remove an existing share as a space editor", func() { 848 // downgrade user permissions to editor 849 resourcePermissions.AddGrant = false 850 resourcePermissions.UpdateGrant = false 851 resourcePermissions.RemoveGrant = false 852 853 manager. 854 EXPECT(). 855 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 856 Once().Return(createdLink, nil) 857 858 req := &link.RemovePublicShareRequest{ 859 Ref: &link.PublicShareReference{ 860 Spec: &link.PublicShareReference_Id{ 861 Id: &link.PublicShareId{ 862 OpaqueId: "share-id", 863 }, 864 }, 865 }, 866 } 867 res, err := provider.RemovePublicShare(ctx, req) 868 Expect(err).ToNot(HaveOccurred()) 869 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED)) 870 Expect(res.GetStatus().GetMessage()).To(Equal("no permission to delete public share")) 871 }) 872 It("triggers an internal server error when the share manager is not available", func() { 873 manager. 874 EXPECT(). 875 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 876 Once().Return(createdLink, nil) 877 878 // Share manager is not functional 879 By("experiencing a share delete error in the persistence layer") 880 manager.EXPECT().RevokePublicShare(mock.Anything, mock.Anything, mock.Anything). 881 Once().Return(errors.New("delete error")) 882 883 req := &link.RemovePublicShareRequest{ 884 Ref: &link.PublicShareReference{ 885 Spec: &link.PublicShareReference_Id{ 886 Id: &link.PublicShareId{ 887 OpaqueId: "share-id", 888 }, 889 }, 890 }, 891 } 892 res, err := provider.RemovePublicShare(ctx, req) 893 Expect(err).To(HaveOccurred()) 894 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 895 Expect(res.GetStatus().GetMessage()).To(Equal("error deleting public share")) 896 }) 897 It("triggers an internal server error when the storage provider is not functional", func() { 898 manager. 899 EXPECT(). 900 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 901 Once().Return(createdLink, nil) 902 903 // Storage Provider is not functional 904 By("experiencing a transport error when trying to stat the shared resource") 905 gatewayClient.EXPECT(). 906 Stat(mock.Anything, mock.Anything).Unset() 907 gatewayClient.EXPECT(). 908 Stat(mock.Anything, mock.Anything). 909 Return(nil, errors.New("transport error")) 910 911 req := &link.RemovePublicShareRequest{ 912 Ref: &link.PublicShareReference{ 913 Spec: &link.PublicShareReference_Id{ 914 Id: &link.PublicShareId{ 915 OpaqueId: "share-id", 916 }, 917 }, 918 }, 919 } 920 res, err := provider.RemovePublicShare(ctx, req) 921 Expect(err).To(HaveOccurred()) 922 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 923 Expect(res.GetStatus().GetMessage()).To(Equal("failed to stat shared resource")) 924 }) 925 }) 926 }) 927 Describe("Updating a PublicShare", func() { 928 var ( 929 existingLink *link.PublicShare 930 updatedLink *link.PublicShare 931 ) 932 933 BeforeEach(func() { 934 // stat the shared resource to get the users resource permissions 935 gatewayClient. 936 EXPECT(). 937 Stat(mock.Anything, mock.Anything). 938 Return(statResourceResponse, nil) 939 940 existingLink = &link.PublicShare{ 941 Id: &link.PublicShareId{ 942 OpaqueId: "share-id", 943 }, 944 Token: "token", 945 Permissions: &link.PublicSharePermissions{ 946 Permissions: &providerpb.ResourcePermissions{ 947 Stat: true, 948 ListContainer: true, 949 InitiateFileDownload: true, 950 AddGrant: true, 951 }, 952 }, 953 Creator: user.GetId(), 954 } 955 }) 956 Context("succeeds when the user downgrades a public link to internal", func() { 957 BeforeEach(func() { 958 linkPermissions = &providerpb.ResourcePermissions{} 959 updatedLink = &link.PublicShare{ 960 Id: &link.PublicShareId{ 961 OpaqueId: "share-id", 962 }, 963 Permissions: &link.PublicSharePermissions{ 964 Permissions: linkPermissions, 965 }, 966 DisplayName: "Updated Link", 967 } 968 }) 969 It("fails when it cannot load the existing share", func() { 970 manager. 971 EXPECT(). 972 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 973 Return(nil, errors.New("transport error")) 974 975 gatewayClient. 976 EXPECT(). 977 Stat(mock.Anything, mock.Anything). 978 Unset() 979 980 req := &link.UpdatePublicShareRequest{ 981 Update: &link.UpdatePublicShareRequest_Update{ 982 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 983 Grant: &link.Grant{ 984 Permissions: &link.PublicSharePermissions{ 985 Permissions: linkPermissions, 986 }, 987 }, 988 }, 989 } 990 991 res, err := provider.UpdatePublicShare(ctx, req) 992 Expect(err).To(HaveOccurred()) 993 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 994 }) 995 It("fails when it cannot connect to the storage provider", func() { 996 manager. 997 EXPECT(). 998 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 999 Once().Return(existingLink, nil) 1000 1001 gatewayClient. 1002 EXPECT(). 1003 Stat(mock.Anything, mock.Anything). 1004 Unset() 1005 gatewayClient. 1006 EXPECT(). 1007 Stat(mock.Anything, mock.Anything). 1008 Return(nil, errors.New("transport error")) 1009 1010 req := &link.UpdatePublicShareRequest{ 1011 Update: &link.UpdatePublicShareRequest_Update{ 1012 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1013 Grant: &link.Grant{ 1014 Permissions: &link.PublicSharePermissions{ 1015 Permissions: linkPermissions, 1016 }, 1017 }, 1018 }, 1019 } 1020 1021 res, err := provider.UpdatePublicShare(ctx, req) 1022 Expect(err).To(HaveOccurred()) 1023 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 1024 }) 1025 It("fails when it cannot find the shared resource", func() { 1026 manager. 1027 EXPECT(). 1028 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1029 Once().Return(existingLink, nil) 1030 1031 gatewayClient. 1032 EXPECT(). 1033 Stat(mock.Anything, mock.Anything). 1034 Unset() 1035 1036 statResourceResponse.Status = status.NewNotFound(context.TODO(), "not found") 1037 statResourceResponse.Info = nil 1038 gatewayClient. 1039 EXPECT(). 1040 Stat(mock.Anything, mock.Anything). 1041 Return(statResourceResponse, nil) 1042 1043 req := &link.UpdatePublicShareRequest{ 1044 Update: &link.UpdatePublicShareRequest_Update{ 1045 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1046 Grant: &link.Grant{ 1047 Permissions: &link.PublicSharePermissions{ 1048 Permissions: linkPermissions, 1049 }, 1050 }, 1051 }, 1052 } 1053 1054 res, err := provider.UpdatePublicShare(ctx, req) 1055 Expect(err).ToNot(HaveOccurred()) 1056 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_NOT_FOUND)) 1057 }) 1058 It("fails when it cannot store share information", func() { 1059 manager. 1060 EXPECT(). 1061 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1062 Once().Return(existingLink, nil) 1063 1064 manager. 1065 EXPECT(). 1066 UpdatePublicShare(mock.Anything, mock.Anything, mock.Anything). 1067 Once().Return(nil, errors.New("storage error")) 1068 1069 req := &link.UpdatePublicShareRequest{ 1070 Update: &link.UpdatePublicShareRequest_Update{ 1071 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1072 Grant: &link.Grant{ 1073 Permissions: &link.PublicSharePermissions{ 1074 Permissions: linkPermissions, 1075 }, 1076 }, 1077 }, 1078 } 1079 1080 res, err := provider.UpdatePublicShare(ctx, req) 1081 Expect(err).ToNot(HaveOccurred()) 1082 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 1083 Expect(res.GetStatus().GetMessage()).To(Equal("storage error")) 1084 }) 1085 It("fails when the user is neither the creator nor the owner of the share", func() { 1086 existingLink.Creator = &userpb.UserId{ 1087 OpaqueId: "admin", 1088 } 1089 manager. 1090 EXPECT(). 1091 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1092 Once().Return(existingLink, nil) 1093 1094 checkPermissionResponse.Status.Code = rpc.Code_CODE_PERMISSION_DENIED 1095 gatewayClient. 1096 EXPECT(). 1097 CheckPermission(mock.Anything, mock.Anything). 1098 Return(checkPermissionResponse, nil) 1099 1100 gatewayClient. 1101 EXPECT(). 1102 Stat(mock.Anything, mock.Anything). 1103 Unset() 1104 1105 req := &link.UpdatePublicShareRequest{ 1106 Update: &link.UpdatePublicShareRequest_Update{ 1107 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1108 Grant: &link.Grant{ 1109 Permissions: &link.PublicSharePermissions{ 1110 Permissions: linkPermissions, 1111 }, 1112 }, 1113 }, 1114 1115 Ref: &link.PublicShareReference{ 1116 Spec: &link.PublicShareReference_Id{ 1117 Id: &link.PublicShareId{ 1118 OpaqueId: "share-id", 1119 }, 1120 }, 1121 }, 1122 } 1123 1124 res, err := provider.UpdatePublicShare(ctx, req) 1125 Expect(err).ToNot(HaveOccurred()) 1126 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED)) 1127 1128 }) 1129 It("fails when user is neither the resource owner nor the share creator", func() { 1130 existingLink.Creator = &userpb.UserId{ 1131 OpaqueId: "admin", 1132 } 1133 manager. 1134 EXPECT(). 1135 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1136 Once().Return(existingLink, nil) 1137 1138 checkPermissionResponse.Status.Code = rpc.Code_CODE_PERMISSION_DENIED 1139 gatewayClient. 1140 EXPECT(). 1141 CheckPermission(mock.Anything, mock.Anything). 1142 Return(checkPermissionResponse, nil) 1143 1144 gatewayClient. 1145 EXPECT(). 1146 Stat(mock.Anything, mock.Anything). 1147 Unset() 1148 1149 linkPermissions.Delete = true 1150 req := &link.UpdatePublicShareRequest{ 1151 Update: &link.UpdatePublicShareRequest_Update{ 1152 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1153 Grant: &link.Grant{ 1154 Permissions: &link.PublicSharePermissions{ 1155 Permissions: linkPermissions, 1156 }, 1157 }, 1158 }, 1159 1160 Ref: &link.PublicShareReference{ 1161 Spec: &link.PublicShareReference_Id{ 1162 Id: &link.PublicShareId{ 1163 OpaqueId: "share-id", 1164 }, 1165 }, 1166 }, 1167 } 1168 1169 res, err := provider.UpdatePublicShare(ctx, req) 1170 Expect(err).ToNot(HaveOccurred()) 1171 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED)) 1172 1173 }) 1174 It("succeeds", func() { 1175 manager. 1176 EXPECT(). 1177 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1178 Once().Return(existingLink, nil) 1179 1180 manager. 1181 EXPECT(). 1182 UpdatePublicShare(mock.Anything, mock.Anything, mock.Anything). 1183 Once().Return(updatedLink, nil) 1184 1185 req := &link.UpdatePublicShareRequest{ 1186 Update: &link.UpdatePublicShareRequest_Update{ 1187 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1188 Grant: &link.Grant{ 1189 Permissions: &link.PublicSharePermissions{ 1190 Permissions: linkPermissions, 1191 }, 1192 }, 1193 }, 1194 1195 Ref: &link.PublicShareReference{ 1196 Spec: &link.PublicShareReference_Id{ 1197 Id: &link.PublicShareId{ 1198 OpaqueId: "share-id", 1199 }, 1200 }, 1201 }, 1202 } 1203 1204 res, err := provider.UpdatePublicShare(ctx, req) 1205 Expect(err).ToNot(HaveOccurred()) 1206 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 1207 Expect(res.GetShare()).To(Equal(updatedLink)) 1208 }) 1209 It("succeeds even if the user is no manager or owner on the resource", func() { 1210 manager. 1211 EXPECT(). 1212 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1213 Once().Return(existingLink, nil) 1214 1215 manager. 1216 EXPECT(). 1217 UpdatePublicShare(mock.Anything, mock.Anything, mock.Anything). 1218 Once().Return(updatedLink, nil) 1219 1220 statResourceResponse.Info.PermissionSet.UpdateGrant = false 1221 1222 req := &link.UpdatePublicShareRequest{ 1223 Update: &link.UpdatePublicShareRequest_Update{ 1224 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1225 Grant: &link.Grant{ 1226 Permissions: &link.PublicSharePermissions{ 1227 Permissions: linkPermissions, 1228 }, 1229 }, 1230 }, 1231 1232 Ref: &link.PublicShareReference{ 1233 Spec: &link.PublicShareReference_Id{ 1234 Id: &link.PublicShareId{ 1235 OpaqueId: "share-id", 1236 }, 1237 }, 1238 }, 1239 } 1240 1241 res, err := provider.UpdatePublicShare(ctx, req) 1242 Expect(err).ToNot(HaveOccurred()) 1243 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 1244 Expect(res.GetShare()).To(Equal(updatedLink)) 1245 }) 1246 }) 1247 Context("when the user changes permissions", func() { 1248 BeforeEach(func() { 1249 linkPermissions = &providerpb.ResourcePermissions{ 1250 Stat: true, 1251 AddGrant: true, 1252 Delete: true, 1253 Move: true, 1254 InitiateFileDownload: true, 1255 InitiateFileUpload: true, 1256 CreateContainer: true, 1257 ListContainer: true, 1258 ListGrants: true, 1259 } 1260 1261 updatedLink = &link.PublicShare{ 1262 Id: &link.PublicShareId{ 1263 OpaqueId: "share-id", 1264 }, 1265 Permissions: &link.PublicSharePermissions{ 1266 Permissions: linkPermissions, 1267 }, 1268 DisplayName: "Updated Link", 1269 } 1270 1271 manager. 1272 EXPECT(). 1273 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1274 Once().Return(existingLink, nil) 1275 }) 1276 It("fails when the user has not enough permissions on the resource", func() { 1277 statResourceResponse.Info.PermissionSet.Delete = false 1278 1279 req := &link.UpdatePublicShareRequest{ 1280 Update: &link.UpdatePublicShareRequest_Update{ 1281 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1282 Grant: &link.Grant{ 1283 Permissions: &link.PublicSharePermissions{ 1284 Permissions: linkPermissions, 1285 }, 1286 }, 1287 }, 1288 } 1289 1290 res, err := provider.UpdatePublicShare(ctx, req) 1291 Expect(err).ToNot(HaveOccurred()) 1292 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 1293 Expect(res.GetStatus().GetMessage()).To(Equal("insufficient permissions to update that kind of share")) 1294 }) 1295 It("fails when the permissions client is not responding", func() { 1296 gatewayClient. 1297 EXPECT(). 1298 CheckPermission(mock.Anything, mock.Anything). 1299 Return(nil, errors.New("transport error")) 1300 1301 req := &link.UpdatePublicShareRequest{ 1302 Update: &link.UpdatePublicShareRequest_Update{ 1303 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1304 Grant: &link.Grant{ 1305 Permissions: &link.PublicSharePermissions{ 1306 Permissions: linkPermissions, 1307 }, 1308 }, 1309 }, 1310 } 1311 1312 res, err := provider.UpdatePublicShare(ctx, req) 1313 Expect(err).ToNot(HaveOccurred()) 1314 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 1315 Expect(res.GetStatus().GetMessage()).To(Equal("transport error")) 1316 }) 1317 It("fails when the user has no permission to write public shares and is not the creator", func() { 1318 checkPermissionResponse.Status.Code = rpc.Code_CODE_PERMISSION_DENIED 1319 gatewayClient. 1320 EXPECT(). 1321 CheckPermission(mock.Anything, mock.Anything). 1322 Return(checkPermissionResponse, nil) 1323 1324 existingLink.Creator = &userpb.UserId{ 1325 OpaqueId: "admin", 1326 } 1327 gatewayClient. 1328 EXPECT(). 1329 Stat(mock.Anything, mock.Anything). 1330 Unset() 1331 1332 req := &link.UpdatePublicShareRequest{ 1333 Update: &link.UpdatePublicShareRequest_Update{ 1334 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1335 Grant: &link.Grant{ 1336 Permissions: &link.PublicSharePermissions{ 1337 Permissions: linkPermissions, 1338 }, 1339 }, 1340 }, 1341 } 1342 1343 res, err := provider.UpdatePublicShare(ctx, req) 1344 Expect(err).ToNot(HaveOccurred()) 1345 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED)) 1346 Expect(res.GetStatus().GetMessage()).To(Equal("no permission to update public share")) 1347 }) 1348 It("fails when the user is not the creator and has no manager or owner permissions", func() { 1349 existingLink.Creator = &userpb.UserId{ 1350 OpaqueId: "admin", 1351 } 1352 1353 gatewayClient. 1354 EXPECT(). 1355 CheckPermission(mock.Anything, mock.Anything). 1356 Return(checkPermissionResponse, nil) 1357 1358 statResourceResponse.Info.PermissionSet.UpdateGrant = false 1359 1360 req := &link.UpdatePublicShareRequest{ 1361 Update: &link.UpdatePublicShareRequest_Update{ 1362 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1363 Grant: &link.Grant{ 1364 Permissions: &link.PublicSharePermissions{ 1365 Permissions: linkPermissions, 1366 }, 1367 }, 1368 }, 1369 } 1370 1371 res, err := provider.UpdatePublicShare(ctx, req) 1372 Expect(err).ToNot(HaveOccurred()) 1373 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED)) 1374 Expect(res.GetStatus().GetMessage()).To(Equal("no permission to update public share")) 1375 }) 1376 It("fails when the expiration date is in the past", func() { 1377 yesterday := time.Now().AddDate(0, 0, -1) 1378 req := &link.UpdatePublicShareRequest{ 1379 Update: &link.UpdatePublicShareRequest_Update{ 1380 Type: link.UpdatePublicShareRequest_Update_TYPE_EXPIRATION, 1381 Grant: &link.Grant{ 1382 Expiration: utils.TimeToTS(yesterday), 1383 }, 1384 }, 1385 } 1386 1387 res, err := provider.UpdatePublicShare(ctx, req) 1388 Expect(err).ToNot(HaveOccurred()) 1389 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 1390 Expect(res.GetStatus().GetMessage()).To(ContainSubstring("expiration date is in the past")) 1391 }) 1392 It("fails when the password is changed to on a writable share", func() { 1393 gatewayClient. 1394 EXPECT(). 1395 CheckPermission( 1396 mock.Anything, 1397 mock.MatchedBy( 1398 func(req *permissions.CheckPermissionRequest) bool { 1399 return req.GetPermission() == permission.DeleteReadOnlyPassword 1400 }, 1401 ), 1402 ). 1403 Return(checkPermissionResponse, nil) 1404 1405 req := &link.UpdatePublicShareRequest{ 1406 Update: &link.UpdatePublicShareRequest_Update{ 1407 Type: link.UpdatePublicShareRequest_Update_TYPE_PASSWORD, 1408 Grant: &link.Grant{ 1409 Password: "", 1410 }, 1411 }, 1412 } 1413 1414 res, err := provider.UpdatePublicShare(ctx, req) 1415 Expect(err).ToNot(HaveOccurred()) 1416 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 1417 Expect(res.GetStatus().GetMessage()).To(ContainSubstring("password protection is enforced")) 1418 }) 1419 It("fails when the password is already empty on a writable share", func() { 1420 gatewayClient. 1421 EXPECT(). 1422 CheckPermission( 1423 mock.Anything, 1424 mock.MatchedBy( 1425 func(req *permissions.CheckPermissionRequest) bool { 1426 return req.GetPermission() == permission.DeleteReadOnlyPassword 1427 }, 1428 ), 1429 ). 1430 Return(checkPermissionResponse, nil) 1431 1432 req := &link.UpdatePublicShareRequest{ 1433 Update: &link.UpdatePublicShareRequest_Update{ 1434 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1435 Grant: &link.Grant{ 1436 Permissions: &link.PublicSharePermissions{ 1437 Permissions: &providerpb.ResourcePermissions{ 1438 Stat: true, 1439 ListContainer: true, 1440 InitiateFileDownload: true, 1441 Move: true, 1442 }, 1443 }, 1444 }, 1445 }, 1446 } 1447 1448 res, err := provider.UpdatePublicShare(ctx, req) 1449 Expect(err).ToNot(HaveOccurred()) 1450 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 1451 Expect(res.GetStatus().GetMessage()).To(ContainSubstring("password protection is enforced")) 1452 }) 1453 It("succeeds when the password is empty on a readable share with opt out permission", func() { 1454 gatewayClient. 1455 EXPECT(). 1456 CheckPermission( 1457 mock.Anything, 1458 mock.MatchedBy( 1459 func(req *permissions.CheckPermissionRequest) bool { 1460 return req.GetPermission() == permission.DeleteReadOnlyPassword 1461 }, 1462 ), 1463 ). 1464 Return(checkPermissionResponse, nil) 1465 1466 manager. 1467 EXPECT(). 1468 UpdatePublicShare(mock.Anything, mock.Anything, mock.Anything). 1469 Once().Return(updatedLink, nil) 1470 1471 req := &link.UpdatePublicShareRequest{ 1472 Update: &link.UpdatePublicShareRequest_Update{ 1473 Type: link.UpdatePublicShareRequest_Update_TYPE_PERMISSIONS, 1474 Grant: &link.Grant{ 1475 Permissions: &link.PublicSharePermissions{ 1476 Permissions: &providerpb.ResourcePermissions{ 1477 Stat: true, 1478 ListContainer: true, 1479 InitiateFileDownload: true, 1480 }, 1481 }, 1482 }, 1483 }, 1484 } 1485 1486 res, err := provider.UpdatePublicShare(ctx, req) 1487 Expect(err).ToNot(HaveOccurred()) 1488 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_OK)) 1489 Expect(res.GetShare()).To(Equal(updatedLink)) 1490 }) 1491 It("fails when the updated password doesn't fulfil the policy", func() { 1492 gatewayClient. 1493 EXPECT(). 1494 CheckPermission( 1495 mock.Anything, 1496 mock.MatchedBy( 1497 func(req *permissions.CheckPermissionRequest) bool { 1498 return req.GetPermission() == permission.DeleteReadOnlyPassword 1499 }, 1500 ), 1501 ). 1502 Return(checkPermissionResponse, nil) 1503 1504 req := &link.UpdatePublicShareRequest{ 1505 Update: &link.UpdatePublicShareRequest_Update{ 1506 Type: link.UpdatePublicShareRequest_Update_TYPE_PASSWORD, 1507 Grant: &link.Grant{ 1508 Password: "Test", 1509 }, 1510 }, 1511 } 1512 1513 res, err := provider.UpdatePublicShare(ctx, req) 1514 Expect(err).ToNot(HaveOccurred()) 1515 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) 1516 Expect(res.GetStatus().GetMessage()).To(ContainSubstring("characters are required")) 1517 }) 1518 }) 1519 Context("when the user gets a public share", func() { 1520 BeforeEach(func() { 1521 manager. 1522 EXPECT(). 1523 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1524 Once().Return(existingLink, nil) 1525 1526 gatewayClient.EXPECT().Stat(mock.Anything, mock.Anything).Unset() 1527 }) 1528 It("succeeds", func() { 1529 res, err := provider.GetPublicShare(ctx, &link.GetPublicShareRequest{ 1530 Ref: &link.PublicShareReference{ 1531 Spec: &link.PublicShareReference_Id{ 1532 Id: &link.PublicShareId{ 1533 OpaqueId: "share-id", 1534 }, 1535 }, 1536 }, 1537 }) 1538 Expect(err).ToNot(HaveOccurred()) 1539 Expect(res.GetShare()).To(Equal(existingLink)) 1540 }) 1541 It("fails when it finds no share", func() { 1542 manager.EXPECT().GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset() 1543 manager. 1544 EXPECT(). 1545 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1546 Once().Return(nil, errtypes.NotFound("not found")) 1547 res, err := provider.GetPublicShare(ctx, &link.GetPublicShareRequest{ 1548 Ref: &link.PublicShareReference{ 1549 Spec: &link.PublicShareReference_Id{ 1550 Id: &link.PublicShareId{ 1551 OpaqueId: "share-id", 1552 }, 1553 }, 1554 }, 1555 }) 1556 Expect(err).ToNot(HaveOccurred()) 1557 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_NOT_FOUND)) 1558 Expect(res.GetStatus().GetMessage()).To(ContainSubstring("not found")) 1559 }) 1560 It("fails when it finds no share due to internal error", func() { 1561 manager.EXPECT().GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset() 1562 manager. 1563 EXPECT(). 1564 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1565 Once().Return(nil, errtypes.InternalError("internal error")) 1566 res, err := provider.GetPublicShare(ctx, &link.GetPublicShareRequest{ 1567 Ref: &link.PublicShareReference{ 1568 Spec: &link.PublicShareReference_Id{ 1569 Id: &link.PublicShareId{ 1570 OpaqueId: "share-id", 1571 }, 1572 }, 1573 }, 1574 }) 1575 Expect(err).ToNot(HaveOccurred()) 1576 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 1577 Expect(res.GetStatus().GetMessage()).To(ContainSubstring("internal error")) 1578 }) 1579 It("fails when the share manager response is empty", func() { 1580 manager.EXPECT().GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset() 1581 manager. 1582 EXPECT(). 1583 GetPublicShare(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1584 Once().Return(nil, nil) 1585 res, err := provider.GetPublicShare(ctx, &link.GetPublicShareRequest{ 1586 Ref: &link.PublicShareReference{ 1587 Spec: &link.PublicShareReference_Id{ 1588 Id: &link.PublicShareId{ 1589 OpaqueId: "share-id", 1590 }, 1591 }, 1592 }, 1593 }) 1594 Expect(err).ToNot(HaveOccurred()) 1595 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_NOT_FOUND)) 1596 Expect(res.GetStatus().GetMessage()).To(ContainSubstring("not found")) 1597 }) 1598 }) 1599 Context("when the user gets a public share by token", func() { 1600 BeforeEach(func() { 1601 manager. 1602 EXPECT(). 1603 GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1604 Once().Return(existingLink, nil) 1605 1606 gatewayClient.EXPECT().Stat(mock.Anything, mock.Anything).Unset() 1607 }) 1608 It("succeeds", func() { 1609 res, err := provider.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{ 1610 Token: "token", 1611 Authentication: &link.PublicShareAuthentication{ 1612 Spec: &link.PublicShareAuthentication_Password{ 1613 Password: "password", 1614 }, 1615 }, 1616 }) 1617 Expect(err).ToNot(HaveOccurred()) 1618 Expect(res.GetShare()).To(Equal(existingLink)) 1619 }) 1620 It("fails with invalid credentials", func() { 1621 manager.EXPECT().GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset() 1622 manager. 1623 EXPECT(). 1624 GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1625 Once().Return(nil, errtypes.InvalidCredentials("wrong password")) 1626 1627 res, err := provider.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{ 1628 Token: "token", 1629 Authentication: &link.PublicShareAuthentication{ 1630 Spec: &link.PublicShareAuthentication_Password{ 1631 Password: "password", 1632 }, 1633 }, 1634 }) 1635 Expect(err).ToNot(HaveOccurred()) 1636 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_PERMISSION_DENIED)) 1637 Expect(res.GetStatus().GetMessage()).To(Equal("wrong password")) 1638 }) 1639 It("fails with an unknown token", func() { 1640 manager.EXPECT().GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset() 1641 manager. 1642 EXPECT(). 1643 GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1644 Once().Return(nil, errtypes.NotFound("public share not found")) 1645 1646 res, err := provider.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{ 1647 Token: "token", 1648 Authentication: &link.PublicShareAuthentication{ 1649 Spec: &link.PublicShareAuthentication_Password{ 1650 Password: "password", 1651 }, 1652 }, 1653 }) 1654 Expect(err).ToNot(HaveOccurred()) 1655 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_NOT_FOUND)) 1656 Expect(res.GetStatus().GetMessage()).To(Equal("unknown token")) 1657 }) 1658 It("fails with an unknown error", func() { 1659 manager.EXPECT().GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Unset() 1660 manager. 1661 EXPECT(). 1662 GetPublicShareByToken(mock.Anything, mock.Anything, mock.Anything, mock.Anything). 1663 Once().Return(nil, errtypes.InternalError("internal error")) 1664 1665 res, err := provider.GetPublicShareByToken(ctx, &link.GetPublicShareByTokenRequest{ 1666 Token: "token", 1667 Authentication: &link.PublicShareAuthentication{ 1668 Spec: &link.PublicShareAuthentication_Password{ 1669 Password: "password", 1670 }, 1671 }, 1672 }) 1673 Expect(err).ToNot(HaveOccurred()) 1674 Expect(res.GetStatus().GetCode()).To(Equal(rpc.Code_CODE_INTERNAL)) 1675 Expect(res.GetStatus().GetMessage()).To(Equal("unexpected error")) 1676 }) 1677 }) 1678 }) 1679 })