Skip to content

Commit

Permalink
enhancement(sharing): allow unmounting a share
Browse files Browse the repository at this point in the history
  • Loading branch information
rhafer committed Feb 21, 2024
1 parent a46cb0d commit 5d9c15a
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 16 deletions.
38 changes: 33 additions & 5 deletions services/graph/pkg/service/v0/api_drives_drive_item.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,30 @@ func (s DrivesDriveItemService) UnmountShare(ctx context.Context, resourceID sto
return err
}

// This is a a bit of a hack. We should not rely on a specific format of the item id.
// (But currently the ShareID is
shareId := resourceID.GetOpaqueId()

// Now, find out the resourceID of the shared resource
getReceivedShareResponse, err := gatewayClient.GetReceivedShare(ctx,
&collaboration.GetReceivedShareRequest{
Ref: &collaboration.ShareReference{
Spec: &collaboration.ShareReference_Id{
Id: &collaboration.ShareId{
OpaqueId: shareId,
},
},
},
},
)
if errCode := errorcode.FromCS3Status(getReceivedShareResponse.GetStatus(), err); errCode != nil {
s.logger.Debug().Err(errCode).
Str("shareid", shareId).
Msg("failed to read share")
return errCode
}

// Find all accepted shares for this resource
receivedSharesResponse, err := gatewayClient.ListReceivedShares(ctx, &collaboration.ListReceivedSharesRequest{
Filters: []*collaboration.Filter{
{
Expand All @@ -67,7 +91,7 @@ func (s DrivesDriveItemService) UnmountShare(ctx context.Context, resourceID sto
{
Type: collaboration.Filter_TYPE_RESOURCE_ID,
Term: &collaboration.Filter_ResourceId{
ResourceId: &resourceID,
ResourceId: getReceivedShareResponse.GetShare().GetShare().GetResourceId(),
},
},
},
Expand All @@ -78,6 +102,7 @@ func (s DrivesDriveItemService) UnmountShare(ctx context.Context, resourceID sto

var errs []error

// Reject all the shares for this resource
for _, receivedShare := range receivedSharesResponse.GetShares() {
receivedShare.State = collaboration.ShareState_SHARE_STATE_REJECTED

Expand All @@ -86,17 +111,20 @@ func (s DrivesDriveItemService) UnmountShare(ctx context.Context, resourceID sto
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{_fieldMaskPathState}},
}

updateReceivedShareResponse, err := gatewayClient.UpdateReceivedShare(ctx, updateReceivedShareRequest)
_, err := gatewayClient.UpdateReceivedShare(ctx, updateReceivedShareRequest)
if err != nil {
errs = append(errs, err)
continue
}
}

// fixMe: send to nirvana, wait for toDriverItem func
_ = updateReceivedShareResponse
// We call it a success if all shares could successfully be rejected, otherwise
// we return an error
if len(errs) != 0 {
return errors.Join(errs...)
}

return errors.Join(errs...)
return nil
}

// MountShare mounts a share
Expand Down
103 changes: 92 additions & 11 deletions services/graph/pkg/service/v0/api_drives_drive_item_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks"
"github.com/owncloud/ocis/v2/ocis-pkg/log"
"github.com/owncloud/ocis/v2/services/graph/mocks"
"github.com/owncloud/ocis/v2/services/graph/pkg/errorcode"
"github.com/owncloud/ocis/v2/services/graph/pkg/identity"
svc "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0"
)
Expand Down Expand Up @@ -330,21 +331,44 @@ var _ = Describe("DrivesDriveItemService", func() {

Describe("gateway client share listing", func() {
It("handles share listing errors", func() {
expectedError := errors.New("listing shares failed")
expectedError := errorcode.New(errorcode.GeneralException, "listing shares failed")
gatewayClient.
On("ListReceivedShares", mock.Anything, mock.Anything, mock.Anything).
Return(&collaborationv1beta1.ListReceivedSharesResponse{}, expectedError)
On("GetReceivedShare", mock.Anything, mock.Anything, mock.Anything).
Return(&collaborationv1beta1.GetReceivedShareResponse{}, errors.New("listing shares failed"))

err := drivesDriveItemService.UnmountShare(context.Background(), storageprovider.ResourceId{})
Expect(err).To(MatchError(expectedError))
Expect(err).To(MatchError(&expectedError))
})

It("uses the correct filters to get the shares", func() {
expectedResourceID := storageprovider.ResourceId{
driveItemResourceID := storageprovider.ResourceId{
StorageId: "1",
OpaqueId: "2",
SpaceId: "3",
SpaceId: "2",
OpaqueId: "3:4:5",
}
expectedResourceID := storageprovider.ResourceId{
StorageId: "3",
SpaceId: "4",
OpaqueId: "5",
}
gatewayClient.
On("GetReceivedShare", mock.Anything, mock.Anything, mock.Anything).
Return(func(ctx context.Context, in *collaborationv1beta1.GetReceivedShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.GetReceivedShareResponse, error) {
Expect(in.Ref.GetId().GetOpaqueId()).To(Equal(driveItemResourceID.GetOpaqueId()))
return &collaborationv1beta1.GetReceivedShareResponse{
Status: status.NewOK(ctx),
Share: &collaborationv1beta1.ReceivedShare{
State: collaborationv1beta1.ShareState_SHARE_STATE_ACCEPTED,
Share: &collaborationv1beta1.Share{
Id: &collaborationv1beta1.ShareId{
OpaqueId: driveItemResourceID.GetOpaqueId(),
},
ResourceId: &expectedResourceID,
},
},
}, nil
})

gatewayClient.
On("ListReceivedShares", mock.Anything, mock.Anything, mock.Anything).
Return(func(ctx context.Context, in *collaborationv1beta1.ListReceivedSharesRequest, opts ...grpc.CallOption) (*collaborationv1beta1.ListReceivedSharesResponse, error) {
Expand Down Expand Up @@ -373,17 +397,29 @@ var _ = Describe("DrivesDriveItemService", func() {
return nil, nil
})

err := drivesDriveItemService.UnmountShare(context.Background(), expectedResourceID)
err := drivesDriveItemService.UnmountShare(context.Background(), driveItemResourceID)
Expect(err).ToNot(HaveOccurred())
})
})

Describe("gateway client share update", func() {
It("updates the share state to be accepted", func() {
It("updates the share state to be rejected", func() {
expectedShareID := collaborationv1beta1.ShareId{
OpaqueId: "1$2!3",
}

gatewayClient.
On("GetReceivedShare", mock.Anything, mock.Anything, mock.Anything).
Return(func(ctx context.Context, in *collaborationv1beta1.GetReceivedShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.GetReceivedShareResponse, error) {
return &collaborationv1beta1.GetReceivedShareResponse{
Status: status.NewOK(ctx),
Share: &collaborationv1beta1.ReceivedShare{
State: collaborationv1beta1.ShareState_SHARE_STATE_ACCEPTED,
Share: &collaborationv1beta1.Share{
Id: &expectedShareID,
},
},
}, nil
})
gatewayClient.
On("ListReceivedShares", mock.Anything, mock.Anything, mock.Anything).
Return(func(ctx context.Context, in *collaborationv1beta1.ListReceivedSharesRequest, opts ...grpc.CallOption) (*collaborationv1beta1.ListReceivedSharesResponse, error) {
Expand Down Expand Up @@ -411,8 +447,53 @@ var _ = Describe("DrivesDriveItemService", func() {
err := drivesDriveItemService.UnmountShare(context.Background(), storageprovider.ResourceId{})
Expect(err).ToNot(HaveOccurred())
})
It("succeeds when all shares could be rejected", func() {
gatewayClient.
On("GetReceivedShare", mock.Anything, mock.Anything, mock.Anything).
Return(func(ctx context.Context, in *collaborationv1beta1.GetReceivedShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.GetReceivedShareResponse, error) {
return &collaborationv1beta1.GetReceivedShareResponse{
Status: status.NewOK(ctx),
Share: &collaborationv1beta1.ReceivedShare{
State: collaborationv1beta1.ShareState_SHARE_STATE_ACCEPTED,
},
}, nil
})
gatewayClient.
On("ListReceivedShares", mock.Anything, mock.Anything, mock.Anything).
Return(func(ctx context.Context, in *collaborationv1beta1.ListReceivedSharesRequest, opts ...grpc.CallOption) (*collaborationv1beta1.ListReceivedSharesResponse, error) {
return &collaborationv1beta1.ListReceivedSharesResponse{
Shares: []*collaborationv1beta1.ReceivedShare{
{},
{},
{},
},
}, nil
})

It("bubbles errors and continues", func() {
var calls int
gatewayClient.
On("UpdateReceivedShare", mock.Anything, mock.Anything, mock.Anything).
Return(func(ctx context.Context, in *collaborationv1beta1.UpdateReceivedShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.UpdateReceivedShareResponse, error) {
calls++
return &collaborationv1beta1.UpdateReceivedShareResponse{}, nil
})

err := drivesDriveItemService.UnmountShare(context.Background(), storageprovider.ResourceId{})
Expect(calls).To(Equal(3))
Expect(err).ToNot(HaveOccurred())
})

It("bubbles errors when any share fails rejecting", func() {
gatewayClient.
On("GetReceivedShare", mock.Anything, mock.Anything, mock.Anything).
Return(func(ctx context.Context, in *collaborationv1beta1.GetReceivedShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.GetReceivedShareResponse, error) {
return &collaborationv1beta1.GetReceivedShareResponse{
Status: status.NewOK(ctx),
Share: &collaborationv1beta1.ReceivedShare{
State: collaborationv1beta1.ShareState_SHARE_STATE_ACCEPTED,
},
}, nil
})
gatewayClient.
On("ListReceivedShares", mock.Anything, mock.Anything, mock.Anything).
Return(func(ctx context.Context, in *collaborationv1beta1.ListReceivedSharesRequest, opts ...grpc.CallOption) (*collaborationv1beta1.ListReceivedSharesResponse, error) {
Expand Down

0 comments on commit 5d9c15a

Please sign in to comment.