enhancement(sharing): allow unmounting a share

(cherry picked from commit 35acae10a3d1a7370115f3444e433af2df7e5346)
This commit is contained in:
Ralf Haferkamp
2024-02-12 17:56:40 +01:00
parent ebcca0e678
commit bb5e1bac35
2 changed files with 126 additions and 17 deletions

View File

@@ -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{
{
@@ -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(),
},
},
},
@@ -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
@@ -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
}
return errors.Join(errs...)
// 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 nil
}
// MountShare mounts a share

View File

@@ -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"
)
@@ -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) {
@@ -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) {
@@ -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) {