github.com/cs3org/reva/v2@v2.27.7/pkg/share/manager/jsoncs3/jsoncs3_test.go (about) 1 // Copyright 2018-2022 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 jsoncs3_test 20 21 import ( 22 "context" 23 "encoding/json" 24 "os" 25 "path/filepath" 26 "sync" 27 28 gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" 29 groupv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" 30 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 31 collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" 32 provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 33 providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 34 "github.com/cs3org/reva/v2/pkg/conversions" 35 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 36 "github.com/cs3org/reva/v2/pkg/rgrpc/status" 37 "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" 38 sharespkg "github.com/cs3org/reva/v2/pkg/share" 39 "github.com/cs3org/reva/v2/pkg/share/manager/jsoncs3" 40 "github.com/cs3org/reva/v2/pkg/share/manager/jsoncs3/sharecache" 41 "github.com/cs3org/reva/v2/pkg/share/manager/jsoncs3/shareid" 42 "github.com/cs3org/reva/v2/pkg/storage/utils/metadata" 43 "github.com/cs3org/reva/v2/pkg/utils" 44 "github.com/cs3org/reva/v2/tests/cs3mocks/mocks" 45 "github.com/stretchr/testify/mock" 46 "google.golang.org/grpc" 47 "google.golang.org/protobuf/testing/protocmp" 48 "google.golang.org/protobuf/types/known/fieldmaskpb" 49 50 . "github.com/onsi/ginkgo/v2" 51 . "github.com/onsi/gomega" 52 ) 53 54 var _ = Describe("Jsoncs3", func() { 55 var ( 56 user1 = &userpb.User{ 57 Id: &userpb.UserId{ 58 Idp: "https://localhost:9200", 59 OpaqueId: "admin", 60 }, 61 } 62 user2 = &userpb.User{ 63 Id: &userpb.UserId{ 64 Idp: "https://localhost:9200", 65 OpaqueId: "einstein", 66 }, 67 Groups: []string{"group1"}, 68 } 69 70 sharedResource = &providerv1beta1.ResourceInfo{ 71 Id: &providerv1beta1.ResourceId{ 72 StorageId: "storageid", 73 SpaceId: "spaceid", 74 OpaqueId: "opaqueid", 75 }, 76 } 77 78 sharedResource2 = &providerv1beta1.ResourceInfo{ 79 Id: &providerv1beta1.ResourceId{ 80 StorageId: "storageid2", 81 SpaceId: "spaceid2", 82 OpaqueId: "opaqueid2", 83 }, 84 } 85 86 grantee = &userpb.User{ 87 Id: user2.Id, 88 Groups: []string{"users"}, 89 } 90 grant *collaboration.ShareGrant 91 92 groupGrant = &collaboration.ShareGrant{ 93 Grantee: &provider.Grantee{ 94 Type: provider.GranteeType_GRANTEE_TYPE_GROUP, 95 Id: &provider.Grantee_GroupId{GroupId: &groupv1beta1.GroupId{ 96 OpaqueId: "group1", 97 }}, 98 }, 99 Permissions: &collaboration.SharePermissions{ 100 Permissions: &providerv1beta1.ResourcePermissions{ 101 InitiateFileUpload: false, 102 }, 103 }, 104 } 105 storage metadata.Storage 106 client *mocks.GatewayAPIClient 107 tmpdir string 108 m *jsoncs3.Manager 109 110 ctx = ctxpkg.ContextSetUser(context.Background(), user1) 111 granteeCtx = ctxpkg.ContextSetUser(context.Background(), user2) 112 otherCtx = ctxpkg.ContextSetUser(context.Background(), &userpb.User{Id: &userpb.UserId{OpaqueId: "otheruser"}}) 113 114 // helper functions 115 shareBykey = func(key *collaboration.ShareKey) *collaboration.Share { 116 s, err := m.GetShare(ctx, &collaboration.ShareReference{ 117 Spec: &collaboration.ShareReference_Key{ 118 Key: key, 119 }, 120 }) 121 ExpectWithOffset(1, err).ToNot(HaveOccurred()) 122 ExpectWithOffset(1, s).ToNot(BeNil()) 123 return s 124 } 125 126 mockStat = func(ref *provider.Reference, info *provider.ResourceInfo) { 127 client.On("Stat", mock.Anything, mock.MatchedBy(func(req *provider.StatRequest) bool { 128 return utils.ResourceIDEqual(req.Ref.ResourceId, ref.ResourceId) && 129 (ref.Path == "" || req.Ref.Path == ref.Path) 130 })).Return(&provider.StatResponse{ 131 Status: status.NewOK(ctx), 132 Info: info, 133 }, nil) 134 } 135 ) 136 137 BeforeEach(func() { 138 grant = &collaboration.ShareGrant{ 139 Grantee: &provider.Grantee{ 140 Type: provider.GranteeType_GRANTEE_TYPE_USER, 141 Id: &provider.Grantee_UserId{UserId: grantee.GetId()}, 142 }, 143 Permissions: &collaboration.SharePermissions{ 144 Permissions: &providerv1beta1.ResourcePermissions{ 145 InitiateFileUpload: false, 146 }, 147 }, 148 } 149 150 var err error 151 tmpdir, err = os.MkdirTemp("", "jsoncs3-test") 152 Expect(err).ToNot(HaveOccurred()) 153 154 err = os.MkdirAll(tmpdir, 0755) 155 Expect(err).ToNot(HaveOccurred()) 156 157 storage, err = metadata.NewDiskStorage(tmpdir) 158 Expect(err).ToNot(HaveOccurred()) 159 160 pool.RemoveSelector("GatewaySelector" + "com.owncloud.api.gateway") 161 client = &mocks.GatewayAPIClient{} 162 gatewaySelector := pool.GetSelector[gatewayv1beta1.GatewayAPIClient]( 163 "GatewaySelector", 164 "com.owncloud.api.gateway", 165 func(cc grpc.ClientConnInterface) gatewayv1beta1.GatewayAPIClient { 166 return client 167 }, 168 ) 169 m, err = jsoncs3.New(storage, gatewaySelector, 0, nil, 0) 170 Expect(err).ToNot(HaveOccurred()) 171 }) 172 173 AfterEach(func() { 174 if tmpdir != "" { 175 os.RemoveAll(tmpdir) 176 } 177 }) 178 179 Describe("Load", func() { 180 It("loads shares including state and mountpoint information", func() { 181 182 sharesChan := make(chan *collaboration.Share) 183 receivedChan := make(chan sharespkg.ReceivedShareWithUser) 184 185 share := &collaboration.Share{ 186 Id: &collaboration.ShareId{OpaqueId: "1iaeiae$vlcvlcvlc!pzbpzbpzb"}, 187 ResourceId: &provider.ResourceId{StorageId: "1iaeiae", SpaceId: "vlcvlcvlc", OpaqueId: "abcd"}, 188 Creator: user1.GetId(), 189 Grantee: &provider.Grantee{ 190 Type: provider.GranteeType_GRANTEE_TYPE_USER, 191 Id: &provider.Grantee_UserId{UserId: grantee.GetId()}, 192 }, 193 Permissions: &collaboration.SharePermissions{ 194 Permissions: &provider.ResourcePermissions{ 195 GetPath: true, 196 InitiateFileDownload: true, 197 ListFileVersions: true, 198 ListContainer: true, 199 Stat: true, 200 }, 201 }, 202 } 203 204 wg := sync.WaitGroup{} 205 wg.Add(2) 206 go func() { 207 err := m.Load(ctx, sharesChan, receivedChan) 208 Expect(err).ToNot(HaveOccurred()) 209 wg.Done() 210 }() 211 go func() { 212 sharesChan <- share 213 close(sharesChan) 214 close(receivedChan) 215 wg.Done() 216 }() 217 wg.Wait() 218 Eventually(sharesChan).Should(BeClosed()) 219 Eventually(receivedChan).Should(BeClosed()) 220 221 s, err := m.GetShare(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{ 222 Id: share.Id, 223 }}) 224 225 Expect(err).ToNot(HaveOccurred()) 226 Expect(s.ResourceId.OpaqueId).To(Equal(share.ResourceId.OpaqueId)) 227 }) 228 }) 229 230 Describe("Share", func() { 231 It("fails if the share already exists", func() { 232 _, err := m.Share(ctx, sharedResource, grant) 233 Expect(err).ToNot(HaveOccurred()) 234 _, err = m.Share(ctx, sharedResource, grant) 235 Expect(err).To(HaveOccurred()) 236 }) 237 238 It("creates a user share", func() { 239 share, err := m.Share(ctx, sharedResource, grant) 240 Expect(err).ToNot(HaveOccurred()) 241 242 Expect(share).ToNot(BeNil()) 243 Expect(share.ResourceId).To(Equal(sharedResource.Id)) 244 }) 245 246 It("creates a group share", func() { 247 share, err := m.Share(ctx, sharedResource, groupGrant) 248 Expect(err).ToNot(HaveOccurred()) 249 250 Expect(share).ToNot(BeNil()) 251 Expect(share.ResourceId).To(Equal(sharedResource.Id)) 252 }) 253 254 It("persists the share", func() { 255 _, err := m.Share(ctx, sharedResource, grant) 256 Expect(err).ToNot(HaveOccurred()) 257 258 s := shareBykey(&collaboration.ShareKey{ 259 ResourceId: sharedResource.Id, 260 Grantee: grant.Grantee, 261 }) 262 Expect(s).ToNot(BeNil()) 263 264 m, err = jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 265 Expect(err).ToNot(HaveOccurred()) 266 267 s = shareBykey(&collaboration.ShareKey{ 268 ResourceId: sharedResource.Id, 269 Grantee: grant.Grantee, 270 }) 271 Expect(s).ToNot(BeNil()) 272 }) 273 }) 274 275 Context("with a space manager", func() { 276 var ( 277 share *collaboration.Share 278 279 manager = &userpb.User{ 280 Id: &userpb.UserId{ 281 Idp: "https://localhost:9200", 282 OpaqueId: "spacemanager", 283 }, 284 } 285 managerCtx context.Context 286 ) 287 288 BeforeEach(func() { 289 managerCtx = ctxpkg.ContextSetUser(context.Background(), manager) 290 291 var err error 292 share, err = m.Share(ctx, sharedResource, grant) 293 Expect(err).ToNot(HaveOccurred()) 294 295 _, err = m.Share(ctx, &providerv1beta1.ResourceInfo{ 296 Id: &providerv1beta1.ResourceId{ 297 StorageId: "storageid", 298 SpaceId: "spaceid", 299 OpaqueId: "spaceid", 300 }, 301 }, &collaboration.ShareGrant{ 302 Grantee: &providerv1beta1.Grantee{ 303 Type: provider.GranteeType_GRANTEE_TYPE_USER, 304 Id: &providerv1beta1.Grantee_UserId{UserId: manager.Id}, 305 }, 306 Permissions: &collaboration.SharePermissions{ 307 Permissions: conversions.NewManagerRole().CS3ResourcePermissions(), 308 }, 309 }) 310 Expect(err).ToNot(HaveOccurred()) 311 }) 312 313 Describe("ListShares", func() { 314 BeforeEach(func() { 315 mockStat( 316 &provider.Reference{ResourceId: sharedResource.Id}, 317 &providerv1beta1.ResourceInfo{PermissionSet: &providerv1beta1.ResourcePermissions{ListGrants: true}}, 318 ) 319 }) 320 It("returns the share requested by id even though it's not owned or created by the manager", func() { 321 322 shares, err := m.ListShares(managerCtx, []*collaboration.Filter{ 323 { 324 Type: collaboration.Filter_TYPE_RESOURCE_ID, 325 Term: &collaboration.Filter_ResourceId{ 326 ResourceId: sharedResource.Id, 327 }, 328 }, 329 }) 330 Expect(err).ToNot(HaveOccurred()) 331 Expect(shares).To(HaveLen(1)) 332 Expect(shares[0].Id).To(Equal(share.Id)) 333 }) 334 }) 335 }) 336 337 Context("with an existing share", func() { 338 var ( 339 share *collaboration.Share 340 shareRef *collaboration.ShareReference 341 ) 342 343 BeforeEach(func() { 344 var err error 345 share, err = m.Share(ctx, sharedResource, grant) 346 Expect(err).ToNot(HaveOccurred()) 347 348 shareRef = &collaboration.ShareReference{ 349 Spec: &collaboration.ShareReference_Id{ 350 Id: &collaboration.ShareId{ 351 OpaqueId: share.Id.OpaqueId, 352 }, 353 }, 354 } 355 356 }) 357 358 Describe("GetShare", func() { 359 BeforeEach(func() { 360 mockStat( 361 &provider.Reference{ResourceId: sharedResource.Id}, 362 &providerv1beta1.ResourceInfo{PermissionSet: &providerv1beta1.ResourcePermissions{ListGrants: false}}, 363 ) 364 }) 365 It("handles unknown ids", func() { 366 s, err := m.GetShare(ctx, &collaboration.ShareReference{ 367 Spec: &collaboration.ShareReference_Id{ 368 Id: &collaboration.ShareId{ 369 OpaqueId: "unknown-id", 370 }, 371 }, 372 }) 373 Expect(s).To(BeNil()) 374 Expect(err).To(HaveOccurred()) 375 }) 376 377 It("handles unknown keys", func() { 378 s, err := m.GetShare(ctx, &collaboration.ShareReference{ 379 Spec: &collaboration.ShareReference_Key{ 380 Key: &collaboration.ShareKey{ 381 ResourceId: &providerv1beta1.ResourceId{ 382 OpaqueId: "unknown", 383 }, 384 Grantee: grant.Grantee, 385 }, 386 }, 387 }) 388 Expect(s).To(BeNil()) 389 Expect(err).To(HaveOccurred()) 390 }) 391 392 It("considers the resource id part of the key", func() { 393 s, err := m.GetShare(ctx, &collaboration.ShareReference{ 394 Spec: &collaboration.ShareReference_Key{ 395 Key: &collaboration.ShareKey{ 396 ResourceId: &providerv1beta1.ResourceId{ 397 StorageId: "storageid", 398 SpaceId: "spaceid", 399 OpaqueId: "unknown", 400 }, 401 Grantee: grant.Grantee, 402 }, 403 }, 404 }) 405 Expect(s).To(BeNil()) 406 Expect(err).To(HaveOccurred()) 407 }) 408 409 It("retrieves an existing share by id", func() { 410 s, err := m.GetShare(ctx, shareRef) 411 Expect(err).ToNot(HaveOccurred()) 412 Expect(s).ToNot(BeNil()) 413 Expect(share.ResourceId).To(Equal(sharedResource.Id)) 414 }) 415 416 It("retrieves an existing share by key", func() { 417 s := shareBykey(&collaboration.ShareKey{ 418 ResourceId: sharedResource.Id, 419 Grantee: grant.Grantee, 420 }) 421 Expect(s.ResourceId).To(BeComparableTo(sharedResource.Id, protocmp.Transform())) 422 Expect(s.Id.OpaqueId).To(Equal(share.Id.OpaqueId)) 423 }) 424 425 It("reloads the provider cache when it is outdated", func() { 426 s, err := m.GetShare(ctx, shareRef) 427 Expect(err).ToNot(HaveOccurred()) 428 Expect(s).ToNot(BeNil()) 429 Expect(s.Permissions.Permissions.InitiateFileUpload).To(BeFalse()) 430 431 // Change providercache on disk 432 spaces, ok := m.Cache.Providers.Load("storageid") 433 Expect(ok).To(BeTrue()) 434 cache, ok := spaces.Spaces.Load("spaceid") 435 Expect(ok).To(BeTrue()) 436 cache.Shares[share.Id.OpaqueId].Permissions.Permissions.InitiateFileUpload = true 437 bytes, err := json.Marshal(cache) 438 Expect(err).ToNot(HaveOccurred()) 439 Expect(storage.SimpleUpload(context.Background(), "storages/storageid/spaceid.json", bytes)).To(Succeed()) 440 Expect(err).ToNot(HaveOccurred()) 441 442 // Reset providercache in memory 443 cache.Shares[share.Id.OpaqueId].Permissions.Permissions.InitiateFileUpload = false 444 445 // Set local cache etag to something other then on disk 446 cache.Etag = "reset1" // trigger reload 447 s, err = m.GetShare(ctx, shareRef) 448 Expect(err).ToNot(HaveOccurred()) 449 Expect(s).ToNot(BeNil()) 450 Expect(s.Permissions.Permissions.InitiateFileUpload).To(BeTrue()) 451 }) 452 453 It("loads the cache when it doesn't have an entry", func() { 454 m, err := jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 455 Expect(err).ToNot(HaveOccurred()) 456 457 s, err := m.GetShare(ctx, shareRef) 458 Expect(err).ToNot(HaveOccurred()) 459 Expect(s).ToNot(BeNil()) 460 }) 461 462 It("does not return other users' shares", func() { 463 s, err := m.GetShare(otherCtx, shareRef) 464 Expect(err).To(HaveOccurred()) 465 Expect(s).To(BeNil()) 466 }) 467 }) 468 469 Describe("UnShare", func() { 470 It("does not remove shares of other users", func() { 471 err := m.Unshare(otherCtx, &collaboration.ShareReference{ 472 Spec: &collaboration.ShareReference_Id{ 473 Id: &collaboration.ShareId{ 474 OpaqueId: share.Id.OpaqueId, 475 }, 476 }, 477 }) 478 479 Expect(err).To(HaveOccurred()) 480 }) 481 482 It("removes an existing share", func() { 483 err := m.Unshare(ctx, &collaboration.ShareReference{ 484 Spec: &collaboration.ShareReference_Id{ 485 Id: &collaboration.ShareId{ 486 OpaqueId: share.Id.OpaqueId, 487 }, 488 }, 489 }) 490 Expect(err).ToNot(HaveOccurred()) 491 492 s, err := m.GetShare(ctx, &collaboration.ShareReference{ 493 Spec: &collaboration.ShareReference_Key{ 494 Key: &collaboration.ShareKey{ 495 ResourceId: sharedResource.Id, 496 Grantee: grant.Grantee, 497 }, 498 }, 499 }) 500 Expect(err).To(HaveOccurred()) 501 Expect(s).To(BeNil()) 502 }) 503 504 It("removes an existing share from the storage", func() { 505 err := m.Unshare(ctx, &collaboration.ShareReference{ 506 Spec: &collaboration.ShareReference_Id{ 507 Id: &collaboration.ShareId{ 508 OpaqueId: share.Id.OpaqueId, 509 }, 510 }, 511 }) 512 Expect(err).ToNot(HaveOccurred()) 513 514 m, err = jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 515 Expect(err).ToNot(HaveOccurred()) 516 517 s, err := m.GetShare(ctx, &collaboration.ShareReference{ 518 Spec: &collaboration.ShareReference_Key{ 519 Key: &collaboration.ShareKey{ 520 ResourceId: sharedResource.Id, 521 Grantee: grant.Grantee, 522 }, 523 }, 524 }) 525 Expect(err).To(HaveOccurred()) 526 Expect(s).To(BeNil()) 527 }) 528 }) 529 530 Describe("UpdateShare", func() { 531 BeforeEach(func() { 532 mockStat( 533 &provider.Reference{ResourceId: sharedResource.Id}, 534 &providerv1beta1.ResourceInfo{PermissionSet: &providerv1beta1.ResourcePermissions{ListGrants: false}}, 535 ) 536 }) 537 It("does not update shares of other users", func() { 538 _, err := m.UpdateShare(otherCtx, &collaboration.ShareReference{ 539 Spec: &collaboration.ShareReference_Id{ 540 Id: &collaboration.ShareId{ 541 OpaqueId: share.Id.OpaqueId, 542 }, 543 }, 544 }, &collaboration.SharePermissions{ 545 Permissions: &providerv1beta1.ResourcePermissions{ 546 InitiateFileUpload: true, 547 }, 548 }, nil, nil) 549 Expect(err).To(HaveOccurred()) 550 }) 551 552 It("updates an existing share", func() { 553 s := shareBykey(&collaboration.ShareKey{ 554 ResourceId: sharedResource.Id, 555 Grantee: grant.Grantee, 556 }) 557 Expect(s.GetPermissions().GetPermissions().InitiateFileUpload).To(BeFalse()) 558 559 // enhance privileges 560 us, err := m.UpdateShare(ctx, &collaboration.ShareReference{ 561 Spec: &collaboration.ShareReference_Id{ 562 Id: &collaboration.ShareId{ 563 OpaqueId: share.Id.OpaqueId, 564 }, 565 }, 566 }, &collaboration.SharePermissions{ 567 Permissions: &providerv1beta1.ResourcePermissions{ 568 InitiateFileUpload: true, 569 }, 570 }, nil, nil) 571 Expect(err).ToNot(HaveOccurred()) 572 Expect(us).ToNot(BeNil()) 573 Expect(us.GetPermissions().GetPermissions().InitiateFileUpload).To(BeTrue()) 574 575 s = shareBykey(&collaboration.ShareKey{ 576 ResourceId: sharedResource.Id, 577 Grantee: grant.Grantee, 578 }) 579 Expect(s.GetPermissions().GetPermissions().InitiateFileUpload).To(BeTrue()) 580 581 // reduce privileges 582 us, err = m.UpdateShare(ctx, &collaboration.ShareReference{ 583 Spec: &collaboration.ShareReference_Id{ 584 Id: &collaboration.ShareId{ 585 OpaqueId: share.Id.OpaqueId, 586 }, 587 }, 588 }, &collaboration.SharePermissions{ 589 Permissions: &providerv1beta1.ResourcePermissions{ 590 InitiateFileUpload: false, 591 }, 592 }, nil, nil) 593 Expect(err).ToNot(HaveOccurred()) 594 Expect(us).ToNot(BeNil()) 595 Expect(us.GetPermissions().GetPermissions().InitiateFileUpload).To(BeFalse()) 596 597 s = shareBykey(&collaboration.ShareKey{ 598 ResourceId: sharedResource.Id, 599 Grantee: grant.Grantee, 600 }) 601 Expect(s.GetPermissions().GetPermissions().InitiateFileUpload).To(BeFalse()) 602 }) 603 604 It("persists the change", func() { 605 s := shareBykey(&collaboration.ShareKey{ 606 ResourceId: sharedResource.Id, 607 Grantee: grant.Grantee, 608 }) 609 Expect(s.GetPermissions().GetPermissions().InitiateFileUpload).To(BeFalse()) 610 611 // enhance privileges 612 us, err := m.UpdateShare(ctx, &collaboration.ShareReference{ 613 Spec: &collaboration.ShareReference_Id{ 614 Id: &collaboration.ShareId{ 615 OpaqueId: share.Id.OpaqueId, 616 }, 617 }, 618 }, &collaboration.SharePermissions{ 619 Permissions: &providerv1beta1.ResourcePermissions{ 620 InitiateFileUpload: true, 621 }, 622 }, nil, nil) 623 Expect(err).ToNot(HaveOccurred()) 624 Expect(us).ToNot(BeNil()) 625 Expect(us.GetPermissions().GetPermissions().InitiateFileUpload).To(BeTrue()) 626 627 m, err = jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 628 Expect(err).ToNot(HaveOccurred()) 629 630 s = shareBykey(&collaboration.ShareKey{ 631 ResourceId: sharedResource.Id, 632 Grantee: grant.Grantee, 633 }) 634 Expect(s.GetPermissions().GetPermissions().InitiateFileUpload).To(BeTrue()) 635 }) 636 }) 637 638 Describe("ListShares", func() { 639 It("lists an existing share", func() { 640 shares, err := m.ListShares(ctx, nil) 641 Expect(err).ToNot(HaveOccurred()) 642 Expect(shares).To(HaveLen(1)) 643 644 Expect(shares[0].Id).To(Equal(share.Id)) 645 }) 646 647 It("syncronizes the provider cache before listing", func() { 648 shares, err := m.ListShares(ctx, nil) 649 Expect(err).ToNot(HaveOccurred()) 650 Expect(len(shares)).To(Equal(1)) 651 Expect(shares[0].Id.OpaqueId).To(Equal(share.Id.OpaqueId)) 652 Expect(shares[0].Permissions.Permissions.InitiateFileUpload).To(BeFalse()) 653 654 // Change providercache on disk 655 spaces, ok := m.Cache.Providers.Load("storageid") 656 Expect(ok).To(BeTrue()) 657 cache, ok := spaces.Spaces.Load("spaceid") 658 Expect(ok).To(BeTrue()) 659 cache.Shares[share.Id.OpaqueId].Permissions.Permissions.InitiateFileUpload = true 660 bytes, err := json.Marshal(cache) 661 Expect(err).ToNot(HaveOccurred()) 662 Expect(storage.SimpleUpload(context.Background(), "storages/storageid/spaceid.json", bytes)).To(Succeed()) 663 Expect(err).ToNot(HaveOccurred()) 664 665 // Reset providercache in memory 666 cache.Shares[share.Id.OpaqueId].Permissions.Permissions.InitiateFileUpload = false 667 668 cache.Etag = "reset1" // trigger reload 669 shares, err = m.ListShares(ctx, nil) 670 Expect(err).ToNot(HaveOccurred()) 671 Expect(len(shares)).To(Equal(1)) 672 Expect(shares[0].Id.OpaqueId).To(Equal(share.Id.OpaqueId)) 673 Expect(shares[0].Permissions.Permissions.InitiateFileUpload).To(BeTrue()) 674 }) 675 676 It("syncronizes the share cache before listing", func() { 677 shares, err := m.ListShares(ctx, nil) 678 Expect(err).ToNot(HaveOccurred()) 679 Expect(len(shares)).To(Equal(1)) 680 681 // Add a second cache to the provider cache so it can be referenced 682 secondShareID := "storageid" + shareid.IDDelimiter + "spaceid" + shareid.IDDelimiter + "secondshare" 683 Expect(m.Cache.Add(ctx, "storageid", "spaceid", secondShareID, &collaboration.Share{ 684 Id: &collaboration.ShareId{OpaqueId: secondShareID}, 685 Creator: user1.Id, 686 })).To(Succeed()) 687 688 cache := sharecache.UserShareCache{ 689 Etag: "etag1", 690 UserShares: map[string]*sharecache.SpaceShareIDs{ 691 "storageid" + shareid.IDDelimiter + "spaceid": { 692 IDs: map[string]struct{}{ 693 shares[0].Id.OpaqueId: {}, 694 "storageid" + shareid.IDDelimiter + "spaceid" + shareid.IDDelimiter + "secondshare": {}, 695 }, 696 }, 697 }, 698 } 699 bytes, err := json.Marshal(cache) 700 Expect(err).ToNot(HaveOccurred()) 701 err = os.WriteFile(filepath.Join(tmpdir, "users/admin/created.json"), bytes, 0x755) 702 Expect(err).ToNot(HaveOccurred()) 703 704 cc, _ := m.CreatedCache.UserShares.Load("admin") 705 cc.Etag = "reset1" // trigger reload 706 shares, err = m.ListShares(ctx, nil) 707 Expect(err).ToNot(HaveOccurred()) 708 Expect(len(shares)).To(Equal(2)) 709 }) 710 711 It("filters by resource id", func() { 712 shares, err := m.ListShares(ctx, []*collaboration.Filter{ 713 { 714 Type: collaboration.Filter_TYPE_RESOURCE_ID, 715 Term: &collaboration.Filter_ResourceId{ 716 ResourceId: &providerv1beta1.ResourceId{ 717 StorageId: "storageid", 718 SpaceId: "spaceid", 719 OpaqueId: "somethingelse", 720 }, 721 }, 722 }, 723 }) 724 Expect(err).ToNot(HaveOccurred()) 725 Expect(shares).To(HaveLen(0)) 726 }) 727 }) 728 729 Describe("ListReceivedShares", func() { 730 It("lists the received shares", func() { 731 received, err := m.ListReceivedShares(granteeCtx, []*collaboration.Filter{}, nil) 732 Expect(err).ToNot(HaveOccurred()) 733 Expect(len(received)).To(Equal(1)) 734 Expect(received[0].Share.ResourceId).To(BeComparableTo(sharedResource.Id, protocmp.Transform())) 735 Expect(received[0].State).To(Equal(collaboration.ShareState_SHARE_STATE_PENDING)) 736 }) 737 738 It("syncronizes the provider cache before listing", func() { 739 received, err := m.ListReceivedShares(granteeCtx, []*collaboration.Filter{}, nil) 740 Expect(err).ToNot(HaveOccurred()) 741 Expect(len(received)).To(Equal(1)) 742 Expect(received[0].Share.Permissions.Permissions.InitiateFileUpload).To(BeFalse()) 743 744 // Change providercache on disk 745 spaces, ok := m.Cache.Providers.Load("storageid") 746 Expect(ok).To(BeTrue()) 747 cache, ok := spaces.Spaces.Load("spaceid") 748 Expect(ok).To(BeTrue()) 749 cache.Shares[share.Id.OpaqueId].Permissions.Permissions.InitiateFileUpload = true 750 bytes, err := json.Marshal(cache) 751 Expect(err).ToNot(HaveOccurred()) 752 Expect(storage.SimpleUpload(context.Background(), "storages/storageid/spaceid.json", bytes)).To(Succeed()) 753 Expect(err).ToNot(HaveOccurred()) 754 755 // Reset providercache in memory 756 cache.Shares[share.Id.OpaqueId].Permissions.Permissions.InitiateFileUpload = false 757 758 cache.Etag = "reset1" // trigger reload 759 received, err = m.ListReceivedShares(granteeCtx, []*collaboration.Filter{}, nil) 760 Expect(err).ToNot(HaveOccurred()) 761 Expect(len(received)).To(Equal(1)) 762 Expect(received[0].Share.Permissions.Permissions.InitiateFileUpload).To(BeTrue()) 763 }) 764 765 It("syncronizes the user received cache before listing", func() { 766 m, err := jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 767 Expect(err).ToNot(HaveOccurred()) 768 769 received, err := m.ListReceivedShares(granteeCtx, []*collaboration.Filter{}, nil) 770 Expect(err).ToNot(HaveOccurred()) 771 Expect(len(received)).To(Equal(1)) 772 }) 773 774 It("filters by resource id", func() { 775 share2, err := m.Share(ctx, sharedResource2, grant) 776 Expect(err).ToNot(HaveOccurred()) 777 778 received, err := m.ListReceivedShares(granteeCtx, []*collaboration.Filter{}, nil) 779 Expect(err).ToNot(HaveOccurred()) 780 Expect(len(received)).To(Equal(2)) 781 782 received, err = m.ListReceivedShares(granteeCtx, []*collaboration.Filter{ 783 { 784 Type: collaboration.Filter_TYPE_RESOURCE_ID, 785 Term: &collaboration.Filter_ResourceId{ 786 ResourceId: sharedResource.Id, 787 }, 788 }, 789 }, nil) 790 Expect(err).ToNot(HaveOccurred()) 791 Expect(len(received)).To(Equal(1)) 792 Expect(received[0].Share.ResourceId).To(BeComparableTo(sharedResource.Id, protocmp.Transform())) 793 Expect(received[0].State).To(Equal(collaboration.ShareState_SHARE_STATE_PENDING)) 794 Expect(received[0].Share.Id).To(Equal(share.Id)) 795 796 received, err = m.ListReceivedShares(granteeCtx, []*collaboration.Filter{ 797 { 798 Type: collaboration.Filter_TYPE_RESOURCE_ID, 799 Term: &collaboration.Filter_ResourceId{ 800 ResourceId: sharedResource2.Id, 801 }, 802 }, 803 }, nil) 804 Expect(err).ToNot(HaveOccurred()) 805 Expect(len(received)).To(Equal(1)) 806 Expect(received[0].Share.ResourceId).To(BeComparableTo(sharedResource2.Id, protocmp.Transform())) 807 Expect(received[0].State).To(Equal(collaboration.ShareState_SHARE_STATE_PENDING)) 808 Expect(received[0].Share.Id).To(Equal(share2.Id)) 809 }) 810 811 Context("with a group share", func() { 812 var ( 813 gshare *collaboration.Share 814 ) 815 816 BeforeEach(func() { 817 var err error 818 gshare, err = m.Share(ctx, sharedResource, groupGrant) 819 Expect(err).ToNot(HaveOccurred()) 820 }) 821 822 It("lists the group share", func() { 823 received, err := m.ListReceivedShares(granteeCtx, []*collaboration.Filter{}, nil) 824 Expect(err).ToNot(HaveOccurred()) 825 Expect(len(received)).To(Equal(2)) 826 ids := []string{} 827 for _, s := range received { 828 ids = append(ids, s.Share.Id.OpaqueId) 829 } 830 Expect(ids).To(ConsistOf(share.Id.OpaqueId, gshare.Id.OpaqueId)) 831 }) 832 833 It("syncronizes the group received cache before listing", func() { 834 m, err := jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 835 Expect(err).ToNot(HaveOccurred()) 836 837 received, err := m.ListReceivedShares(granteeCtx, []*collaboration.Filter{}, nil) 838 Expect(err).ToNot(HaveOccurred()) 839 Expect(len(received)).To(Equal(2)) 840 ids := []string{} 841 for _, s := range received { 842 ids = append(ids, s.Share.Id.OpaqueId) 843 } 844 Expect(ids).To(ConsistOf(share.Id.OpaqueId, gshare.Id.OpaqueId)) 845 }) 846 847 It("merges the user state with the group share", func() { 848 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 849 Spec: &collaboration.ShareReference_Id{ 850 Id: gshare.Id, 851 }, 852 }) 853 Expect(err).ToNot(HaveOccurred()) 854 855 rs.State = collaboration.ShareState_SHARE_STATE_ACCEPTED 856 _, err = m.UpdateReceivedShare(granteeCtx, rs, &fieldmaskpb.FieldMask{Paths: []string{"state"}}, nil) 857 Expect(err).ToNot(HaveOccurred()) 858 859 received, err := m.ListReceivedShares(granteeCtx, []*collaboration.Filter{}, nil) 860 Expect(err).ToNot(HaveOccurred()) 861 Expect(len(received)).To(Equal(2)) 862 }) 863 }) 864 }) 865 866 Describe("GetReceivedShare", func() { 867 It("gets the state", func() { 868 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 869 Spec: &collaboration.ShareReference_Id{ 870 Id: share.Id, 871 }, 872 }) 873 Expect(err).ToNot(HaveOccurred()) 874 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_PENDING)) 875 }) 876 877 It("syncs the cache", func() { 878 m, err := jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 879 Expect(err).ToNot(HaveOccurred()) 880 881 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 882 Spec: &collaboration.ShareReference_Id{ 883 Id: share.Id, 884 }, 885 }) 886 Expect(err).ToNot(HaveOccurred()) 887 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_PENDING)) 888 }) 889 890 Context("with a group share", func() { 891 var ( 892 gshare *collaboration.Share 893 ) 894 895 BeforeEach(func() { 896 var err error 897 gshare, err = m.Share(ctx, sharedResource, groupGrant) 898 Expect(err).ToNot(HaveOccurred()) 899 }) 900 901 It("gets the group share", func() { 902 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 903 Spec: &collaboration.ShareReference_Id{ 904 Id: gshare.Id, 905 }, 906 }) 907 Expect(err).ToNot(HaveOccurred()) 908 Expect(rs).ToNot(BeNil()) 909 }) 910 911 It("syncs the cache", func() { 912 m, err := jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 913 Expect(err).ToNot(HaveOccurred()) 914 915 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 916 Spec: &collaboration.ShareReference_Id{ 917 Id: gshare.Id, 918 }, 919 }) 920 Expect(err).ToNot(HaveOccurred()) 921 Expect(rs).ToNot(BeNil()) 922 }) 923 }) 924 }) 925 926 Describe("UpdateReceivedShare", func() { 927 It("updates the state", func() { 928 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 929 Spec: &collaboration.ShareReference_Id{ 930 Id: share.Id, 931 }, 932 }) 933 Expect(err).ToNot(HaveOccurred()) 934 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_PENDING)) 935 936 rs.State = collaboration.ShareState_SHARE_STATE_ACCEPTED 937 rs, err = m.UpdateReceivedShare(granteeCtx, rs, &fieldmaskpb.FieldMask{Paths: []string{"state"}}, nil) 938 Expect(err).ToNot(HaveOccurred()) 939 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 940 941 rs, err = m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 942 Spec: &collaboration.ShareReference_Id{ 943 Id: share.Id, 944 }, 945 }) 946 Expect(err).ToNot(HaveOccurred()) 947 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 948 }) 949 950 It("updates the mountpoint", func() { 951 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 952 Spec: &collaboration.ShareReference_Id{ 953 Id: share.Id, 954 }, 955 }) 956 Expect(err).ToNot(HaveOccurred()) 957 Expect(rs.MountPoint).To(BeNil()) 958 959 rs.MountPoint = &providerv1beta1.Reference{ 960 Path: "newMP", 961 } 962 rs, err = m.UpdateReceivedShare(granteeCtx, rs, &fieldmaskpb.FieldMask{Paths: []string{"mount_point"}}, nil) 963 Expect(err).ToNot(HaveOccurred()) 964 Expect(rs.MountPoint.Path).To(Equal("newMP")) 965 966 rs, err = m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 967 Spec: &collaboration.ShareReference_Id{ 968 Id: share.Id, 969 }, 970 }) 971 Expect(err).ToNot(HaveOccurred()) 972 Expect(rs.MountPoint.Path).To(Equal("newMP")) 973 Expect(rs.Hidden).To(Equal(false)) 974 }) 975 976 It("hides the share", func() { 977 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 978 Spec: &collaboration.ShareReference_Id{ 979 Id: share.Id, 980 }, 981 }) 982 Expect(err).ToNot(HaveOccurred()) 983 Expect(rs.MountPoint).To(BeNil()) 984 985 rs.MountPoint = &providerv1beta1.Reference{ 986 Path: "newMP", 987 } 988 rs.Hidden = true 989 990 rs, err = m.UpdateReceivedShare(granteeCtx, rs, &fieldmaskpb.FieldMask{Paths: []string{"hidden", "mount_point"}}, nil) 991 Expect(err).ToNot(HaveOccurred()) 992 Expect(rs.MountPoint.Path).To(Equal("newMP")) 993 Expect(rs.Hidden).To(Equal(true)) 994 995 rs, err = m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 996 Spec: &collaboration.ShareReference_Id{ 997 Id: share.Id, 998 }, 999 }) 1000 Expect(err).ToNot(HaveOccurred()) 1001 Expect(rs.MountPoint.Path).To(Equal("newMP")) 1002 Expect(rs.Hidden).To(Equal(true)) 1003 }) 1004 1005 It("handles invalid field masks", func() { 1006 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 1007 Spec: &collaboration.ShareReference_Id{ 1008 Id: share.Id, 1009 }, 1010 }) 1011 Expect(err).ToNot(HaveOccurred()) 1012 1013 _, err = m.UpdateReceivedShare(granteeCtx, rs, &fieldmaskpb.FieldMask{Paths: []string{"invalid"}}, nil) 1014 Expect(err).To(HaveOccurred()) 1015 }) 1016 1017 Context("with a group share", func() { 1018 var ( 1019 gshare *collaboration.Share 1020 ) 1021 1022 BeforeEach(func() { 1023 var err error 1024 gshare, err = m.Share(ctx, sharedResource, groupGrant) 1025 Expect(err).ToNot(HaveOccurred()) 1026 }) 1027 1028 It("updates the received group share", func() { 1029 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 1030 Spec: &collaboration.ShareReference_Id{ 1031 Id: gshare.Id, 1032 }, 1033 }) 1034 Expect(err).ToNot(HaveOccurred()) 1035 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_PENDING)) 1036 1037 rs.State = collaboration.ShareState_SHARE_STATE_ACCEPTED 1038 rs, err = m.UpdateReceivedShare(granteeCtx, rs, &fieldmaskpb.FieldMask{Paths: []string{"state"}}, nil) 1039 Expect(err).ToNot(HaveOccurred()) 1040 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 1041 1042 rs, err = m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 1043 Spec: &collaboration.ShareReference_Id{ 1044 Id: gshare.Id, 1045 }, 1046 }) 1047 Expect(err).ToNot(HaveOccurred()) 1048 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 1049 }) 1050 1051 It("persists the change", func() { 1052 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 1053 Spec: &collaboration.ShareReference_Id{ 1054 Id: gshare.Id, 1055 }, 1056 }) 1057 Expect(err).ToNot(HaveOccurred()) 1058 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_PENDING)) 1059 1060 rs.State = collaboration.ShareState_SHARE_STATE_ACCEPTED 1061 rs, err = m.UpdateReceivedShare(granteeCtx, rs, &fieldmaskpb.FieldMask{Paths: []string{"state"}}, nil) 1062 Expect(err).ToNot(HaveOccurred()) 1063 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 1064 1065 m, err := jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 1066 Expect(err).ToNot(HaveOccurred()) 1067 1068 rs, err = m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 1069 Spec: &collaboration.ShareReference_Id{ 1070 Id: gshare.Id, 1071 }, 1072 }) 1073 Expect(err).ToNot(HaveOccurred()) 1074 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 1075 }) 1076 1077 It("hides share and persists the change", func() { 1078 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 1079 Spec: &collaboration.ShareReference_Id{ 1080 Id: gshare.Id, 1081 }, 1082 }) 1083 Expect(err).ToNot(HaveOccurred()) 1084 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_PENDING)) 1085 1086 rs.State = collaboration.ShareState_SHARE_STATE_ACCEPTED 1087 rs.Hidden = true 1088 rs, err = m.UpdateReceivedShare(granteeCtx, rs, &fieldmaskpb.FieldMask{Paths: []string{"state", "hidden"}}, nil) 1089 Expect(err).ToNot(HaveOccurred()) 1090 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 1091 Expect(rs.Hidden).To(Equal(true)) 1092 1093 m, err := jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 1094 Expect(err).ToNot(HaveOccurred()) 1095 1096 rs, err = m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 1097 Spec: &collaboration.ShareReference_Id{ 1098 Id: gshare.Id, 1099 }, 1100 }) 1101 Expect(rs.Hidden).To(Equal(true)) 1102 Expect(err).ToNot(HaveOccurred()) 1103 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 1104 }) 1105 1106 It("hides and unhides the share and persists the change", func() { 1107 rs, err := m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 1108 Spec: &collaboration.ShareReference_Id{ 1109 Id: gshare.Id, 1110 }, 1111 }) 1112 Expect(err).ToNot(HaveOccurred()) 1113 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_PENDING)) 1114 1115 rs.State = collaboration.ShareState_SHARE_STATE_ACCEPTED 1116 rs.Hidden = true 1117 rs, err = m.UpdateReceivedShare(granteeCtx, rs, &fieldmaskpb.FieldMask{Paths: []string{"state", "hidden"}}, nil) 1118 Expect(err).ToNot(HaveOccurred()) 1119 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 1120 Expect(rs.Hidden).To(Equal(true)) 1121 1122 m, err := jsoncs3.New(storage, nil, 0, nil, 0) // Reset in-memory cache 1123 Expect(err).ToNot(HaveOccurred()) 1124 1125 rs, err = m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 1126 Spec: &collaboration.ShareReference_Id{ 1127 Id: gshare.Id, 1128 }, 1129 }) 1130 Expect(rs.Hidden).To(Equal(true)) 1131 Expect(err).ToNot(HaveOccurred()) 1132 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 1133 1134 rs.Hidden = false 1135 rs, err = m.UpdateReceivedShare(granteeCtx, rs, &fieldmaskpb.FieldMask{Paths: []string{"state", "hidden"}}, nil) 1136 Expect(err).ToNot(HaveOccurred()) 1137 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 1138 Expect(rs.Hidden).To(Equal(false)) 1139 1140 rs, err = m.GetReceivedShare(granteeCtx, &collaboration.ShareReference{ 1141 Spec: &collaboration.ShareReference_Id{ 1142 Id: gshare.Id, 1143 }, 1144 }) 1145 Expect(rs.Hidden).To(Equal(false)) 1146 Expect(err).ToNot(HaveOccurred()) 1147 Expect(rs.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) 1148 }) 1149 }) 1150 }) 1151 }) 1152 })