From d7e2e9f7158dd13d298b113a1d979e2592f1985e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Duffeck?= Date: Tue, 3 Aug 2021 11:02:44 +0200 Subject: [PATCH] Use field mask to update received shares MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The next step for the shares storahge provider is to introduce field masks so the shares can update state and mount point. This PR is based on the full changeset, but removes everything but the API change. Add a sharesstorageprovider The provider exposes all received shares. It can be mounted to /home/Shares to make a lot of special cases for shares handling in the gateway and storage drivers superfluous. Add missing mock file Implement methods for setting/unsetting arbitrary metadata Fix tests Adapt to changes from rebase Fix creating references with embedded mounts Fix corner cases when stating shares Allow moves between shares on the same storage Make the storage rules known to the gateway as well Do not choke on non-existent shares Reject a share when it is being deleted Fix rebase artifacts WIP: Refactor statting shares. Merge shares permissions. update after rebase, fix tests Signed-off-by: Jörn Friedrich Dreyer list all shares Signed-off-by: Jörn Friedrich Dreyer work on api change Signed-off-by: Jörn Friedrich Dreyer Fix build Persist mountpoints in the share managers followin the new cs3 api Add support for renaming shares in the SharesStorageprovider Adapt commands for updating received shares Regenerate the share manager mock Fix linter warning Do not raise an internal error when trying to access non-existent shares Make hound happy Fix wrong column name in query Fix typo Do not confuse user and group names Add test for listing received group shares Do not list parent group shares if there is a child share for it already Make hound happy Hide the fact that accepted groups shares can be child shares in the db list shares using the shares manager + hide group shares when the same resource has a user and group share refactor all the ocs error writing from the new code Only collide with mountpoints of shares pointing do different resources Also return shares being shared with one of the user's groups Add sharesstorageprovider service file for local acceptance tests Adapt nextcloud share manager to new method signature Also remove the test for UpdateReceivedShare which can not be tested anymore with the new signature. The ReceivedShare never held the display name that's being tested so the test only passed on the data from the update field, but since the method only takes the actual received share now this is no longer possible. WIP: use go-cs3apis fork until it has been merged Add placeholder changelog to make CI run Tweak documentation on how to run the acceptance tests Add missing storage registry rule for the sharesstorageprovider Fix revad config for local acceptance tests reduce changes to share api change Signed-off-by: Jörn Friedrich Dreyer JSON encode the FieldMask parameter as-is paramsObj.Ref -> paramsObj.ReceivedShare Restore deleted test update code comment remove go mod replace Signed-off-by: Jörn Friedrich Dreyer --- .../unreleased/sharemanager-api-change.md | 5 + cmd/reva/ocm-share-update-received.go | 26 ++- cmd/reva/share-update-received.go | 26 ++- go.mod | 3 +- go.sum | 4 + internal/grpc/interceptors/auth/scope.go | 2 +- .../grpc/services/gateway/ocmshareprovider.go | 94 ++++---- .../grpc/services/gateway/storageprovider.go | 21 +- .../services/gateway/usershareprovider.go | 82 ++++--- .../ocmshareprovider/ocmshareprovider.go | 2 +- .../usershareprovider/usershareprovider.go | 2 +- .../handlers/apps/sharing/shares/pending.go | 26 +-- pkg/auth/scope/receivedshare.go | 2 +- pkg/auth/scope/share.go | 6 + pkg/cbox/share/sql/sql.go | 17 +- pkg/ocm/share/manager/json/json.go | 16 +- pkg/ocm/share/share.go | 3 +- pkg/share/manager/json/json.go | 20 +- pkg/share/manager/memory/memory.go | 20 +- pkg/share/manager/nextcloud/nextcloud.go | 12 +- .../nextcloud/nextcloud_server_mock.go | 8 +- pkg/share/manager/nextcloud/nextcloud_test.go | 78 ++++++- pkg/share/manager/sql/sql.go | 18 +- pkg/share/manager/sql/sql_test.go | 23 +- pkg/share/mocks/Manager.go | 213 ++++++++++++++++++ pkg/share/share.go | 5 +- 26 files changed, 560 insertions(+), 174 deletions(-) create mode 100644 changelog/unreleased/sharemanager-api-change.md create mode 100644 pkg/share/mocks/Manager.go diff --git a/changelog/unreleased/sharemanager-api-change.md b/changelog/unreleased/sharemanager-api-change.md new file mode 100644 index 0000000000..8210920deb --- /dev/null +++ b/changelog/unreleased/sharemanager-api-change.md @@ -0,0 +1,5 @@ +Change: Sharemanager API change + +This PR updates reva to reflect the share manager CS3 API changes. + +https://github.com/cs3org/reva/pull/2121 \ No newline at end of file diff --git a/cmd/reva/ocm-share-update-received.go b/cmd/reva/ocm-share-update-received.go index 40b2f7999e..7f88765f14 100644 --- a/cmd/reva/ocm-share-update-received.go +++ b/cmd/reva/ocm-share-update-received.go @@ -25,6 +25,7 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1" "github.com/pkg/errors" + "google.golang.org/protobuf/types/known/fieldmaskpb" ) func ocmShareUpdateReceivedCommand() *command { @@ -57,7 +58,7 @@ func ocmShareUpdateReceivedCommand() *command { shareState := getOCMShareState(*state) - shareRequest := &ocm.UpdateReceivedOCMShareRequest{ + shareRes, err := shareClient.GetReceivedOCMShare(ctx, &ocm.GetReceivedOCMShareRequest{ Ref: &ocm.ShareReference{ Spec: &ocm.ShareReference_Id{ Id: &ocm.ShareId{ @@ -65,20 +66,27 @@ func ocmShareUpdateReceivedCommand() *command { }, }, }, - Field: &ocm.UpdateReceivedOCMShareRequest_UpdateField{ - Field: &ocm.UpdateReceivedOCMShareRequest_UpdateField_State{ - State: shareState, - }, - }, + }) + if err != nil { + return err + } + if shareRes.Status.Code != rpc.Code_CODE_OK { + return formatError(shareRes.Status) + } + shareRes.Share.State = shareState + + shareRequest := &ocm.UpdateReceivedOCMShareRequest{ + Share: shareRes.Share, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state"}}, } - shareRes, err := shareClient.UpdateReceivedOCMShare(ctx, shareRequest) + updateRes, err := shareClient.UpdateReceivedOCMShare(ctx, shareRequest) if err != nil { return err } - if shareRes.Status.Code != rpc.Code_CODE_OK { - return formatError(shareRes.Status) + if updateRes.Status.Code != rpc.Code_CODE_OK { + return formatError(updateRes.Status) } fmt.Println("OK") diff --git a/cmd/reva/share-update-received.go b/cmd/reva/share-update-received.go index 7dd974efb7..624fe3e983 100644 --- a/cmd/reva/share-update-received.go +++ b/cmd/reva/share-update-received.go @@ -25,6 +25,7 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" "github.com/pkg/errors" + "google.golang.org/protobuf/types/known/fieldmaskpb" ) func shareUpdateReceivedCommand() *command { @@ -57,7 +58,7 @@ func shareUpdateReceivedCommand() *command { shareState := getShareState(*state) - shareRequest := &collaboration.UpdateReceivedShareRequest{ + shareRes, err := shareClient.GetReceivedShare(ctx, &collaboration.GetReceivedShareRequest{ Ref: &collaboration.ShareReference{ Spec: &collaboration.ShareReference_Id{ Id: &collaboration.ShareId{ @@ -65,20 +66,27 @@ func shareUpdateReceivedCommand() *command { }, }, }, - Field: &collaboration.UpdateReceivedShareRequest_UpdateField{ - Field: &collaboration.UpdateReceivedShareRequest_UpdateField_State{ - State: shareState, - }, - }, + }) + if err != nil { + return err + } + if shareRes.Status.Code != rpc.Code_CODE_OK { + return formatError(shareRes.Status) + } + shareRes.Share.State = shareState + + shareRequest := &collaboration.UpdateReceivedShareRequest{ + Share: shareRes.Share, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state"}}, } - shareRes, err := shareClient.UpdateReceivedShare(ctx, shareRequest) + updateRes, err := shareClient.UpdateReceivedShare(ctx, shareRequest) if err != nil { return err } - if shareRes.Status.Code != rpc.Code_CODE_OK { - return formatError(shareRes.Status) + if updateRes.Status.Code != rpc.Code_CODE_OK { + return formatError(updateRes.Status) } fmt.Println("OK") diff --git a/go.mod b/go.mod index 6df9611241..3193737c6a 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/cheggaaa/pb v1.0.29 github.com/coreos/go-oidc v2.2.1+incompatible github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e - github.com/cs3org/go-cs3apis v0.0.0-20210922150613-cb9e3c99f8de + github.com/cs3org/go-cs3apis v0.0.0-20211004093007-d29741980082 github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59 github.com/gdexlab/go-render v1.0.1 @@ -70,6 +70,7 @@ require ( golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f golang.org/x/sys v0.0.0-20210921065528-437939a70204 golang.org/x/term v0.0.0-20210916214954-140adaaadfaf + google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 google.golang.org/grpc v1.41.0 google.golang.org/protobuf v1.27.1 gopkg.in/square/go-jose.v2 v2.6.0 // indirect diff --git a/go.sum b/go.sum index c90866b6a2..443f117005 100644 --- a/go.sum +++ b/go.sum @@ -90,8 +90,12 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e h1:tqSPWQeueWTKnJVMJffz4pz0o1WuQxJ28+5x5JgaHD8= github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= +github.com/cs3org/go-cs3apis v0.0.0-20210325133324-32b03d75a535 h1:555D8A3ddKqb4OyK9v5mdphw2zDLWKGXOkcnf1RQwTA= +github.com/cs3org/go-cs3apis v0.0.0-20210325133324-32b03d75a535/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cs3org/go-cs3apis v0.0.0-20210922150613-cb9e3c99f8de h1:N+AI8wz7yhDDqHDuq9EGaqQoFhAOi9XW37xt0ormflw= github.com/cs3org/go-cs3apis v0.0.0-20210922150613-cb9e3c99f8de/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= +github.com/cs3org/go-cs3apis v0.0.0-20211004093007-d29741980082 h1:ErxzuD05JkSlTQrqc8YSca7R1BPFuCesufg8gxzTB2g= +github.com/cs3org/go-cs3apis v0.0.0-20211004093007-d29741980082/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/internal/grpc/interceptors/auth/scope.go b/internal/grpc/interceptors/auth/scope.go index b8f7cf1f7b..7cac0416b3 100644 --- a/internal/grpc/interceptors/auth/scope.go +++ b/internal/grpc/interceptors/auth/scope.go @@ -195,7 +195,7 @@ func extractShareRef(req interface{}) (*collaboration.ShareReference, bool) { case *collaboration.GetReceivedShareRequest: return v.GetRef(), true case *collaboration.UpdateReceivedShareRequest: - return v.GetRef(), true + return &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{Id: v.GetShare().GetShare().GetId()}}, true } return nil, false } diff --git a/internal/grpc/services/gateway/ocmshareprovider.go b/internal/grpc/services/gateway/ocmshareprovider.go index d1d686a846..bd7ebb76bb 100644 --- a/internal/grpc/services/gateway/ocmshareprovider.go +++ b/internal/grpc/services/gateway/ocmshareprovider.go @@ -224,54 +224,64 @@ func (s *svc) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceive return res, nil } - // we don't commit to storage invalid update fields or empty display names. - if req.Field.GetState() == ocm.ShareState_SHARE_STATE_INVALID && req.Field.GetDisplayName() == "" { - log.Error().Msg("the update field is invalid, aborting reference manipulation") - return res, nil - - } - - // TODO(labkode): if update field is displayName we need to do a rename on the storage to align - // share display name and storage filename. - if req.Field.GetState() != ocm.ShareState_SHARE_STATE_INVALID { - if req.Field.GetState() == ocm.ShareState_SHARE_STATE_ACCEPTED { - getShareReq := &ocm.GetReceivedOCMShareRequest{Ref: req.Ref} - getShareRes, err := s.GetReceivedOCMShare(ctx, getShareReq) - if err != nil { - log.Err(err).Msg("gateway: error calling GetReceivedShare") - return &ocm.UpdateReceivedOCMShareResponse{ - Status: &rpc.Status{ - Code: rpc.Code_CODE_INTERNAL, + // properties are updated in the order they appear in the field mask + // when an error occurs the request ends and no further fields are updated + for i := range req.UpdateMask.Paths { + switch req.UpdateMask.Paths[i] { + case "state": + switch req.GetShare().GetState() { + case ocm.ShareState_SHARE_STATE_ACCEPTED: + getShareReq := &ocm.GetReceivedOCMShareRequest{ + Ref: &ocm.ShareReference{ + Spec: &ocm.ShareReference_Id{ + Id: req.Share.Share.Id, + }, }, - }, nil - } - - if getShareRes.Status.Code != rpc.Code_CODE_OK { - log.Error().Msg("gateway: error calling GetReceivedShare") + } + getShareRes, err := s.GetReceivedOCMShare(ctx, getShareReq) + if err != nil { + log.Err(err).Msg("gateway: error calling GetReceivedShare") + return &ocm.UpdateReceivedOCMShareResponse{ + Status: &rpc.Status{ + Code: rpc.Code_CODE_INTERNAL, + }, + }, nil + } + + if getShareRes.Status.Code != rpc.Code_CODE_OK { + log.Error().Msg("gateway: error calling GetReceivedShare") + return &ocm.UpdateReceivedOCMShareResponse{ + Status: &rpc.Status{ + Code: rpc.Code_CODE_INTERNAL, + }, + }, nil + } + + share := getShareRes.Share + if share == nil { + panic("gateway: error updating a received share: the share is nil") + } + + createRefStatus, err := s.createOCMReference(ctx, share.Share) return &ocm.UpdateReceivedOCMShareResponse{ - Status: &rpc.Status{ - Code: rpc.Code_CODE_INTERNAL, - }, - }, nil - } - - share := getShareRes.Share - if share == nil { - panic("gateway: error updating a received share: the share is nil") + Status: createRefStatus, + }, err + case ocm.ShareState_SHARE_STATE_REJECTED: + s.removeReference(ctx, req.GetShare().GetShare().ResourceId) // error is logged inside removeReference + // FIXME we are ignoring an error from removeReference here + return res, nil } - - createRefStatus, err := s.createOCMReference(ctx, share.Share) + case "mount_point": + // TODO(labkode): implementing updating mount point + err = errtypes.NotSupported("gateway: update of mount point is not yet implemented") return &ocm.UpdateReceivedOCMShareResponse{ - Status: createRefStatus, - }, err + Status: status.NewUnimplemented(ctx, err, "error updating received share"), + }, nil + default: + return nil, errtypes.NotSupported("updating " + req.UpdateMask.Paths[i] + " is not supported") } } - - // TODO(labkode): implementing updating display name - err = errtypes.NotSupported("gateway: update of display name is not yet implemented") - return &ocm.UpdateReceivedOCMShareResponse{ - Status: status.NewUnimplemented(ctx, err, "error updating received share"), - }, nil + return res, nil } func (s *svc) GetReceivedOCMShare(ctx context.Context, req *ocm.GetReceivedOCMShareRequest) (*ocm.GetReceivedOCMShareResponse, error) { diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 84d24a3844..974349cac9 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -29,6 +29,7 @@ import ( "time" rtrace "github.com/cs3org/reva/pkg/trace" + "google.golang.org/protobuf/types/known/fieldmaskpb" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" @@ -888,7 +889,7 @@ func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provide // the following will check that: // - the resource to delete is a share the current user received // - signal the storage the delete must not land in the trashbin - // - delete the resource and update the share status to pending + // - delete the resource and update the share status to "rejected" for _, share := range sRes.Shares { if statRes != nil && (share.Share.ResourceId.OpaqueId == statRes.Info.Id.OpaqueId) && (share.Share.ResourceId.StorageId == statRes.Info.Id.StorageId) { // this opaque needs explanation. It signals the storage the resource we're about to delete does not @@ -903,21 +904,13 @@ func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provide }, } - // the following block takes care of updating the state of the share to "pending". This will ensure the user + // the following block takes care of updating the state of the share to "rejected". This will ensure the user // can "Accept" the share once again. + // TODO should this be pending? If so, update the two comments above as well. If not, get rid of this comment. + share.State = collaboration.ShareState_SHARE_STATE_REJECTED r := &collaboration.UpdateReceivedShareRequest{ - Ref: &collaboration.ShareReference{ - Spec: &collaboration.ShareReference_Id{ - Id: &collaboration.ShareId{ - OpaqueId: share.Share.Id.OpaqueId, - }, - }, - }, - Field: &collaboration.UpdateReceivedShareRequest_UpdateField{ - Field: &collaboration.UpdateReceivedShareRequest_UpdateField_State{ - State: collaboration.ShareState_SHARE_STATE_REJECTED, - }, - }, + Share: share, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state"}}, } _, err := s.UpdateReceivedShare(ctx, r) diff --git a/internal/grpc/services/gateway/usershareprovider.go b/internal/grpc/services/gateway/usershareprovider.go index 77f89bfc10..7243b4bae4 100644 --- a/internal/grpc/services/gateway/usershareprovider.go +++ b/internal/grpc/services/gateway/usershareprovider.go @@ -276,6 +276,27 @@ func (s *svc) GetReceivedShare(ctx context.Context, req *collaboration.GetReceiv // 2) if received share is not mounted: we only rename in user share provider. func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.UpdateReceivedShareRequest) (*collaboration.UpdateReceivedShareResponse, error) { log := appctx.GetLogger(ctx) + + // sanity checks + switch { + case req.GetShare() == nil: + return &collaboration.UpdateReceivedShareResponse{ + Status: status.NewInvalidArg(ctx, "updating requires a received share object"), + }, nil + case req.GetShare().GetShare() == nil: + return &collaboration.UpdateReceivedShareResponse{ + Status: status.NewInvalidArg(ctx, "share missing"), + }, nil + case req.GetShare().GetShare().GetId() == nil: + return &collaboration.UpdateReceivedShareResponse{ + Status: status.NewInvalidArg(ctx, "share id missing"), + }, nil + case req.GetShare().GetShare().GetId().GetOpaqueId() == "": + return &collaboration.UpdateReceivedShareResponse{ + Status: status.NewInvalidArg(ctx, "share id empty"), + }, nil + } + c, err := pool.GetUserShareProviderClient(s.c.UserShareProviderEndpoint) if err != nil { err = errors.Wrap(err, "gateway: error calling GetUserShareProviderClient") @@ -304,39 +325,44 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update return res, nil } - // we don't commit to storage invalid update fields or empty display names. - if req.Field.GetState() == collaboration.ShareState_SHARE_STATE_INVALID && req.Field.GetDisplayName() == "" { - log.Error().Msg("the update field is invalid, aborting reference manipulation") - return res, nil - + // check if we have a resource id in the update response that we can use to update references + if res.GetShare().GetShare().GetResourceId() == nil { + log.Err(err).Msg("gateway: UpdateReceivedShare must return a ResourceId") + return &collaboration.UpdateReceivedShareResponse{ + Status: &rpc.Status{ + Code: rpc.Code_CODE_INTERNAL, + }, + }, nil } - // TODO(labkode): if update field is displayName we need to do a rename on the storage to align - // share display name and storage filename. - if req.Field.GetState() != collaboration.ShareState_SHARE_STATE_INVALID { - if req.Field.GetState() == collaboration.ShareState_SHARE_STATE_ACCEPTED { - share := res.Share - if share == nil { - panic("gateway: error updating a received share: the share is nil") + // properties are updated in the order they appear in the field mask + // when an error occurs the request ends and no further fields are updated + for i := range req.UpdateMask.Paths { + switch req.UpdateMask.Paths[i] { + case "state": + switch req.GetShare().GetState() { + case collaboration.ShareState_SHARE_STATE_ACCEPTED: + rpcStatus := s.createReference(ctx, res.GetShare().GetShare().GetResourceId()) + if rpcStatus.Code != rpc.Code_CODE_OK { + return &collaboration.UpdateReceivedShareResponse{Status: rpcStatus}, nil + } + case collaboration.ShareState_SHARE_STATE_REJECTED: + rpcStatus := s.removeReference(ctx, res.GetShare().GetShare().ResourceId) + if rpcStatus.Code != rpc.Code_CODE_OK && rpcStatus.Code != rpc.Code_CODE_NOT_FOUND { + return &collaboration.UpdateReceivedShareResponse{Status: rpcStatus}, nil + } } - createRefStatus := s.createReference(ctx, share.Share.ResourceId) - rsp := &collaboration.UpdateReceivedShareResponse{Status: createRefStatus} - - if createRefStatus.Code == rpc.Code_CODE_OK { - rsp.Share = share - } - return rsp, nil - } else if req.Field.GetState() == collaboration.ShareState_SHARE_STATE_REJECTED { - s.removeReference(ctx, res.Share.Share.ResourceId) - return res, nil + case "mount_point": + // TODO(labkode): implementing updating mount point + err = errtypes.NotSupported("gateway: update of mount point is not yet implemented") + return &collaboration.UpdateReceivedShareResponse{ + Status: status.NewUnimplemented(ctx, err, "error updating received share"), + }, nil + default: + return nil, errtypes.NotSupported("updating " + req.UpdateMask.Paths[i] + " is not supported") } } - - // TODO(labkode): implementing updating display name - err = errtypes.NotSupported("gateway: update of display name is not yet implemented") - return &collaboration.UpdateReceivedShareResponse{ - Status: status.NewUnimplemented(ctx, err, "error updating received share"), - }, nil + return res, nil } func (s *svc) removeReference(ctx context.Context, resourceID *provider.ResourceId) *rpc.Status { diff --git a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go index 1b4e8676db..78543eb799 100644 --- a/internal/grpc/services/ocmshareprovider/ocmshareprovider.go +++ b/internal/grpc/services/ocmshareprovider/ocmshareprovider.go @@ -247,7 +247,7 @@ func (s *service) ListReceivedOCMShares(ctx context.Context, req *ocm.ListReceiv } func (s *service) UpdateReceivedOCMShare(ctx context.Context, req *ocm.UpdateReceivedOCMShareRequest) (*ocm.UpdateReceivedOCMShareResponse, error) { - _, err := s.sm.UpdateReceivedShare(ctx, req.Ref, req.Field) // TODO(labkode): check what to update + _, err := s.sm.UpdateReceivedShare(ctx, req.Share, req.UpdateMask) // TODO(labkode): check what to update if err != nil { return &ocm.UpdateReceivedOCMShareResponse{ Status: status.NewInternal(ctx, err, "error updating received share"), diff --git a/internal/grpc/services/usershareprovider/usershareprovider.go b/internal/grpc/services/usershareprovider/usershareprovider.go index 5fb5a2e77f..9f5b0d1fc8 100644 --- a/internal/grpc/services/usershareprovider/usershareprovider.go +++ b/internal/grpc/services/usershareprovider/usershareprovider.go @@ -231,7 +231,7 @@ func (s *service) GetReceivedShare(ctx context.Context, req *collaboration.GetRe } func (s *service) UpdateReceivedShare(ctx context.Context, req *collaboration.UpdateReceivedShareRequest) (*collaboration.UpdateReceivedShareResponse, error) { - share, err := s.sm.UpdateReceivedShare(ctx, req.Ref, req.Field) // TODO(labkode): check what to update + share, err := s.sm.UpdateReceivedShare(ctx, req.Share, req.UpdateMask) // TODO(labkode): check what to update if err != nil { return &collaboration.UpdateReceivedShareResponse{ Status: status.NewInternal(ctx, err, "error updating received share"), diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go index 76bc15fbef..1fe1bf5d39 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go @@ -30,6 +30,7 @@ import ( "github.com/cs3org/reva/pkg/rgrpc/todo/pool" "github.com/go-chi/chi/v5" "github.com/pkg/errors" + "google.golang.org/protobuf/types/known/fieldmaskpb" ) // AcceptReceivedShare handles Post Requests on /apps/files_sharing/api/v1/shares/{shareid} @@ -54,28 +55,17 @@ func (h *Handler) updateReceivedShare(w http.ResponseWriter, r *http.Request, sh return } - ref := &collaboration.ShareReference{ - Spec: &collaboration.ShareReference_Id{ - Id: &collaboration.ShareId{ - OpaqueId: shareID, - }, - }, - } - shareRequest := &collaboration.UpdateReceivedShareRequest{ - Ref: ref, - Field: &collaboration.UpdateReceivedShareRequest_UpdateField{ - Field: &collaboration.UpdateReceivedShareRequest_UpdateField_State{ - State: collaboration.ShareState_SHARE_STATE_ACCEPTED, - }, + Share: &collaboration.ReceivedShare{ + Share: &collaboration.Share{Id: &collaboration.ShareId{OpaqueId: shareID}}, }, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state"}}, } if rejectShare { - shareRequest.Field = &collaboration.UpdateReceivedShareRequest_UpdateField{ - Field: &collaboration.UpdateReceivedShareRequest_UpdateField_State{ - State: collaboration.ShareState_SHARE_STATE_REJECTED, - }, - } + shareRequest.Share.State = collaboration.ShareState_SHARE_STATE_REJECTED + } else { + // TODO find free mount point and pass it on with an updated field mask + shareRequest.Share.State = collaboration.ShareState_SHARE_STATE_ACCEPTED } shareRes, err := client.UpdateReceivedShare(ctx, shareRequest) diff --git a/pkg/auth/scope/receivedshare.go b/pkg/auth/scope/receivedshare.go index cc9b90353f..3fe2e99594 100644 --- a/pkg/auth/scope/receivedshare.go +++ b/pkg/auth/scope/receivedshare.go @@ -39,7 +39,7 @@ func receivedShareScope(scope *authpb.Scope, resource interface{}) (bool, error) case *collaboration.GetReceivedShareRequest: return checkShareRef(share.Share, v.GetRef()), nil case *collaboration.UpdateReceivedShareRequest: - return checkShareRef(share.Share, v.GetRef()), nil + return checkShare(share.Share, v.GetShare().GetShare()), nil case string: return checkSharePath(v) || checkResourcePath(v), nil } diff --git a/pkg/auth/scope/share.go b/pkg/auth/scope/share.go index de26f62a02..069a2d7d2a 100644 --- a/pkg/auth/scope/share.go +++ b/pkg/auth/scope/share.go @@ -90,6 +90,12 @@ func checkShareRef(s *collaboration.Share, ref *collaboration.ShareReference) bo } return false } +func checkShare(s1 *collaboration.Share, s2 *collaboration.Share) bool { + if s2.GetId() != nil { + return s2.GetId().OpaqueId == s1.Id.OpaqueId + } + return false +} func checkSharePath(path string) bool { paths := []string{ diff --git a/pkg/cbox/share/sql/sql.go b/pkg/cbox/share/sql/sql.go index 675f40ba0a..2cfe7d57e0 100644 --- a/pkg/cbox/share/sql/sql.go +++ b/pkg/cbox/share/sql/sql.go @@ -38,6 +38,7 @@ import ( "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" + "google.golang.org/genproto/protobuf/field_mask" // Provides mysql drivers _ "github.com/go-sql-driver/mysql" @@ -435,17 +436,26 @@ func (m *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareRefe } -func (m *mgr) UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareReference, f *collaboration.UpdateReceivedShareRequest_UpdateField) (*collaboration.ReceivedShare, error) { +func (m *mgr) UpdateReceivedShare(ctx context.Context, share *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { user := ctxpkg.ContextMustGetUser(ctx) - rs, err := m.GetReceivedShare(ctx, ref) + rs, err := m.GetReceivedShare(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{Id: share.Share.Id}}) if err != nil { return nil, err } + for i := range fieldMask.Paths { + switch fieldMask.Paths[i] { + case "state": + rs.State = share.State + default: + return nil, errtypes.NotSupported("updating " + fieldMask.Paths[i] + " is not supported") + } + } + var query, queryAccept string params := []interface{}{rs.Share.Id.OpaqueId, conversions.FormatUserID(user.Id)} - switch f.GetState() { + switch rs.GetState() { case collaboration.ShareState_SHARE_STATE_REJECTED: query = "insert into oc_share_acl(id, rejected_by) values(?, ?)" case collaboration.ShareState_SHARE_STATE_ACCEPTED: @@ -473,6 +483,5 @@ func (m *mgr) UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareR } } - rs.State = f.GetState() return rs, nil } diff --git a/pkg/ocm/share/manager/json/json.go b/pkg/ocm/share/manager/json/json.go index f8b7f7fdc0..2d91faa42c 100644 --- a/pkg/ocm/share/manager/json/json.go +++ b/pkg/ocm/share/manager/json/json.go @@ -45,6 +45,7 @@ import ( "github.com/google/uuid" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" + "google.golang.org/genproto/protobuf/field_mask" ) const createOCMCoreShareEndpoint = "shares" @@ -630,8 +631,8 @@ func (m *mgr) getReceived(ctx context.Context, ref *ocm.ShareReference) (*ocm.Re return nil, errtypes.NotFound(ref.String()) } -func (m *mgr) UpdateReceivedShare(ctx context.Context, ref *ocm.ShareReference, f *ocm.UpdateReceivedOCMShareRequest_UpdateField) (*ocm.ReceivedShare, error) { - rs, err := m.getReceived(ctx, ref) +func (m *mgr) UpdateReceivedShare(ctx context.Context, share *ocm.ReceivedShare, fieldMask *field_mask.FieldMask) (*ocm.ReceivedShare, error) { + rs, err := m.getReceived(ctx, &ocm.ShareReference{Spec: &ocm.ShareReference_Id{Id: share.Share.Id}}) if err != nil { return nil, err } @@ -639,12 +640,21 @@ func (m *mgr) UpdateReceivedShare(ctx context.Context, ref *ocm.ShareReference, m.Lock() defer m.Unlock() + for i := range fieldMask.Paths { + switch fieldMask.Paths[i] { + case "state": + rs.State = share.State + // TODO case "mount_point": + default: + return nil, errtypes.NotSupported("updating " + fieldMask.Paths[i] + " is not supported") + } + } + if err := m.model.ReadFile(); err != nil { err = errors.Wrap(err, "error reading model") return nil, err } - rs.State = f.GetState() encShare, err := utils.MarshalProtoV1ToJSON(rs) if err != nil { return nil, err diff --git a/pkg/ocm/share/share.go b/pkg/ocm/share/share.go index e4b7d1188d..522c3dc837 100644 --- a/pkg/ocm/share/share.go +++ b/pkg/ocm/share/share.go @@ -25,6 +25,7 @@ import ( ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1" ocm "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "google.golang.org/genproto/protobuf/field_mask" ) // Manager is the interface that manipulates the OCM shares. @@ -53,7 +54,7 @@ type Manager interface { GetReceivedShare(ctx context.Context, ref *ocm.ShareReference) (*ocm.ReceivedShare, error) // UpdateReceivedShare updates the received share with share state. - UpdateReceivedShare(ctx context.Context, ref *ocm.ShareReference, f *ocm.UpdateReceivedOCMShareRequest_UpdateField) (*ocm.ReceivedShare, error) + UpdateReceivedShare(ctx context.Context, share *ocm.ReceivedShare, fieldMask *field_mask.FieldMask) (*ocm.ReceivedShare, error) } // ResourceIDFilter is an abstraction for creating filter by resource id. diff --git a/pkg/share/manager/json/json.go b/pkg/share/manager/json/json.go index fe47803f94..026682ce33 100644 --- a/pkg/share/manager/json/json.go +++ b/pkg/share/manager/json/json.go @@ -35,6 +35,7 @@ import ( "github.com/google/uuid" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" + "google.golang.org/genproto/protobuf/field_mask" "github.com/cs3org/reva/pkg/share/manager/registry" "github.com/cs3org/reva/pkg/utils" @@ -448,8 +449,8 @@ func (m *mgr) getReceived(ctx context.Context, ref *collaboration.ShareReference return nil, errtypes.NotFound(ref.String()) } -func (m *mgr) UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareReference, f *collaboration.UpdateReceivedShareRequest_UpdateField) (*collaboration.ReceivedShare, error) { - rs, err := m.getReceived(ctx, ref) +func (m *mgr) UpdateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { + rs, err := m.getReceived(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{Id: receivedShare.Share.Id}}) if err != nil { return nil, err } @@ -458,12 +459,22 @@ func (m *mgr) UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareR m.Lock() defer m.Unlock() + for i := range fieldMask.Paths { + switch fieldMask.Paths[i] { + case "state": + rs.State = receivedShare.State + // TODO case "mount_point": + default: + return nil, errtypes.NotSupported("updating " + fieldMask.Paths[i] + " is not supported") + } + } + if v, ok := m.model.State[user.Id.String()]; ok { - v[rs.Share.Id.String()] = f.GetState() + v[rs.Share.Id.String()] = rs.GetState() m.model.State[user.Id.String()] = v } else { a := map[string]collaboration.ShareState{ - rs.Share.Id.String(): f.GetState(), + rs.Share.Id.String(): rs.GetState(), } m.model.State[user.Id.String()] = a } @@ -473,6 +484,5 @@ func (m *mgr) UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareR return nil, err } - rs.State = f.GetState() return rs, nil } diff --git a/pkg/share/manager/memory/memory.go b/pkg/share/manager/memory/memory.go index 8f84c77d9b..fb365d7aa8 100644 --- a/pkg/share/manager/memory/memory.go +++ b/pkg/share/manager/memory/memory.go @@ -28,6 +28,7 @@ import ( ctxpkg "github.com/cs3org/reva/pkg/ctx" "github.com/cs3org/reva/pkg/share" + "google.golang.org/genproto/protobuf/field_mask" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -309,8 +310,8 @@ func (m *manager) getReceived(ctx context.Context, ref *collaboration.ShareRefer return nil, errtypes.NotFound(ref.String()) } -func (m *manager) UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareReference, f *collaboration.UpdateReceivedShareRequest_UpdateField) (*collaboration.ReceivedShare, error) { - rs, err := m.getReceived(ctx, ref) +func (m *manager) UpdateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { + rs, err := m.getReceived(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{Id: receivedShare.Share.Id}}) if err != nil { return nil, err } @@ -319,16 +320,25 @@ func (m *manager) UpdateReceivedShare(ctx context.Context, ref *collaboration.Sh m.lock.Lock() defer m.lock.Unlock() + for i := range fieldMask.Paths { + switch fieldMask.Paths[i] { + case "state": + rs.State = receivedShare.State + // TODO case "mount_point": + default: + return nil, errtypes.NotSupported("updating " + fieldMask.Paths[i] + " is not supported") + } + } + if v, ok := m.shareState[user.Id.String()]; ok { - v[rs.Share.Id] = f.GetState() + v[rs.Share.Id] = rs.GetState() m.shareState[user.Id.String()] = v } else { a := map[*collaboration.ShareId]collaboration.ShareState{ - rs.Share.Id: f.GetState(), + rs.Share.Id: rs.GetState(), } m.shareState[user.Id.String()] = a } - rs.State = f.GetState() return rs, nil } diff --git a/pkg/share/manager/nextcloud/nextcloud.go b/pkg/share/manager/nextcloud/nextcloud.go index 3b1de3d1e5..c4ffdb94e8 100644 --- a/pkg/share/manager/nextcloud/nextcloud.go +++ b/pkg/share/manager/nextcloud/nextcloud.go @@ -39,6 +39,7 @@ import ( "github.com/cs3org/reva/pkg/share/manager/registry" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" + "google.golang.org/genproto/protobuf/field_mask" ) func init() { @@ -403,14 +404,15 @@ func (sm *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareRef } // UpdateReceivedShare updates the received share with share state. -func (sm *mgr) UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareReference, f *collaboration.UpdateReceivedShareRequest_UpdateField) (*collaboration.ReceivedShare, error) { +func (sm *mgr) UpdateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { type paramsObj struct { - Ref *collaboration.ShareReference `json:"ref"` - F *collaboration.UpdateReceivedShareRequest_UpdateField `json:"f"` + ReceivedShare *collaboration.ReceivedShare `json:"received_share"` + FieldMask *field_mask.FieldMask `json:"field_mask"` } + bodyObj := ¶msObj{ - Ref: ref, - F: f, + ReceivedShare: receivedShare, + FieldMask: fieldMask, } bodyStr, err := json.Marshal(bodyObj) if err != nil { diff --git a/pkg/share/manager/nextcloud/nextcloud_server_mock.go b/pkg/share/manager/nextcloud/nextcloud_server_mock.go index d72d2178c5..1a865b9bf8 100644 --- a/pkg/share/manager/nextcloud/nextcloud_server_mock.go +++ b/pkg/share/manager/nextcloud/nextcloud_server_mock.go @@ -47,10 +47,10 @@ var responses = map[string]Response{ `POST /apps/sciencemesh/~tester/api/share/GetShare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`: {200, `{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}}`, serverStateHome}, `POST /apps/sciencemesh/~tester/api/share/Unshare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`: {200, ``, serverStateHome}, `POST /apps/sciencemesh/~tester/api/share/UpdateShare {"ref":{"Spec":{"Id":{"opaque_id":"some-share-id"}}},"p":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`: {200, `{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}}`, serverStateHome}, - `POST /apps/sciencemesh/~tester/api/share/ListShares [{"type":4,"Term":{"Creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}]`: {200, `[{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}}]`, serverStateHome}, - `POST /apps/sciencemesh/~tester/api/share/ListReceivedShares [{"type":4,"Term":{"Creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}]`: {200, `[{"share":{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}},"state":2}]`, serverStateHome}, - `POST /apps/sciencemesh/~tester/api/share/GetReceivedShare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`: {200, `{"share":{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}},"state":2}`, serverStateHome}, - `POST /apps/sciencemesh/~tester/api/share/UpdateReceivedShare {"ref":{"Spec":{"Id":{"opaque_id":"some-share-id"}}},"f":{"Field":{"DisplayName":"some new name for this received share"}}}`: {200, `{"share":{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}},"state":2}`, serverStateHome}, + `POST /apps/sciencemesh/~tester/api/share/ListShares [{"type":4,"Term":{"Creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}]`: {200, `[{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}}]`, serverStateHome}, + `POST /apps/sciencemesh/~tester/api/share/ListReceivedShares [{"type":4,"Term":{"Creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}]`: {200, `[{"share":{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}},"state":2}]`, serverStateHome}, + `POST /apps/sciencemesh/~tester/api/share/GetReceivedShare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`: {200, `{"share":{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}},"state":2}`, serverStateHome}, + `POST /apps/sciencemesh/~tester/api/share/UpdateReceivedShare {"received_share":{"share":{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}},"state":2},"field_mask":{"paths":["state"]}}`: {200, `{"share":{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}},"state":2}`, serverStateHome}, } // GetNextcloudServerMock returns a handler that pretends to be a remote Nextcloud server diff --git a/pkg/share/manager/nextcloud/nextcloud_test.go b/pkg/share/manager/nextcloud/nextcloud_test.go index 4d7a305242..f6f86b3857 100644 --- a/pkg/share/manager/nextcloud/nextcloud_test.go +++ b/pkg/share/manager/nextcloud/nextcloud_test.go @@ -22,6 +22,7 @@ import ( "context" "os" + "google.golang.org/genproto/protobuf/field_mask" "google.golang.org/grpc/metadata" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" @@ -727,7 +728,7 @@ var _ = Describe("Nextcloud", func() { }) }) - // UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareReference, f *collaboration.UpdateReceivedShareRequest_UpdateField) (*collaboration.ReceivedShare, error) + // UpdateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) Describe("UpdateReceivedShare", func() { It("calls the UpdateReceivedShare endpoint", func() { called := make([]string, 0) @@ -738,17 +739,72 @@ var _ = Describe("Nextcloud", func() { am, _ := nextcloud.NewShareManager(&nextcloud.ShareManagerConfig{ EndPoint: "http://mock.com/apps/sciencemesh/", }, mock) - receivedShare, err := am.UpdateReceivedShare(ctx, &collaboration.ShareReference{ - Spec: &collaboration.ShareReference_Id{ - Id: &collaboration.ShareId{ - OpaqueId: "some-share-id", + receivedShare, err := am.UpdateReceivedShare(ctx, + &collaboration.ReceivedShare{ + Share: &collaboration.Share{ + Id: &collaboration.ShareId{}, + ResourceId: &provider.ResourceId{}, + Permissions: &collaboration.SharePermissions{ + Permissions: &provider.ResourcePermissions{ + AddGrant: true, + CreateContainer: true, + Delete: true, + GetPath: true, + GetQuota: true, + InitiateFileDownload: true, + InitiateFileUpload: true, + ListGrants: true, + ListContainer: true, + ListFileVersions: true, + ListRecycle: true, + Move: true, + RemoveGrant: true, + PurgeRecycle: true, + RestoreFileVersion: true, + RestoreRecycleItem: true, + Stat: true, + UpdateGrant: true, + DenyGrant: true, + }, + }, + Grantee: &provider.Grantee{ + Id: &provider.Grantee_UserId{ + UserId: &userpb.UserId{ + Idp: "0.0.0.0:19000", + OpaqueId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + Type: userpb.UserType_USER_TYPE_PRIMARY, + }, + }, + }, + Owner: &userpb.UserId{ + Idp: "0.0.0.0:19000", + OpaqueId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + Type: userpb.UserType_USER_TYPE_PRIMARY, + }, + Creator: &userpb.UserId{ + Idp: "0.0.0.0:19000", + OpaqueId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + Type: userpb.UserType_USER_TYPE_PRIMARY, + }, + Ctime: &types.Timestamp{ + Seconds: 1234567890, + Nanos: 0, + XXX_NoUnkeyedLiteral: struct{}{}, + XXX_unrecognized: nil, + XXX_sizecache: 0, + }, + Mtime: &types.Timestamp{ + Seconds: 1234567890, + Nanos: 0, + XXX_NoUnkeyedLiteral: struct{}{}, + XXX_unrecognized: nil, + XXX_sizecache: 0, + }, }, + State: collaboration.ShareState_SHARE_STATE_ACCEPTED, }, - }, - &collaboration.UpdateReceivedShareRequest_UpdateField{ - Field: &collaboration.UpdateReceivedShareRequest_UpdateField_DisplayName{ - DisplayName: "some new name for this received share", - }, + &field_mask.FieldMask{ + Paths: []string{"state"}, }) Expect(err).ToNot(HaveOccurred()) Expect(*receivedShare).To(Equal(collaboration.ReceivedShare{ @@ -814,7 +870,7 @@ var _ = Describe("Nextcloud", func() { }, State: collaboration.ShareState_SHARE_STATE_ACCEPTED, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/share/UpdateReceivedShare {"ref":{"Spec":{"Id":{"opaque_id":"some-share-id"}}},"f":{"Field":{"DisplayName":"some new name for this received share"}}}`)) + Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/share/UpdateReceivedShare {"received_share":{"share":{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}},"state":2},"field_mask":{"paths":["state"]}}`)) }) }) diff --git a/pkg/share/manager/sql/sql.go b/pkg/share/manager/sql/sql.go index c43ef2b377..516bcbf526 100644 --- a/pkg/share/manager/sql/sql.go +++ b/pkg/share/manager/sql/sql.go @@ -37,6 +37,7 @@ import ( "github.com/cs3org/reva/pkg/utils" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" + "google.golang.org/genproto/protobuf/field_mask" // Provides mysql drivers _ "github.com/go-sql-driver/mysql" @@ -382,14 +383,24 @@ func (m *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareRefe } -func (m *mgr) UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareReference, f *collaboration.UpdateReceivedShareRequest_UpdateField) (*collaboration.ReceivedShare, error) { - rs, err := m.GetReceivedShare(ctx, ref) +func (m *mgr) UpdateReceivedShare(ctx context.Context, share *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { + rs, err := m.GetReceivedShare(ctx, &collaboration.ShareReference{Spec: &collaboration.ShareReference_Id{Id: share.Share.Id}}) if err != nil { return nil, err } + for i := range fieldMask.Paths { + switch fieldMask.Paths[i] { + case "state": + rs.State = share.State + // TODO case "mount_point": + default: + return nil, errtypes.NotSupported("updating " + fieldMask.Paths[i] + " is not supported") + } + } + var queryAccept string - switch f.GetState() { + switch rs.GetState() { case collaboration.ShareState_SHARE_STATE_REJECTED: queryAccept = "update oc_share set accepted=2 where id=?" case collaboration.ShareState_SHARE_STATE_ACCEPTED: @@ -407,7 +418,6 @@ func (m *mgr) UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareR } } - rs.State = f.GetState() return rs, nil } diff --git a/pkg/share/manager/sql/sql_test.go b/pkg/share/manager/sql/sql_test.go index aba406862a..016ced3044 100644 --- a/pkg/share/manager/sql/sql_test.go +++ b/pkg/share/manager/sql/sql_test.go @@ -32,6 +32,7 @@ import ( "github.com/cs3org/reva/pkg/share" sqlmanager "github.com/cs3org/reva/pkg/share/manager/sql" mocks "github.com/cs3org/reva/pkg/share/manager/sql/mocks" + "google.golang.org/protobuf/types/known/fieldmaskpb" _ "github.com/mattn/go-sqlite3" "github.com/stretchr/testify/mock" @@ -199,7 +200,7 @@ var _ = Describe("SQL manager", func() { }) Describe("UpdateReceivedShare", func() { - It("updates the received share", func() { + It("returns an error when no valid field is set in the mask", func() { loginAs(otherUser) share, err := mgr.GetReceivedShare(ctx, shareRef) @@ -207,11 +208,21 @@ var _ = Describe("SQL manager", func() { Expect(share).ToNot(BeNil()) Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) - share, err = mgr.UpdateReceivedShare(ctx, shareRef, &collaboration.UpdateReceivedShareRequest_UpdateField{ - Field: &collaboration.UpdateReceivedShareRequest_UpdateField_State{ - State: collaboration.ShareState_SHARE_STATE_REJECTED, - }, - }) + share.State = collaboration.ShareState_SHARE_STATE_REJECTED + _, err = mgr.UpdateReceivedShare(ctx, share, &fieldmaskpb.FieldMask{Paths: []string{"foo"}}) + Expect(err).To(HaveOccurred()) + }) + + It("updates the state when the state is set in the mask", func() { + loginAs(otherUser) + + share, err := mgr.GetReceivedShare(ctx, shareRef) + Expect(err).ToNot(HaveOccurred()) + Expect(share).ToNot(BeNil()) + Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_ACCEPTED)) + + share.State = collaboration.ShareState_SHARE_STATE_REJECTED + share, err = mgr.UpdateReceivedShare(ctx, share, &fieldmaskpb.FieldMask{Paths: []string{"state"}}) Expect(err).ToNot(HaveOccurred()) Expect(share.State).To(Equal(collaboration.ShareState_SHARE_STATE_REJECTED)) diff --git a/pkg/share/mocks/Manager.go b/pkg/share/mocks/Manager.go new file mode 100644 index 0000000000..5a80d362cf --- /dev/null +++ b/pkg/share/mocks/Manager.go @@ -0,0 +1,213 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + collaborationv1beta1 "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" + + fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" + + mock "github.com/stretchr/testify/mock" + + providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" +) + +// Manager is an autogenerated mock type for the Manager type +type Manager struct { + mock.Mock +} + +// GetReceivedShare provides a mock function with given fields: ctx, ref +func (_m *Manager) GetReceivedShare(ctx context.Context, ref *collaborationv1beta1.ShareReference) (*collaborationv1beta1.ReceivedShare, error) { + ret := _m.Called(ctx, ref) + + var r0 *collaborationv1beta1.ReceivedShare + if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ShareReference) *collaborationv1beta1.ReceivedShare); ok { + r0 = rf(ctx, ref) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*collaborationv1beta1.ReceivedShare) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *collaborationv1beta1.ShareReference) error); ok { + r1 = rf(ctx, ref) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetShare provides a mock function with given fields: ctx, ref +func (_m *Manager) GetShare(ctx context.Context, ref *collaborationv1beta1.ShareReference) (*collaborationv1beta1.Share, error) { + ret := _m.Called(ctx, ref) + + var r0 *collaborationv1beta1.Share + if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ShareReference) *collaborationv1beta1.Share); ok { + r0 = rf(ctx, ref) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*collaborationv1beta1.Share) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *collaborationv1beta1.ShareReference) error); ok { + r1 = rf(ctx, ref) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListReceivedShares provides a mock function with given fields: ctx, filters +func (_m *Manager) ListReceivedShares(ctx context.Context, filters []*collaborationv1beta1.Filter) ([]*collaborationv1beta1.ReceivedShare, error) { + ret := _m.Called(ctx, filters) + + var r0 []*collaborationv1beta1.ReceivedShare + if rf, ok := ret.Get(0).(func(context.Context, []*collaborationv1beta1.Filter) []*collaborationv1beta1.ReceivedShare); ok { + r0 = rf(ctx, filters) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*collaborationv1beta1.ReceivedShare) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, []*collaborationv1beta1.Filter) error); ok { + r1 = rf(ctx, filters) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListShares provides a mock function with given fields: ctx, filters +func (_m *Manager) ListShares(ctx context.Context, filters []*collaborationv1beta1.Filter) ([]*collaborationv1beta1.Share, error) { + ret := _m.Called(ctx, filters) + + var r0 []*collaborationv1beta1.Share + if rf, ok := ret.Get(0).(func(context.Context, []*collaborationv1beta1.Filter) []*collaborationv1beta1.Share); ok { + r0 = rf(ctx, filters) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*collaborationv1beta1.Share) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, []*collaborationv1beta1.Filter) error); ok { + r1 = rf(ctx, filters) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Share provides a mock function with given fields: ctx, md, g +func (_m *Manager) Share(ctx context.Context, md *providerv1beta1.ResourceInfo, g *collaborationv1beta1.ShareGrant) (*collaborationv1beta1.Share, error) { + ret := _m.Called(ctx, md, g) + + var r0 *collaborationv1beta1.Share + if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.ResourceInfo, *collaborationv1beta1.ShareGrant) *collaborationv1beta1.Share); ok { + r0 = rf(ctx, md, g) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*collaborationv1beta1.Share) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *providerv1beta1.ResourceInfo, *collaborationv1beta1.ShareGrant) error); ok { + r1 = rf(ctx, md, g) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Unshare provides a mock function with given fields: ctx, ref +func (_m *Manager) Unshare(ctx context.Context, ref *collaborationv1beta1.ShareReference) error { + ret := _m.Called(ctx, ref) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ShareReference) error); ok { + r0 = rf(ctx, ref) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdateReceivedShare provides a mock function with given fields: ctx, _a1, fieldMask +func (_m *Manager) UpdateReceivedShare(ctx context.Context, _a1 *collaborationv1beta1.ReceivedShare, fieldMask *fieldmaskpb.FieldMask) (*collaborationv1beta1.ReceivedShare, error) { + ret := _m.Called(ctx, _a1, fieldMask) + + var r0 *collaborationv1beta1.ReceivedShare + if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ReceivedShare, *fieldmaskpb.FieldMask) *collaborationv1beta1.ReceivedShare); ok { + r0 = rf(ctx, _a1, fieldMask) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*collaborationv1beta1.ReceivedShare) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *collaborationv1beta1.ReceivedShare, *fieldmaskpb.FieldMask) error); ok { + r1 = rf(ctx, _a1, fieldMask) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UpdateShare provides a mock function with given fields: ctx, ref, p +func (_m *Manager) UpdateShare(ctx context.Context, ref *collaborationv1beta1.ShareReference, p *collaborationv1beta1.SharePermissions) (*collaborationv1beta1.Share, error) { + ret := _m.Called(ctx, ref, p) + + var r0 *collaborationv1beta1.Share + if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ShareReference, *collaborationv1beta1.SharePermissions) *collaborationv1beta1.Share); ok { + r0 = rf(ctx, ref, p) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*collaborationv1beta1.Share) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *collaborationv1beta1.ShareReference, *collaborationv1beta1.SharePermissions) error); ok { + r1 = rf(ctx, ref, p) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/pkg/share/share.go b/pkg/share/share.go index 9184e0d93c..9847216507 100644 --- a/pkg/share/share.go +++ b/pkg/share/share.go @@ -23,8 +23,11 @@ import ( collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "google.golang.org/genproto/protobuf/field_mask" ) +//go:generate mockery -name Manager + // Manager is the interface that manipulates shares. type Manager interface { // Create a new share in fn with the given acl. @@ -50,7 +53,7 @@ type Manager interface { GetReceivedShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) // UpdateReceivedShare updates the received share with share state. - UpdateReceivedShare(ctx context.Context, ref *collaboration.ShareReference, f *collaboration.UpdateReceivedShareRequest_UpdateField) (*collaboration.ReceivedShare, error) + UpdateReceivedShare(ctx context.Context, share *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) } // GroupGranteeFilter is an abstraction for creating filter by grantee type group.