Skip to content

Commit

Permalink
Dummy implementation of the Lock CS3APIs (#2350) (#2412)
Browse files Browse the repository at this point in the history
Co-authored-by: Willy Kloucek <34452982+wkloucek@users.noreply.github.com>
  • Loading branch information
butonic and wkloucek authored Jan 5, 2022
1 parent 649b6a7 commit 73c3c4b
Show file tree
Hide file tree
Showing 16 changed files with 390 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Enhancement: add file locking methods to the storage and filesystem interfaces

We've added the file locking methods from the CS3apis to the storage and filesystem
interfaces. As of now they are dummy implementations and will only return "unimplemented"
errors.

https://github.com/cs3org/reva/pull/2350
https://github.com/cs3org/cs3apis/pull/160
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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-20211213090556-12c0d565f51d
github.com/cs3org/go-cs3apis v0.0.0-20211214102047-7ce3134d7bf8
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
Expand Down
8 changes: 2 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,8 @@ 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-20211104090126-8e972dca8304 h1:e/nIPR518vyvrulo9goAZTtYD6gFfu/2/9MDe6mTGcw=
github.com/cs3org/go-cs3apis v0.0.0-20211104090126-8e972dca8304/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/go-cs3apis v0.0.0-20211213090556-12c0d565f51d h1:gnb2ciU4N+RwUug/nwe54wenWi7vSp5bAAjXINlgHZ8=
github.com/cs3org/go-cs3apis v0.0.0-20211213090556-12c0d565f51d/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
github.com/cs3org/go-cs3apis v0.0.0-20211214102047-7ce3134d7bf8 h1:PqOprF37OvwCbAN5W23znknGk6N/LMayqLAeP904FHE=
github.com/cs3org/go-cs3apis v0.0.0-20211214102047-7ce3134d7bf8/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=
Expand Down
88 changes: 88 additions & 0 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,94 @@ func (s *svc) UnsetArbitraryMetadata(ctx context.Context, req *provider.UnsetArb
return res, nil
}

// SetLock puts a lock on the given reference
func (s *svc) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provider.SetLockResponse, error) {
var c provider.ProviderAPIClient
var err error
c, _, req.Ref, err = s.findAndUnwrap(ctx, req.Ref)
if err != nil {
return &provider.SetLockResponse{
Status: status.NewStatusFromErrType(ctx, "SetLock ref="+req.Ref.String(), err),
}, nil
}

res, err := c.SetLock(ctx, req)
if err != nil {
if gstatus.Code(err) == codes.PermissionDenied {
return &provider.SetLockResponse{Status: &rpc.Status{Code: rpc.Code_CODE_PERMISSION_DENIED}}, nil
}
return nil, errors.Wrap(err, "gateway: error calling SetLock")
}

return res, nil
}

// GetLock returns an existing lock on the given reference
func (s *svc) GetLock(ctx context.Context, req *provider.GetLockRequest) (*provider.GetLockResponse, error) {
var c provider.ProviderAPIClient
var err error
c, _, req.Ref, err = s.findAndUnwrap(ctx, req.Ref)
if err != nil {
return &provider.GetLockResponse{
Status: status.NewStatusFromErrType(ctx, "GetLock ref="+req.Ref.String(), err),
}, nil
}

res, err := c.GetLock(ctx, req)
if err != nil {
if gstatus.Code(err) == codes.PermissionDenied {
return &provider.GetLockResponse{Status: &rpc.Status{Code: rpc.Code_CODE_PERMISSION_DENIED}}, nil
}
return nil, errors.Wrap(err, "gateway: error calling GetLock")
}

return res, nil
}

