Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dummy implementation of the Lock CS3APIs #2350

Merged
merged 3 commits into from
Dec 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
84 changes: 82 additions & 2 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,7 @@ func (s *svc) SetArbitraryMetadata(ctx context.Context, req *provider.SetArbitra
if gstatus.Code(err) == codes.PermissionDenied {
return &provider.SetArbitraryMetadataResponse{Status: &rpc.Status{Code: rpc.Code_CODE_PERMISSION_DENIED}}, nil
}
return nil, errors.Wrap(err, "gateway: error calling Stat")
return nil, errors.Wrap(err, "gateway: error calling SetArbitraryMetadata")
}

return res, nil
Expand All @@ -1221,7 +1221,87 @@ func (s *svc) UnsetArbitraryMetadata(ctx context.Context, req *provider.UnsetArb
if gstatus.Code(err) == codes.PermissionDenied {
return &provider.UnsetArbitraryMetadataResponse{Status: &rpc.Status{Code: rpc.Code_CODE_PERMISSION_DENIED}}, nil
}
return nil, errors.Wrap(err, "gateway: error calling Stat")
return nil, errors.Wrap(err, "gateway: error calling UnsetArbitraryMetadata")
}

return res, nil
}

// SetLock puts a lock on the given reference
func (s *svc) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provider.SetLockResponse, error) {
c, err := s.find(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) {
c, err := s.find(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) {
c, err := s.find(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) {
c, err := s.find(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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,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
126 changes: 126 additions & 0 deletions internal/grpc/services/storageprovider/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,132 @@ 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) {
newRef, err := s.unwrap(ctx, req.Ref)
if err != nil {
err := errors.Wrap(err, "storageprovidersvc: error unwrapping path")
return &provider.SetLockResponse{
Status: status.NewInternal(ctx, err, "error setting lock"),
}, nil
}

if err := s.storage.SetLock(ctx, newRef, 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, err, "error setting lock: "+req.Ref.String())
}
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) {
newRef, err := s.unwrap(ctx, req.Ref)
if err != nil {
err := errors.Wrap(err, "storageprovidersvc: error unwrapping path")
return &provider.GetLockResponse{
Status: status.NewInternal(ctx, err, "error getting lock"),
}, nil
}

var lock *provider.Lock
if lock, err = s.storage.GetLock(ctx, newRef); 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, err, "error getting lock: "+req.Ref.String())
}
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) {
newRef, err := s.unwrap(ctx, req.Ref)
if err != nil {
err := errors.Wrap(err, "storageprovidersvc: error unwrapping path")
return &provider.RefreshLockResponse{
Status: status.NewInternal(ctx, err, "error refreshing lock"),
}, nil
}

if err = s.storage.RefreshLock(ctx, newRef, 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, err, "error refreshing lock: "+req.Ref.String())
}
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) {
newRef, err := s.unwrap(ctx, req.Ref)
if err != nil {
err := errors.Wrap(err, "storageprovidersvc: error unwrapping path")
return &provider.UnlockResponse{
Status: status.NewInternal(ctx, err, "error on unlocking"),
}, nil
}

if err = s.storage.Unlock(ctx, newRef); 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, err, "error unlocking: "+req.Ref.String())
}
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 @@ -1473,6 +1473,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
20 changes: 20 additions & 0 deletions pkg/storage/fs/s3/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,26 @@ func (fs *s3FS) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Refere
return errtypes.NotSupported("s3: operation not supported")
}

// GetLock returns an existing lock on the given reference
func (fs *s3FS) 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 *s3FS) 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 *s3FS) 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 *s3FS) Unlock(ctx context.Context, ref *provider.Reference) error {
return errtypes.NotSupported("unimplemented")
}

func (fs *s3FS) CreateReference(ctx context.Context, path string, targetURI *url.URL) error {
// TODO(jfd):implement
return errtypes.NotSupported("s3: operation not supported")
Expand Down
Loading