feat(ocis): bump reva

Signed-off-by: jkoberg <jkoberg@owncloud.com>
This commit is contained in:
jkoberg
2025-01-07 13:49:49 +01:00
parent b13a3a3a92
commit fcbc552f16
13 changed files with 165 additions and 31 deletions

View File

@@ -0,0 +1,5 @@
Enhancement: Bump Reva
Bumps the reva version
https://github.com/owncloud/ocis/pull/10830

2
go.mod
View File

@@ -17,7 +17,7 @@ require (
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/coreos/go-oidc/v3 v3.11.0
github.com/cs3org/go-cs3apis v0.0.0-20241105092511-3ad35d174fc1
github.com/cs3org/reva/v2 v2.27.0
github.com/cs3org/reva/v2 v2.27.1-0.20250107124628-bd76241aa776
github.com/davidbyttow/govips/v2 v2.15.0
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e

4
go.sum
View File

@@ -255,8 +255,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c=
github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME=
github.com/cs3org/go-cs3apis v0.0.0-20241105092511-3ad35d174fc1 h1:RU6LT6mkD16xZs011+8foU7T3LrPvTTSWeTQ9OgfhkA=
github.com/cs3org/go-cs3apis v0.0.0-20241105092511-3ad35d174fc1/go.mod h1:DedpcqXl193qF/08Y04IO0PpxyyMu8+GrkD6kWK2MEQ=
github.com/cs3org/reva/v2 v2.27.0 h1:Lq8VBRjQmyCfCO6+wC80Z4vH2Q1MfgORggg1e6mEcdM=
github.com/cs3org/reva/v2 v2.27.0/go.mod h1:fJWmn7EkttWOWphZfiKdFOcHuthcUsU55aSN1VeTOhU=
github.com/cs3org/reva/v2 v2.27.1-0.20250107124628-bd76241aa776 h1:tNLN9UCR9OHhZUHftWKfJyNPPaS0HaT0QOH4zGln/UE=
github.com/cs3org/reva/v2 v2.27.1-0.20250107124628-bd76241aa776/go.mod h1:OrCNgIFkp3ROHiEjNCj8eZHACmYCD4owtFRuYFlYZkU=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=

View File

@@ -315,6 +315,7 @@ func (s *service) InitiateFileUpload(ctx context.Context, req *provider.Initiate
uReq := &provider.InitiateFileUploadRequest{
Ref: cs3Ref,
Opaque: req.Opaque,
LockId: req.LockId,
}
gatewayClient, err := s.gatewaySelector.Next()

View File

@@ -84,6 +84,7 @@ type lockInfo struct {
Shared *struct{} `xml:"lockscope>shared"`
Write *struct{} `xml:"locktype>write"`
Owner owner `xml:"owner"`
LockID string `xml:"locktoken>href"`
}
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_owner
@@ -144,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.
//
@@ -184,13 +185,6 @@ func (cls *cs3LS) Create(ctx context.Context, now time.Time, details LockDetails
}
*/
// Having a lock token provides no special access rights. Anyone can find out anyone
// else's lock token by performing lock discovery. Locks must be enforced based upon
// whatever authentication mechanism is used by the server, not based on the secrecy
// of the token values.
// see: http://www.webdav.org/specs/rfc2518.html#n-lock-tokens
token := uuid.New()
u := ctxpkg.ContextMustGetUser(ctx)
// add metadata via opaque
@@ -198,6 +192,17 @@ func (cls *cs3LS) Create(ctx context.Context, now time.Time, details LockDetails
o := utils.AppendPlainToOpaque(nil, "lockownername", u.GetDisplayName())
o = utils.AppendPlainToOpaque(o, "locktime", now.Format(time.RFC3339))
lockid := details.LockID
if lockid == "" {
// Having a lock token provides no special access rights. Anyone can find out anyone
// else's lock token by performing lock discovery. Locks must be enforced based upon
// whatever authentication mechanism is used by the server, not based on the secrecy
// of the token values.
// see: http://www.webdav.org/specs/rfc2518.html#n-lock-tokens
token := uuid.New()
lockid = lockTokenPrefix + token.String()
}
r := &provider.SetLockRequest{
Ref: details.Root,
Lock: &provider.Lock{
@@ -205,7 +210,7 @@ func (cls *cs3LS) Create(ctx context.Context, now time.Time, details LockDetails
Type: provider.LockType_LOCK_TYPE_EXCL,
User: details.UserID, // no way to set an app lock? TODO maybe via the ownerxml
//AppName: , // TODO use a urn scheme?
LockId: lockTokenPrefix + token.String(), // can be a token or a Coded-URL
LockId: lockid,
},
}
if details.Duration > 0 {
@@ -227,15 +232,52 @@ func (cls *cs3LS) Create(ctx context.Context, now time.Time, details LockDetails
}
switch res.GetStatus().GetCode() {
case rpc.Code_CODE_OK:
return lockTokenPrefix + token.String(), nil
return lockid, nil
default:
return "", ocdavErrors.NewErrFromStatus(res.GetStatus())
}
}
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 {
@@ -287,6 +329,8 @@ type LockDetails struct {
OwnerName string
// Locktime is the time the lock was created
Locktime time.Time
// LockID is the lock token
LockID string
}
func readLockInfo(r io.Reader) (li lockInfo, status int, err error) {
@@ -450,7 +494,7 @@ func (s *svc) lockReference(ctx context.Context, w http.ResponseWriter, r *http.
u := ctxpkg.ContextMustGetUser(ctx)
token, now, created := "", time.Now(), false
ld := LockDetails{UserID: u.Id, Root: ref, Duration: duration, OwnerName: u.GetDisplayName(), Locktime: now}
ld := LockDetails{UserID: u.Id, Root: ref, Duration: duration, OwnerName: u.GetDisplayName(), Locktime: now, LockID: li.LockID}
if li == (lockInfo{}) {
// An empty lockInfo means to refresh the lock.
ih, ok := parseIfHeader(r.Header.Get(net.HeaderIf))
@@ -463,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
@@ -471,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."

View File

@@ -24,6 +24,7 @@ import (
"net"
"net/url"
"os"
"regexp"
"strings"
"sync"
@@ -130,7 +131,7 @@ func (a *authorizer) IsProviderAllowed(ctx context.Context, pi *ocmprovider.Prov
var providerAuthorized bool
if normalizedDomain != "" {
for _, p := range a.providers {
if p.Domain == normalizedDomain {
if ok, err := regexp.MatchString(p.Domain, normalizedDomain); ok && err == nil {
providerAuthorized = true
break
}

View File

@@ -474,20 +474,47 @@ func (d *driver) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Refer
return errtypes.NotSupported("operation not supported")
}
// SetLock sets a lock on a file
func (d *driver) SetLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error {
return errtypes.NotSupported("operation not supported")
client, _, rel, err := d.webdavClient(ctx, nil, ref)
if err != nil {
return err
}
return client.Lock(rel, lock.GetLockId())
}
func (d *driver) GetLock(ctx context.Context, ref *provider.Reference) (*provider.Lock, error) {
return nil, errtypes.NotSupported("operation not supported")
client, _, rel, err := d.webdavClient(ctx, nil, ref)
if err != nil {
return nil, err
}
token, err := client.GetLock(rel)
if err != nil {
return nil, err
}
return &provider.Lock{LockId: token, Type: provider.LockType_LOCK_TYPE_EXCL}, nil
}
func (d *driver) RefreshLock(ctx context.Context, ref *provider.Reference, lock *provider.Lock, existingLockID string) error {
return errtypes.NotSupported("operation not supported")
client, _, rel, err := d.webdavClient(ctx, nil, ref)
if err != nil {
return err
}
return client.RefreshLock(rel, lock.GetLockId())
}
// Unlock removes a lock from a file
func (d *driver) Unlock(ctx context.Context, ref *provider.Reference, lock *provider.Lock) error {
return errtypes.NotSupported("operation not supported")
client, _, rel, err := d.webdavClient(ctx, nil, ref)
if err != nil {
return err
}
return client.Unlock(rel, lock.GetLockId())
}
func (d *driver) ListStorageSpaces(ctx context.Context, filters []*provider.ListStorageSpacesRequest_Filter, _ bool) ([]*provider.StorageSpace, error) {

View File

@@ -106,7 +106,8 @@ func (d *driver) Upload(ctx context.Context, req storage.UploadRequest, _ storag
}
})
return &provider.ResourceInfo{}, client.WriteStream(rel, req.Body, 0)
locktoken, _ := ctxpkg.ContextGetLockID(ctx)
return &provider.ResourceInfo{}, client.WriteStream(rel, req.Body, 0, locktoken)
}
// UseIn tells the tus upload middleware which extensions it supports.
@@ -356,7 +357,7 @@ func (u *upload) FinishUpload(ctx context.Context) error {
return err
}
defer f.Close()
return client.WriteStream(rel, f, 0)
return client.WriteStream(rel, f, 0, "")
}
func (u *upload) Terminate(ctx context.Context) error {

View File

@@ -288,7 +288,8 @@ type CapabilitiesFilesSharingFederation struct {
// CapabilitiesNotifications holds a list of notification endpoints
type CapabilitiesNotifications struct {
Endpoints []string `json:"ocs-endpoints,omitempty" xml:"ocs-endpoints>element,omitempty" mapstructure:"endpoints"`
Endpoints []string `json:"ocs-endpoints,omitempty" xml:"ocs-endpoints>element,omitempty" mapstructure:"endpoints"`
Configurable bool `json:"configurable" xml:"configurable,omitempty" mapstructure:"configurable"`
}
// CapabilitiesTheme holds theming capabilities

View File

@@ -24,6 +24,7 @@ import (
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
"github.com/rs/zerolog"
@@ -109,6 +110,10 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) {
ref := &provider.Reference{Path: fn}
if lockID := r.Header.Get("X-Lock-Id"); lockID != "" {
ctx = ctxpkg.ContextSetLockID(ctx, lockID)
}
info, err := fs.Upload(ctx, storage.UploadRequest{
Ref: ref,
Body: r.Body,

View File

@@ -50,6 +50,7 @@ import (
"github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/pkg/errors"
"github.com/shamaton/msgpack/v2"
"golang.org/x/sync/errgroup"
)
@@ -744,12 +745,58 @@ func (fs *Decomposedfs) DeleteStorageSpace(ctx context.Context, req *provider.De
return err
}
// remove space metadata
if err := os.RemoveAll(fs.getSpaceRoot(spaceID)); err != nil {
root := fs.getSpaceRoot(spaceID)
// walkfn will delete the blob if the node has one
walkfn := func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if filepath.Ext(path) != ".mpk" {
return nil
}
b, err := os.ReadFile(path)
if err != nil {
return err
}
m := map[string][]byte{}
if err := msgpack.Unmarshal(b, &m); err != nil {
return err
}
bid := m["user.ocis.blobid"]
if string(bid) == "" {
return nil
}
if err := fs.tp.DeleteBlob(&node.Node{
BlobID: string(bid),
SpaceID: spaceID,
}); err != nil {
return err
}
// remove .mpk file so subsequent attempts will not try to delete the blob again
return os.Remove(path)
}
// This is deletes all blobs of the space
// NOTE: This isn't needed when no s3 is used, but we can't differentiate that here...
if err := filepath.Walk(root, walkfn); err != nil {
return err
}
// TODO remove space blobs with s3 backend by adding a purge method to the Blobstore interface
// remove space metadata
if err := os.RemoveAll(root); err != nil {
return err
}
// try removing the space root node
// Note that this will fail when there are other spaceids starting with the same two digits.
_ = os.Remove(filepath.Dir(root))
return nil
}

View File

@@ -75,8 +75,8 @@ func SplitStorageID(sid string) (storageID, spaceID string) {
// The result format will look like:
// <storageid>$<spaceid>!<opaqueid>
func FormatResourceID(sid *provider.ResourceId) string {
if sid.OpaqueId == "" {
return FormatStorageID(sid.StorageId, sid.SpaceId)
if sid.GetOpaqueId() == "" {
return FormatStorageID(sid.GetStorageId(), sid.GetSpaceId())
}
return strings.Join([]string{FormatStorageID(sid.StorageId, sid.SpaceId), sid.OpaqueId}, _idDelimiter)
}

2
vendor/modules.txt vendored
View File

@@ -367,7 +367,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1
github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1
github.com/cs3org/go-cs3apis/cs3/tx/v1beta1
github.com/cs3org/go-cs3apis/cs3/types/v1beta1
# github.com/cs3org/reva/v2 v2.27.0
# github.com/cs3org/reva/v2 v2.27.1-0.20250107124628-bd76241aa776
## explicit; go 1.22.0
github.com/cs3org/reva/v2/cmd/revad/internal/grace
github.com/cs3org/reva/v2/cmd/revad/runtime