// RefreshLock refreshes an existing lock on the given reference
func (s *svc) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) (*provider.RefreshLockResponse, error) {
var c provider.ProviderAPIClient
var err error
c, _, req.Ref, err = s.findAndUnwrap(ctx, req.Ref)
if err != nil {
return &provider.RefreshLockResponse{
Status: status.NewStatusFromErrType(ctx, "RefreshLock ref="+req.Ref.String(), err),
}, nil
}

res, err := c.RefreshLock(ctx, req)
if err != nil {
if gstatus.Code(err) == codes.PermissionDenied {
return &provider.RefreshLockResponse{Status: &rpc.Status{Code: rpc.Code_CODE_PERMISSION_DENIED}}, nil
}
return nil, errors.Wrap(err, "gateway: error calling RefreshLock")
}

return res, nil
}

// Unlock removes an existing lock from the given reference
func (s *svc) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provider.UnlockResponse, error) {
var c provider.ProviderAPIClient
var err error
c, _, req.Ref, err = s.findAndUnwrap(ctx, req.Ref)
if err != nil {
return &provider.UnlockResponse{
Status: status.NewStatusFromErrType(ctx, "Unlock ref="+req.Ref.String(), err),
}, nil
}

res, err := c.Unlock(ctx, req)
if err != nil {
if gstatus.Code(err) == codes.PermissionDenied {
return &provider.UnlockResponse{Status: &rpc.Status{Code: rpc.Code_CODE_PERMISSION_DENIED}}, nil
}
return nil, errors.Wrap(err, "gateway: error calling Unlock")
}

return res, nil
}

// Stat returns the Resoure info for a given resource by forwarding the request to all responsible providers.
// In the simplest case there is only one provider, eg. when statting a relative or id based reference
// However the registry can return multiple providers for a reference and Stat needs to take them all into account:
Expand Down
12 changes: 12 additions & 0 deletions internal/grpc/services/gateway/storageprovidercache.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,18 @@ func (c *cachedAPIClient) SetArbitraryMetadata(ctx context.Context, in *provider
func (c *cachedAPIClient) UnsetArbitraryMetadata(ctx context.Context, in *provider.UnsetArbitraryMetadataRequest, opts ...grpc.CallOption) (*provider.UnsetArbitraryMetadataResponse, error) {
return c.c.UnsetArbitraryMetadata(ctx, in, opts...)
}
func (c *cachedAPIClient) SetLock(ctx context.Context, in *provider.SetLockRequest, opts ...grpc.CallOption) (*provider.SetLockResponse, error) {
return c.c.SetLock(ctx, in, opts...)
}
func (c *cachedAPIClient) GetLock(ctx context.Context, in *provider.GetLockRequest, opts ...grpc.CallOption) (*provider.GetLockResponse, error) {
return c.c.GetLock(ctx, in, opts...)
}
func (c *cachedAPIClient) RefreshLock(ctx context.Context, in *provider.RefreshLockRequest, opts ...grpc.CallOption) (*provider.RefreshLockResponse, error) {
return c.c.RefreshLock(ctx, in, opts...)
}
func (c *cachedAPIClient) Unlock(ctx context.Context, in *provider.UnlockRequest, opts ...grpc.CallOption) (*provider.UnlockResponse, error) {
return c.c.Unlock(ctx, in, opts...)
}
func (c *cachedAPIClient) GetHome(ctx context.Context, in *provider.GetHomeRequest, opts ...grpc.CallOption) (*provider.GetHomeResponse, error) {
return c.c.GetHome(ctx, in, opts...)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,26 @@ func (s *service) UnsetArbitraryMetadata(ctx context.Context, req *provider.Unse
return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented")
}

// SetLock puts a lock on the given reference
func (s *service) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provider.SetLockResponse, error) {
return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented")
}

// GetLock returns an existing lock on the given reference
func (s *service) GetLock(ctx context.Context, req *provider.GetLockRequest) (*provider.GetLockResponse, error) {
return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented")
}

// RefreshLock refreshes an existing lock on the given reference
func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) (*provider.RefreshLockResponse, error) {
return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented")
}

