From d357f5d0f2d1fd2efe6ce3a7b01321b807067ca5 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Mon, 23 Dec 2024 17:08:26 +0100 Subject: [PATCH] feat(ocdav): allow lock refreshing Signed-off-by: jkoberg --- go.mod | 2 +- go.sum | 4 +- .../http/services/owncloud/ocdav/locks.go | 47 +++++++++++++++++-- pkg/ocm/storage/received/ocm.go | 3 +- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index bccbb892c5..d6359f818b 100644 --- a/go.mod +++ b/go.mod @@ -229,7 +229,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/studio-b12/gowebdav => github.com/kobergj/gowebdav v0.0.0-20241223142249-060874be3bb2 +replace github.com/studio-b12/gowebdav => github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202 // exclude the v2 line of go-sqlite3 which was released accidentally and prevents pulling in newer versions of go-sqlite3 // see https://github.com/mattn/go-sqlite3/issues/965 for more details diff --git a/go.sum b/go.sum index d167557444..1715082d73 100644 --- a/go.sum +++ b/go.sum @@ -492,8 +492,8 @@ github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90 github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/kobergj/gowebdav v0.0.0-20241223142249-060874be3bb2 h1:jtEsQsh9Wpo622GUZwMmcV3fR4nw1PZWhob4z530nz0= -github.com/kobergj/gowebdav v0.0.0-20241223142249-060874be3bb2/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE= +github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202 h1:A1xJ2NKgiYFiaHiLl9B5yw/gUBACSs9crDykTS3GuQI= +github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= diff --git a/internal/http/services/owncloud/ocdav/locks.go b/internal/http/services/owncloud/ocdav/locks.go index 9f66a0f778..da98699615 100644 --- a/internal/http/services/owncloud/ocdav/locks.go +++ b/internal/http/services/owncloud/ocdav/locks.go @@ -145,7 +145,7 @@ type LockSystem interface { // // See http://www.webdav.org/specs/rfc4918.html#rfc.section.9.10.6 for // when to use each error. - Refresh(ctx context.Context, now time.Time, token string, duration time.Duration) (LockDetails, error) + Refresh(ctx context.Context, now time.Time, ref *provider.Reference, token string) error // Unlock unlocks the lock with the given token. // @@ -239,8 +239,45 @@ func (cls *cs3LS) Create(ctx context.Context, now time.Time, details LockDetails } -func (cls *cs3LS) Refresh(ctx context.Context, now time.Time, token string, duration time.Duration) (LockDetails, error) { - return LockDetails{}, ocdavErrors.ErrNotImplemented +func (cls *cs3LS) Refresh(ctx context.Context, now time.Time, ref *provider.Reference, token string) error { + u := ctxpkg.ContextMustGetUser(ctx) + + // add metadata via opaque + // TODO: upate cs3api: https://github.com/cs3org/cs3apis/issues/213 + o := utils.AppendPlainToOpaque(nil, "lockownername", u.GetDisplayName()) + o = utils.AppendPlainToOpaque(o, "locktime", now.Format(time.RFC3339)) + + if token == "" { + return errors.New("token is empty") + } + + r := &provider.RefreshLockRequest{ + Ref: ref, + Lock: &provider.Lock{ + Opaque: o, + Type: provider.LockType_LOCK_TYPE_EXCL, + //AppName: , // TODO use a urn scheme? + LockId: token, + User: u.GetId(), + }, + } + + client, err := cls.selector.Next() + if err != nil { + return err + } + + res, err := client.RefreshLock(ctx, r) + if err != nil { + return err + } + switch res.GetStatus().GetCode() { + case rpc.Code_CODE_OK: + return nil + + default: + return ocdavErrors.NewErrFromStatus(res.GetStatus()) + } } func (cls *cs3LS) Unlock(ctx context.Context, now time.Time, ref *provider.Reference, token string) error { @@ -470,7 +507,7 @@ func (s *svc) lockReference(ctx context.Context, w http.ResponseWriter, r *http. if token == "" { return http.StatusBadRequest, ocdavErrors.ErrInvalidLockToken } - ld, err = s.LockSystem.Refresh(ctx, now, token, duration) + err = s.LockSystem.Refresh(ctx, now, ref, token) if err != nil { if err == ocdavErrors.ErrNoSuchLock { return http.StatusPreconditionFailed, err @@ -478,6 +515,8 @@ func (s *svc) lockReference(ctx context.Context, w http.ResponseWriter, r *http. return http.StatusInternalServerError, err } + ld.LockID = token + } else { // Section 9.10.3 says that "If no Depth header is submitted on a LOCK request, // then the request MUST act as if a "Depth:infinity" had been submitted." diff --git a/pkg/ocm/storage/received/ocm.go b/pkg/ocm/storage/received/ocm.go index 0b069ccc34..02b5d8235a 100644 --- a/pkg/ocm/storage/received/ocm.go +++ b/pkg/ocm/storage/received/ocm.go @@ -504,8 +504,7 @@ func (d *driver) RefreshLock(ctx context.Context, ref *provider.Reference, lock return err } - err = client.RefreshLock(rel, lock.GetLockId()) - return err + return client.RefreshLock(rel, lock.GetLockId()) } // Unlock removes a lock from a file