diff --git a/changelog/unreleased/refresh-lock-improvements.md b/changelog/unreleased/refresh-lock-improvements.md new file mode 100644 index 0000000000..afea87ada0 --- /dev/null +++ b/changelog/unreleased/refresh-lock-improvements.md @@ -0,0 +1,6 @@ +Enhancement: Make Refresh Lock operation WOPI compliant + +We now support the WOPI compliant `UnlockAndRelock` operation. This has been implemented in the Eos FS. To make use of it, we need a compatible WOPI server. + +https://github.com/cs3org/reva/pull/3289 +https://learn.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/rest/files/unlockandrelock diff --git a/go.mod b/go.mod index d923b65329..7c898be745 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,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-20220719130120-361e9f987d64 + github.com/cs3org/go-cs3apis v0.0.0-20220929083235-bb0b1a236d6c github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 github.com/dgraph-io/ristretto v0.1.0 github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59 diff --git a/go.sum b/go.sum index 5174067ba4..0f75960c3a 100644 --- a/go.sum +++ b/go.sum @@ -228,6 +228,8 @@ github.com/cs3org/go-cs3apis v0.0.0-20220330081745-2ad58f5932b9 h1:SuPu5Mc2mpz+J github.com/cs3org/go-cs3apis v0.0.0-20220330081745-2ad58f5932b9/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cs3org/go-cs3apis v0.0.0-20220719130120-361e9f987d64 h1:cFnankJOCWndnOns4sKRG7yzH61ammK2Am6rEGWCK40= github.com/cs3org/go-cs3apis v0.0.0-20220719130120-361e9f987d64/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= +github.com/cs3org/go-cs3apis v0.0.0-20220929083235-bb0b1a236d6c h1:b+YTmOGlf43mnF8MzO0fsy8/Ho8JLu44Iq5Y0fKLJMM= +github.com/cs3org/go-cs3apis v0.0.0-20220929083235-bb0b1a236d6c/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/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index bba333ad7a..2129e930f0 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -354,7 +354,7 @@ func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequ }, nil } - if err = s.storage.RefreshLock(ctx, newRef, req.Lock); err != nil { + if err = s.storage.RefreshLock(ctx, newRef, req.Lock, req.ExistingLockId); err != nil { var st *rpc.Status switch err.(type) { case errtypes.IsNotFound: diff --git a/pkg/storage/fs/cback/cback.go b/pkg/storage/fs/cback/cback.go index 22a60e106f..63d2c162bb 100644 --- a/pkg/storage/fs/cback/cback.go +++ b/pkg/storage/fs/cback/cback.go @@ -478,7 +478,7 @@ func (fs *cback) GetLock(ctx context.Context, ref *provider.Reference) (*provide return nil, errtypes.NotSupported("Operation Not Permitted") } -func (fs *cback) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { +func (fs *cback) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { return errtypes.NotSupported("Operation Not Permitted") } diff --git a/pkg/storage/fs/nextcloud/nextcloud.go b/pkg/storage/fs/nextcloud/nextcloud.go index bb8f7ff555..71c3617373 100644 --- a/pkg/storage/fs/nextcloud/nextcloud.go +++ b/pkg/storage/fs/nextcloud/nextcloud.go @@ -781,7 +781,7 @@ func (nc *StorageDriver) SetLock(ctx context.Context, ref *provider.Reference, l } // RefreshLock refreshes an existing lock on the given reference -func (nc *StorageDriver) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { +func (nc *StorageDriver) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { return errtypes.NotSupported("unimplemented") } diff --git a/pkg/storage/fs/owncloud/owncloud.go b/pkg/storage/fs/owncloud/owncloud.go index 862ce823bb..1b74b7ab43 100644 --- a/pkg/storage/fs/owncloud/owncloud.go +++ b/pkg/storage/fs/owncloud/owncloud.go @@ -1484,7 +1484,7 @@ func (fs *ocfs) SetLock(ctx context.Context, ref *provider.Reference, lock *prov } // RefreshLock refreshes an existing lock on the given reference -func (fs *ocfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { +func (fs *ocfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { return errtypes.NotSupported("unimplemented") } diff --git a/pkg/storage/fs/owncloudsql/owncloudsql.go b/pkg/storage/fs/owncloudsql/owncloudsql.go index b64d688a30..ebf2796c49 100644 --- a/pkg/storage/fs/owncloudsql/owncloudsql.go +++ b/pkg/storage/fs/owncloudsql/owncloudsql.go @@ -1035,7 +1035,7 @@ func (fs *owncloudsqlfs) SetLock(ctx context.Context, ref *provider.Reference, l } // RefreshLock refreshes an existing lock on the given reference -func (fs *owncloudsqlfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { +func (fs *owncloudsqlfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { return errtypes.NotSupported("unimplemented") } diff --git a/pkg/storage/fs/s3/s3.go b/pkg/storage/fs/s3/s3.go index b777697e64..32a90fe428 100644 --- a/pkg/storage/fs/s3/s3.go +++ b/pkg/storage/fs/s3/s3.go @@ -291,7 +291,7 @@ func (fs *s3FS) SetLock(ctx context.Context, ref *provider.Reference, lock *prov } // RefreshLock refreshes an existing lock on the given reference -func (fs *s3FS) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { +func (fs *s3FS) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { return errtypes.NotSupported("unimplemented") } diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index b8af0eeb1a..ebec63a004 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -60,7 +60,7 @@ type FS interface { UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) - RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error + RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter) ([]*provider.StorageSpace, error) CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) diff --git a/pkg/storage/utils/decomposedfs/decomposedfs.go b/pkg/storage/utils/decomposedfs/decomposedfs.go index 33dadb0d06..427a429a74 100644 --- a/pkg/storage/utils/decomposedfs/decomposedfs.go +++ b/pkg/storage/utils/decomposedfs/decomposedfs.go @@ -538,7 +538,7 @@ func (fs *Decomposedfs) SetLock(ctx context.Context, ref *provider.Reference, lo } // RefreshLock refreshes an existing lock on the given reference -func (fs *Decomposedfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { +func (fs *Decomposedfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { return errtypes.NotSupported("unimplemented") } diff --git a/pkg/storage/utils/eosfs/eosfs.go b/pkg/storage/utils/eosfs/eosfs.go index 197bbcf1da..64f8981b25 100644 --- a/pkg/storage/utils/eosfs/eosfs.go +++ b/pkg/storage/utils/eosfs/eosfs.go @@ -869,9 +869,7 @@ func encodeLock(l *provider.Lock) (string, error) { } // RefreshLock refreshes an existing lock on the given reference -func (fs *eosfs) RefreshLock(ctx context.Context, ref *provider.Reference, newLock *provider.Lock) error { - // TODO (gdelmont): check if the new lock is already expired? - +func (fs *eosfs) RefreshLock(ctx context.Context, ref *provider.Reference, newLock *provider.Lock, existingLockID string) error { if newLock.Type == provider.LockType_LOCK_TYPE_SHARED { return errtypes.NotSupported("shared lock not yet implemented") } @@ -897,6 +895,10 @@ func (fs *eosfs) RefreshLock(ctx context.Context, ref *provider.Reference, newLo return errtypes.BadRequest("caller does not hold the lock") } + if existingLockID != "" && oldLock.LockId != existingLockID { + return errtypes.BadRequest("mismatching existing lock id") + } + path, err := fs.resolve(ctx, ref) if err != nil { return errors.Wrap(err, "eosfs: error resolving reference") diff --git a/pkg/storage/utils/localfs/localfs.go b/pkg/storage/utils/localfs/localfs.go index 7673ee4577..f7e6abdc59 100644 --- a/pkg/storage/utils/localfs/localfs.go +++ b/pkg/storage/utils/localfs/localfs.go @@ -722,7 +722,7 @@ func (fs *localfs) SetLock(ctx context.Context, ref *provider.Reference, lock *p } // RefreshLock refreshes an existing lock on the given reference -func (fs *localfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error { +func (fs *localfs) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error { return errtypes.NotSupported("unimplemented") }