// Unlock removes an existing lock from the given reference
func (s *service) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provider.UnlockResponse, error) {
return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented")
}

func (s *service) InitiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*provider.InitiateFileDownloadResponse, error) {
statReq := &provider.StatRequest{Ref: req.Ref}
statRes, err := s.Stat(ctx, statReq)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,26 @@ func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provide
})
}

// SetLock puts a lock on the given reference
func (s *service) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provider.SetLockResponse, error) {
return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented")
}

// GetLock returns an existing lock on the given reference
func (s *service) GetLock(ctx context.Context, req *provider.GetLockRequest) (*provider.GetLockResponse, error) {
return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented")
}

// RefreshLock refreshes an existing lock on the given reference
func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) (*provider.RefreshLockResponse, error) {
return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented")
}

// Unlock removes an existing lock from the given reference
func (s *service) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provider.UnlockResponse, error) {
return nil, gstatus.Errorf(codes.Unimplemented, "method not implemented")
}

func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) {
if isVirtualRoot(req.Ref.ResourceId) && (req.Ref.Path == "" || req.Ref.Path == ".") {
// The root is empty, it is filled by mountpoints
Expand Down
95 changes: 95 additions & 0 deletions internal/grpc/services/storageprovider/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,101 @@ func (s *service) UnsetArbitraryMetadata(ctx context.Context, req *provider.Unse
return res, nil
}

// SetLock puts a lock on the given reference
func (s *service) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provider.SetLockResponse, error) {
if err := s.storage.SetLock(ctx, req.Ref, req.Lock); err != nil {
var st *rpc.Status
switch err.(type) {
case errtypes.IsNotFound:
st = status.NewNotFound(ctx, "path not found when setting lock")
case errtypes.PermissionDenied:
st = status.NewPermissionDenied(ctx, err, "permission denied")
default:
st = status.NewInternal(ctx, fmt.Sprintf("error setting lock %s: %s", req.Ref.String(), err))
}
return &provider.SetLockResponse{
Status: st,
}, nil
}

res := &provider.SetLockResponse{
Status: status.NewOK(ctx),
}
return res, nil
}

// GetLock returns an existing lock on the given reference
func (s *service) GetLock(ctx context.Context, req *provider.GetLockRequest) (*provider.GetLockResponse, error) {
var lock *provider.Lock
var err error
if lock, err = s.storage.GetLock(ctx, req.Ref); err != nil {
var st *rpc.Status
switch err.(type) {
case errtypes.IsNotFound:
st = status.NewNotFound(ctx, "path not found when getting lock")
case errtypes.PermissionDenied:
st = status.NewPermissionDenied(ctx, err, "permission denied")
default:
st = status.NewInternal(ctx, fmt.Sprintf("error getting lock %s: %s", req.Ref.String(), err))
}
return &provider.GetLockResponse{
Status: st,
}, nil
}

res := &provider.GetLockResponse{
Status: status.NewOK(ctx),
Lock: lock,
}
return res, nil
}

// RefreshLock refreshes an existing lock on the given reference
func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) (*provider.RefreshLockResponse, error) {
if err := s.storage.RefreshLock(ctx, req.Ref, req.Lock); err != nil {
var st *rpc.Status
switch err.(type) {
case errtypes.IsNotFound:
st = status.NewNotFound(ctx, "path not found when refreshing lock")
case errtypes.PermissionDenied:
st = status.NewPermissionDenied(ctx, err, "permission denied")
default:
st = status.NewInternal(ctx, fmt.Sprintf("error refreshing lock %s: %s", req.Ref.String(), err))
}
return &provider.RefreshLockResponse{
Status: st,
}, nil
}

res := &provider.RefreshLockResponse{
Status: status.NewOK(ctx),
}
return res, nil
}

