deps: Bump reva to latest main

for getting https://github.com/opencloud-eu/reva/pull/360
This commit is contained in:
Ralf Haferkamp
2025-10-06 11:21:57 +02:00
committed by Ralf Haferkamp
parent f096285769
commit 9ec532da93
18 changed files with 203 additions and 53 deletions
@@ -150,7 +150,10 @@ func NewUnary(m map[string]interface{}, unprotected []string, tp trace.TracerPro
log.Warn().Err(err).Msg("access token is invalid")
return nil, status.Errorf(codes.PermissionDenied, "auth: core access token is invalid")
}
if sharedconf.MultiTenantEnabled() && u.GetId().GetType() != userpb.UserType_USER_TYPE_SERVICE && u.GetId().GetTenantId() == "" {
log.Warn().Msg("user has no tenant id, rejecting request")
return nil, status.Errorf(codes.PermissionDenied, "auth: user has no tenant id, rejecting request")
}
// store user and scopes in context
ctx = ctxpkg.ContextSetUser(ctx, u)
ctx = ctxpkg.ContextSetScopes(ctx, tokenScope)
@@ -32,6 +32,7 @@ import (
"github.com/opencloud-eu/reva/v2/pkg/errtypes"
"github.com/opencloud-eu/reva/v2/pkg/group"
"github.com/opencloud-eu/reva/v2/pkg/group/manager/registry"
"github.com/opencloud-eu/reva/v2/pkg/sharedconf"
"github.com/opencloud-eu/reva/v2/pkg/utils"
ldapIdentity "github.com/opencloud-eu/reva/v2/pkg/utils/ldap"
"github.com/pkg/errors"
@@ -71,6 +72,10 @@ func parseConfig(m map[string]interface{}) (*config, error) {
// New returns a group manager implementation that connects to a LDAP server to provide group metadata.
func New(m map[string]interface{}) (group.Manager, error) {
if sharedconf.MultiTenantEnabled() {
return nil, errtypes.NotSupported("ldap group manager does not support multi-tenancy")
}
mgr := &manager{}
err := mgr.Configure(m)
if err != nil {
@@ -22,5 +22,6 @@ import (
// Load core group manager drivers.
_ "github.com/opencloud-eu/reva/v2/pkg/group/manager/json"
_ "github.com/opencloud-eu/reva/v2/pkg/group/manager/ldap"
_ "github.com/opencloud-eu/reva/v2/pkg/group/manager/null"
// Add your own here
)
+62
View File
@@ -0,0 +1,62 @@
// Copyright 2018-2020 CERN
// Copyright 2025 OpenCloud GmbH
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
package null
import (
"context"
grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
"github.com/opencloud-eu/reva/v2/pkg/errtypes"
"github.com/opencloud-eu/reva/v2/pkg/group"
"github.com/opencloud-eu/reva/v2/pkg/group/manager/registry"
)
func init() {
registry.Register("null", New)
}
type manager struct {
}
// New returns a group manager implementation that return NOT FOUND or empty result set for every call
func New(m map[string]interface{}) (group.Manager, error) {
return &manager{}, nil
}
func (m *manager) GetGroup(ctx context.Context, gid *grouppb.GroupId, skipFetchingMembers bool) (*grouppb.Group, error) {
return nil, errtypes.NotFound(gid.OpaqueId)
}
func (m *manager) GetGroupByClaim(ctx context.Context, claim, value string, skipFetchingMembers bool) (*grouppb.Group, error) {
return nil, errtypes.NotFound(value)
}
func (m *manager) FindGroups(ctx context.Context, query string, skipFetchingMembers bool) ([]*grouppb.Group, error) {
return []*grouppb.Group{}, nil
}
func (m *manager) GetMembers(ctx context.Context, gid *grouppb.GroupId) ([]*userpb.UserId, error) {
return nil, errtypes.NotFound(gid.OpaqueId)
}
func (m *manager) HasMember(ctx context.Context, gid *grouppb.GroupId, uid *userpb.UserId) (bool, error) {
return false, errtypes.NotFound(gid.OpaqueId)
}
+6
View File
@@ -42,6 +42,7 @@ type conf struct {
GatewaySVC string `mapstructure:"gatewaysvc"`
DataGateway string `mapstructure:"datagateway"`
SkipUserGroupsInToken bool `mapstructure:"skip_user_groups_in_token"`
MultiTenantEnabled bool `mapstructure:"multi_tenant_enabled"`
GRPCClientOptions ClientOptions `mapstructure:"grpc_client_options"`
}
@@ -107,6 +108,11 @@ func SkipUserGroupsInToken() bool {
return sharedConf.SkipUserGroupsInToken
}
// MultiTenantEnabled returns whether this is a mulit-tenant enabled configuratio
func MultiTenantEnabled() bool {
return sharedConf.MultiTenantEnabled
}
// GRPCClientOptions returns the global grpc client options
func GRPCClientOptions() ClientOptions {
return sharedConf.GRPCClientOptions
@@ -303,6 +303,22 @@ func (lu *Lookup) InternalPath(spaceID, nodeID string) string {
return path
}
// LockfilePaths returns the paths(s) to the lockfile of the node
func (lu *Lookup) LockfilePaths(spaceID, nodeID string) []string {
spaceRoot, _ := lu.IDCache.Get(context.Background(), spaceID, spaceID)
if len(spaceRoot) == 0 {
return nil
}
paths := []string{filepath.Join(spaceRoot, MetadataDir, Pathify(nodeID, 4, 2)+".lock")}
nodepath := lu.InternalPath(spaceID, nodeID)
if len(nodepath) > 0 {
paths = append(paths, nodepath+".lock")
}
return paths
}
// VersionPath returns the path to the version of the node
func (lu *Lookup) VersionPath(spaceID, nodeID, version string) string {
spaceRoot, _ := lu.IDCache.Get(context.Background(), spaceID, spaceID)
@@ -399,7 +399,7 @@ func (t *Tree) generateTempNodeId(path string) string {
return strings.ReplaceAll(strings.TrimPrefix(path, "/"), "/", "-")
} else {
// Use sha256 if path too long
pathHash := fmt.Sprintf("%x", sha256.Sum256([]byte(path)))[:240]
pathHash := fmt.Sprintf("%x", sha256.Sum256([]byte(path)))
t.log.Info().Str("path", path).Msg("path too long, using sha256 as lock: " + pathHash)
return pathHash
}
+6 -13
View File
@@ -343,8 +343,6 @@ func (t *Tree) CreateDir(ctx context.Context, n *node.Node) (err error) {
// Move replaces the target with the source
func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node) (err error) {
lockFilePath := oldNode.LockFilePath()
if oldNode.SpaceID != newNode.SpaceID {
// WebDAV RFC https://www.rfc-editor.org/rfc/rfc4918#section-9.9.4 says to use
// > 502 (Bad Gateway) - This may occur when the destination is on another
@@ -400,14 +398,6 @@ func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node)
return errors.Wrap(err, "posixfs: could not update node attributes")
}
// rename the lock (if it exists)
if _, err := os.Stat(lockFilePath); err == nil {
err = os.Rename(lockFilePath, newNode.LockFilePath())
if err != nil {
return errors.Wrap(err, "posixfs: could not move lock")
}
}
// update id cache for the moved subtree.
if oldNode.IsDir(ctx) {
err = t.WarmupIDCache(filepath.Join(newNode.ParentPath(), newNode.Name), false, false)
@@ -582,8 +572,11 @@ func (t *Tree) Delete(ctx context.Context, n *node.Node) error {
}
// Remove lock file if it exists
if err := os.Remove(n.LockFilePath()); err != nil {
t.log.Error().Err(err).Str("path", n.LockFilePath()).Msg("could not remove lock file")
paths := n.LockFilePaths()
for _, lockFilePath := range paths {
if err := os.Remove(lockFilePath); err != nil && !os.IsNotExist(err) {
t.log.Error().Err(err).Str("path", lockFilePath).Msg("could not remove lock file")
}
}
err := t.trashbin.MoveToTrash(ctx, n, path)
@@ -747,7 +740,7 @@ func (t *Tree) isInternal(path string) bool {
}
func isLockFile(path string) bool {
return strings.HasSuffix(path, ".lock") || strings.HasSuffix(path, ".flock") || strings.HasSuffix(path, ".mlock")
return strings.HasSuffix(path, ".flock") || strings.HasSuffix(path, ".mlock")
}
func isTrash(path string) bool {
@@ -273,6 +273,11 @@ func (lu *Lookup) InternalPath(spaceID, nodeID string) string {
return filepath.Join(lu.Options.Root, "spaces", Pathify(spaceID, 1, 2), "nodes", Pathify(nodeID, 4, 2))
}
// LockfilePaths returns the paths(s) to the lockfile of the node
func (lu *Lookup) LockfilePaths(spaceID, nodeID string) []string {
return []string{lu.InternalPath(spaceID, nodeID) + ".lock"}
}
// VersionPath returns the internal path for a version of a node
// Deprecated: use InternalPath instead
func (lu *Lookup) VersionPath(spaceID, nodeID, version string) string {
@@ -40,7 +40,7 @@ import (
func (n *Node) SetLock(ctx context.Context, lock *provider.Lock) error {
ctx, span := tracer.Start(ctx, "SetLock")
defer span.End()
lockFilePath := n.LockFilePath()
lockFilePath := n.LockFilePaths()[0]
// ensure parent path exists
if err := os.MkdirAll(filepath.Dir(lockFilePath), 0700); err != nil {
@@ -90,7 +90,7 @@ func (n *Node) SetLock(ctx context.Context, lock *provider.Lock) error {
}
// ReadLock reads the lock id for a node
func (n Node) ReadLock(ctx context.Context, skipFileLock bool) (*provider.Lock, error) {
func (n *Node) ReadLock(ctx context.Context, skipFileLock bool) (*provider.Lock, error) {
ctx, span := tracer.Start(ctx, "ReadLock")
defer span.End()
@@ -124,10 +124,7 @@ func (n Node) ReadLock(ctx context.Context, skipFileLock bool) (*provider.Lock,
}()
}
_, subspan = tracer.Start(ctx, "os.Open")
f, err := os.Open(n.LockFilePath())
subspan.End()
f, err := openAndMigrateLockFile(ctx, n, os.O_RDONLY, 0)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return nil, errtypes.NotFound("no lock found")
@@ -182,7 +179,7 @@ func (n *Node) RefreshLock(ctx context.Context, lock *provider.Lock, existingLoc
}
}()
f, err := os.OpenFile(n.LockFilePath(), os.O_RDWR, os.ModeExclusive)
f, err := openAndMigrateLockFile(ctx, n, os.O_RDWR, os.ModeExclusive)
switch {
case errors.Is(err, fs.ErrNotExist):
return errtypes.PreconditionFailed("lock does not exist")
@@ -190,7 +187,6 @@ func (n *Node) RefreshLock(ctx context.Context, lock *provider.Lock, existingLoc
return errors.Wrap(err, "Decomposedfs: could not open lock file")
}
defer f.Close()
readLock := &provider.Lock{}
if err := json.NewDecoder(f).Decode(readLock); err != nil {
return errors.Wrap(err, "Decomposedfs: could not read lock")
@@ -246,7 +242,7 @@ func (n *Node) Unlock(ctx context.Context, lock *provider.Lock) error {
}
}()
f, err := os.OpenFile(n.LockFilePath(), os.O_RDONLY, os.ModeExclusive)
f, err := openAndMigrateLockFile(ctx, n, os.O_RDONLY, os.ModeExclusive)
switch {
case errors.Is(err, fs.ErrNotExist):
return errtypes.Aborted("lock does not exist")
@@ -323,8 +319,12 @@ func readLocksIntoOpaque(ctx context.Context, n *Node, ri *provider.ResourceInfo
}
func (n *Node) hasLocks(ctx context.Context) bool {
_, err := os.Stat(n.LockFilePath()) // FIXME better error checking
return err == nil
for _, p := range n.LockFilePaths() {
if _, err := os.Stat(p); err == nil {
return true
}
}
return false
}
func isLockModificationAllowed(ctx context.Context, oldLock *provider.Lock, newLock *provider.Lock) (bool, error) {
@@ -358,3 +358,45 @@ func isLockModificationAllowed(ctx context.Context, oldLock *provider.Lock, newL
return appNameEquals && lockUserEquals && contextUserEquals, nil
}
// openAndMigrateLockFile opens the lock file for a node, migrating any legacy lock files if found
// This is needed to support the transition to the new lock file scheme in the posix driver.
// Once this transition period is over the migration code can be removed again.
func openAndMigrateLockFile(ctx context.Context, n *Node, flag int, perm os.FileMode) (*os.File, error) {
lockfilePaths := n.LockFilePaths()
// check for legacy lock files and migrate them
for i := 1; i < len(lockfilePaths); i++ {
fi, err := os.Stat(lockfilePaths[i])
if err == nil {
if fi.Size() == 0 {
// this is not a lock file of ours. ignore
continue
}
f, err := os.Open(lockfilePaths[i])
if err != nil {
continue
}
defer f.Close()
readLock := &provider.Lock{}
if err := json.NewDecoder(f).Decode(readLock); err != nil {
// this is not a lock file of ours. ignore
continue
}
// legacy lock file found, move it to the new location
err = os.MkdirAll(filepath.Dir(lockfilePaths[0]), 0700)
if err != nil {
return nil, errors.Wrap(err, "Decomposedfs: could not create lock file directory")
}
if err := os.Rename(lockfilePaths[i], lockfilePaths[0]); err != nil {
return nil, errors.Wrap(err, "Decomposedfs: could not migrate lock file")
}
} else if !errors.Is(err, fs.ErrNotExist) {
return nil, errors.Wrap(err, "Decomposedfs: could not stat legacy lock file")
}
}
return os.OpenFile(lockfilePaths[0], flag, perm)
}
@@ -158,6 +158,7 @@ type PathLookup interface {
InternalRoot() string
InternalSpaceRoot(spaceID string) string
InternalPath(spaceID, nodeID string) string
LockfilePaths(spaceID, nodeID string) []string
VersionPath(spaceID, nodeID, version string) string
Path(ctx context.Context, n *Node, hasPermission PermissionFunc) (path string, err error)
MetadataBackend() metadata.Backend
@@ -635,9 +636,13 @@ func (n *Node) ParentPath() string {
return n.lu.InternalPath(n.SpaceID, n.ParentID)
}
// LockFilePath returns the internal path of the lock file of the node
func (n *Node) LockFilePath() string {
return n.InternalPath() + ".lock"
// LockfilePaths returns the paths(s) to the lockfile of the node
// Returning multiple paths allows for supporting legacy lockfiles
// while migrating to a new lockfile scheme. The first element is always the
// path to use for new locks.
// In the future only one path should remain at which point the function can return a single string.
func (n *Node) LockFilePaths() []string {
return n.lu.LockfilePaths(n.SpaceID, n.ID)
}
// CalculateEtag returns a hash of fileid + tmtime (or mtime)
@@ -501,7 +501,7 @@ func (t *Tree) Delete(ctx context.Context, n *node.Node) (err error) {
}
// Remove lock file if it exists
_ = os.Remove(n.LockFilePath())
_ = os.Remove(n.LockFilePaths()[0])
// finally remove the entry from the parent dir
if err = os.Remove(path); err != nil {
+11
View File
@@ -28,6 +28,7 @@ import (
"github.com/google/uuid"
"github.com/opencloud-eu/reva/v2/pkg/appctx"
"github.com/opencloud-eu/reva/v2/pkg/errtypes"
"github.com/opencloud-eu/reva/v2/pkg/sharedconf"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"go.opentelemetry.io/otel/attribute"
@@ -180,6 +181,16 @@ func (i *Identity) Setup() error {
return fmt.Errorf("invalid disable mechanism setting: %s", i.User.DisableMechanism)
}
if sharedconf.MultiTenantEnabled() {
if i.User.Schema.TenantID == "" {
return fmt.Errorf("Invalid configuration: a 'tenantId' user schema attribute must be defined for multi-tenant setups")
}
} else {
if i.User.Schema.TenantID != "" {
return fmt.Errorf("Invalid configuration: Superfluous 'tenantId' user schema attribute defined for single-tenant setups")
}
}
return nil
}