// Unlock removes an existing lock from the given reference
func (s *service) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provider.UnlockResponse, error) {
if err := s.storage.Unlock(ctx, req.Ref); err != nil {
var st *rpc.Status
switch err.(type) {
case errtypes.IsNotFound:
st = status.NewNotFound(ctx, "path not found when unlocking")
case errtypes.PermissionDenied:
st = status.NewPermissionDenied(ctx, err, "permission denied")
default:
st = status.NewInternal(ctx, fmt.Sprintf("error unlocking %s: %s", req.Ref.String(), err))
}
return &provider.UnlockResponse{
Status: st,
}, nil
}

res := &provider.UnlockResponse{
Status: status.NewOK(ctx),
}
return res, nil
}

func (s *service) InitiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*provider.InitiateFileDownloadResponse, error) {
// TODO(labkode): maybe add some checks before download starts? eg. check permissions?
// TODO(labkode): maybe add short-lived token?
Expand Down
20 changes: 20 additions & 0 deletions pkg/storage/fs/nextcloud/nextcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,26 @@ func (nc *StorageDriver) UnsetArbitraryMetadata(ctx context.Context, ref *provid
return err
}

// GetLock returns an existing lock on the given reference
func (nc *StorageDriver) GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) {
return nil, errtypes.NotSupported("unimplemented")
}

// SetLock puts a lock on the given reference
func (nc *StorageDriver) SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error {
return errtypes.NotSupported("unimplemented")
}

// RefreshLock refreshes an existing lock on the given reference
func (nc *StorageDriver) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error {
return errtypes.NotSupported("unimplemented")
}

// Unlock removes an existing lock from the given reference
func (nc *StorageDriver) Unlock(ctx context.Context, ref *provider.Reference) error {
return errtypes.NotSupported("unimplemented")
}

// ListStorageSpaces as defined in the storage.FS interface
func (nc *StorageDriver) ListStorageSpaces(ctx context.Context, f []*provider.ListStorageSpacesRequest_Filter, _ map[string]struct{}) ([]*provider.StorageSpace, error) {
bodyStr, _ := json.Marshal(f)
Expand Down
20 changes: 20 additions & 0 deletions pkg/storage/fs/owncloud/owncloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,26 @@ func (fs *ocfs) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Refere
}
}

// GetLock returns an existing lock on the given reference
func (fs *ocfs) GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) {
return nil, errtypes.NotSupported("unimplemented")
}

// SetLock puts a lock on the given reference
func (fs *ocfs) SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error {
return errtypes.NotSupported("unimplemented")
}

// RefreshLock refreshes an existing lock on the given reference
func (fs *ocfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error {
return errtypes.NotSupported("unimplemented")
}

// Unlock removes an existing lock from the given reference
func (fs *ocfs) Unlock(ctx context.Context, ref *provider.Reference) error {
return errtypes.NotSupported("unimplemented")
}

// Delete is actually only a move to trash
//
// This is a first optimistic approach.
Expand Down
20 changes: 20 additions & 0 deletions pkg/storage/fs/owncloudsql/owncloudsql.go
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,26 @@ func (fs *owncloudsqlfs) UnsetArbitraryMetadata(ctx context.Context, ref *provid
}
}

// GetLock returns an existing lock on the given reference
func (fs *owncloudsqlfs) GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) {
return nil, errtypes.NotSupported("unimplemented")
}

// SetLock puts a lock on the given reference
func (fs *owncloudsqlfs) SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error {
return errtypes.NotSupported("unimplemented")
}

// RefreshLock refreshes an existing lock on the given reference
func (fs *owncloudsqlfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error {
return errtypes.NotSupported("unimplemented")
}

// Unlock removes an existing lock from the given reference
func (fs *owncloudsqlfs) Unlock(ctx context.Context, ref *provider.Reference) error {
return errtypes.NotSupported("unimplemented")
}

// Delete is actually only a move to trash
//
// This is a first optimistic approach.
Expand Down
Loading

0 comments on commit 73c3c4b

Please sign in to comment.