From 61cb398bf225a198c1b680339671ee18c4bb2209 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Tue, 12 Mar 2024 16:57:44 +0100 Subject: [PATCH] Move reva to stable-2.19 branch stable-5.0 does no longer use edge --- go.mod | 2 +- go.sum | 4 +- .../eventsmiddleware/conversion.go | 18 ++++ .../interceptors/eventsmiddleware/events.go | 9 ++ .../internal/grpc/services/gateway/gateway.go | 12 +++ .../grpc/services/gateway/ocmshareprovider.go | 14 +-- .../services/gateway/publicshareprovider.go | 34 +++++++- .../grpc/services/gateway/storageprovider.go | 17 ++++ .../services/gateway/storageprovidercache.go | 85 ++++++++++++------- .../services/gateway/usershareprovider.go | 10 ++- .../http/services/owncloud/ocdav/dav.go | 2 +- .../cs3org/reva/v2/pkg/events/files.go | 30 +++++++ .../cs3org/reva/v2/pkg/rhttp/datatx/datatx.go | 6 ++ .../pkg/rhttp/datatx/manager/simple/simple.go | 3 + .../pkg/rhttp/datatx/manager/spaces/spaces.go | 3 + .../v2/pkg/rhttp/datatx/manager/tus/tus.go | 5 ++ .../utils/decomposedfs/decomposedfs.go | 9 ++ .../utils/decomposedfs/options/options.go | 5 +- .../storage/utils/decomposedfs/tree/tree.go | 1 - vendor/modules.txt | 2 +- 20 files changed, 223 insertions(+), 48 deletions(-) diff --git a/go.mod b/go.mod index 523a0a96c2b..c619d0e9362 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/cenkalti/backoff v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.9.0 github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 - github.com/cs3org/reva/v2 v2.19.2-0.20240307091744-fa2caba1f4e4 + github.com/cs3org/reva/v2 v2.19.2-0.20240312144105-9d61fada7d92 github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 github.com/disintegration/imaging v1.6.2 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e diff --git a/go.sum b/go.sum index 2e2b7b0cbad..6c8a4979b1d 100644 --- a/go.sum +++ b/go.sum @@ -1019,8 +1019,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-20231023073225-7748710e0781 h1:BUdwkIlf8IS2FasrrPg8gGPHQPOrQ18MS1Oew2tmGtY= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.19.2-0.20240307091744-fa2caba1f4e4 h1:dOApLUv2cYnWU1Z8pqEBk8a9BEGe6VRl/f0sFmwzLw4= -github.com/cs3org/reva/v2 v2.19.2-0.20240307091744-fa2caba1f4e4/go.mod h1:GRUrOp5HbFVwZTgR9bVrMZ/MvVy+Jhxw1PdMmhhKP9E= +github.com/cs3org/reva/v2 v2.19.2-0.20240312144105-9d61fada7d92 h1:prG6ijbZgfMheujalOny12VXQmjibIXYhO/dk0ZDFpE= +github.com/cs3org/reva/v2 v2.19.2-0.20240312144105-9d61fada7d92/go.mod h1:GRUrOp5HbFVwZTgR9bVrMZ/MvVy+Jhxw1PdMmhhKP9E= 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= diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/interceptors/eventsmiddleware/conversion.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/interceptors/eventsmiddleware/conversion.go index a4ff32f62b1..edcab27e37b 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/interceptors/eventsmiddleware/conversion.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/interceptors/eventsmiddleware/conversion.go @@ -216,6 +216,24 @@ func FileDownloaded(r *provider.InitiateFileDownloadResponse, req *provider.Init } } +// FileLocked converts the response to an events +func FileLocked(r *provider.SetLockResponse, req *provider.SetLockRequest, owner, executant *user.UserId) events.FileLocked { + return events.FileLocked{ + Executant: executant, + Ref: req.Ref, + Timestamp: utils.TSNow(), + } +} + +// FileUnlocked converts the response to an event +func FileUnlocked(r *provider.UnlockResponse, req *provider.UnlockRequest, owner, executant *user.UserId) events.FileUnlocked { + return events.FileUnlocked{ + Executant: executant, + Ref: req.Ref, + Timestamp: utils.TSNow(), + } +} + // ItemTrashed converts the response to an event func ItemTrashed(r *provider.DeleteResponse, req *provider.DeleteRequest, spaceOwner, executant *user.UserId) events.ItemTrashed { opaqueID := utils.ReadPlainFromOpaque(r.Opaque, "opaque_id") diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/interceptors/eventsmiddleware/events.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/interceptors/eventsmiddleware/events.go index 8566f8bdefa..558a96010d2 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/interceptors/eventsmiddleware/events.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/interceptors/eventsmiddleware/events.go @@ -184,6 +184,15 @@ func NewUnary(m map[string]interface{}) (grpc.UnaryServerInterceptor, int, error if isSuccess(v) { ev = FileTouched(v, req.(*provider.TouchFileRequest), ownerID, executantID) } + case *provider.SetLockResponse: + fmt.Println("set lock response", v) + if isSuccess(v) { + ev = FileLocked(v, req.(*provider.SetLockRequest), ownerID, executantID) + } + case *provider.UnlockResponse: + if isSuccess(v) { + ev = FileUnlocked(v, req.(*provider.UnlockRequest), ownerID, executantID) + } } if ev != nil { diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/gateway.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/gateway.go index c3a30e12ca5..23bc84274a7 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/gateway.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/gateway.go @@ -72,6 +72,7 @@ type config struct { DataTransfersFolder string `mapstructure:"data_transfers_folder"` TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"` AllowedUserAgents map[string][]string `mapstructure:"allowed_user_agents"` // map[path][]user-agent + StatCacheConfig cache.Config `mapstructure:"stat_cache_config"` CreatePersonalSpaceCacheConfig cache.Config `mapstructure:"create_personal_space_cache_config"` ProviderCacheConfig cache.Config `mapstructure:"provider_cache_config"` UseCommonSpaceRootShareLogic bool `mapstructure:"use_common_space_root_share_logic"` @@ -121,6 +122,14 @@ func (c *config) init() { } // caching needs to be explicitly enabled + if c.StatCacheConfig.Store == "" { + c.StatCacheConfig.Store = "noop" + } + + if c.StatCacheConfig.Database == "" { + c.StatCacheConfig.Database = "reva" + } + if c.ProviderCacheConfig.Store == "" { c.ProviderCacheConfig.Store = "noop" } @@ -142,6 +151,7 @@ type svc struct { c *config dataGatewayURL url.URL tokenmgr token.Manager + statCache cache.StatCache providerCache cache.ProviderCache createPersonalSpaceCache cache.CreatePersonalSpaceCache } @@ -172,6 +182,7 @@ func New(m map[string]interface{}, _ *grpc.Server) (rgrpc.Service, error) { c: c, dataGatewayURL: *u, tokenmgr: tokenManager, + statCache: cache.GetStatCache(c.StatCacheConfig), providerCache: cache.GetProviderCache(c.ProviderCacheConfig), createPersonalSpaceCache: cache.GetCreatePersonalSpaceCache(c.CreatePersonalSpaceCacheConfig), } @@ -184,6 +195,7 @@ func (s *svc) Register(ss *grpc.Server) { } func (s *svc) Close() error { + s.statCache.Close() s.providerCache.Close() s.createPersonalSpaceCache.Close() return nil diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/ocmshareprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/ocmshareprovider.go index 3cdac238d26..6ee1182c4e5 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/ocmshareprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/ocmshareprovider.go @@ -52,17 +52,21 @@ func (s *svc) CreateOCMShare(ctx context.Context, req *ocm.CreateOCMShareRequest } status, err := s.addGrant(ctx, req.ResourceId, req.Grantee, req.AccessMethods[0].GetWebdavOptions().Permissions, req.Expiration, nil) - switch { - case err != nil: + if err != nil { appctx.GetLogger(ctx).Debug().Interface("status", status).Interface("req", req).Msg(err.Error()) return nil, errors.Wrap(err, "gateway: error adding grant to storage") - case status.Code == rpc.Code_CODE_UNIMPLEMENTED: + } + + switch status.Code { + case rpc.Code_CODE_OK: + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.ResourceId) + case rpc.Code_CODE_UNIMPLEMENTED: appctx.GetLogger(ctx).Debug().Interface("status", status).Interface("req", req).Msg("storing grants not supported, ignoring") - case status.Code != rpc.Code_CODE_OK: + default: appctx.GetLogger(ctx).Debug().Interface("status", status).Interface("req", req).Msg("storing grants is not successful") return &ocm.CreateOCMShareResponse{ Status: status, - }, nil + }, err } return res, nil diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/publicshareprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/publicshareprovider.go index 4738acd7c54..7a683f18902 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/publicshareprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/publicshareprovider.go @@ -21,9 +21,11 @@ package gateway import ( "context" + userprovider "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" "github.com/cs3org/reva/v2/pkg/appctx" + ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" "github.com/pkg/errors" ) @@ -37,7 +39,15 @@ func (s *svc) CreatePublicShare(ctx context.Context, req *link.CreatePublicShare return nil, err } - return c.CreatePublicShare(ctx, req) + res, err := c.CreatePublicShare(ctx, req) + if err != nil { + return nil, err + } + + if res.GetShare() != nil { + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), res.Share.ResourceId) + } + return res, nil } func (s *svc) RemovePublicShare(ctx context.Context, req *link.RemovePublicShareRequest) (*link.RemovePublicShareResponse, error) { @@ -48,7 +58,13 @@ func (s *svc) RemovePublicShare(ctx context.Context, req *link.RemovePublicShare if err != nil { return nil, err } - return driver.RemovePublicShare(ctx, req) + res, err := driver.RemovePublicShare(ctx, req) + if err != nil { + return nil, err + } + // TODO: How to find out the resourceId? -> get public share first, then delete + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), nil) + return res, nil } func (s *svc) GetPublicShareByToken(ctx context.Context, req *link.GetPublicShareByTokenRequest) (*link.GetPublicShareByTokenResponse, error) { @@ -121,5 +137,17 @@ func (s *svc) UpdatePublicShare(ctx context.Context, req *link.UpdatePublicShare }, nil } - return pClient.UpdatePublicShare(ctx, req) + res, err := pClient.UpdatePublicShare(ctx, req) + if err != nil { + return nil, errors.Wrap(err, "error updating share") + } + if res.GetShare() != nil { + s.statCache.RemoveStatContext(ctx, + &userprovider.UserId{ + OpaqueId: res.Share.Owner.GetOpaqueId(), + }, + res.Share.ResourceId, + ) + } + return res, nil } diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovider.go index 781295963da..cf3a7387e3e 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovider.go @@ -326,6 +326,7 @@ func (s *svc) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorag if res.Status.Code == rpc.Code_CODE_OK { id := res.StorageSpace.Root + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), id) s.providerCache.RemoveListStorageProviders(id) } return res, nil @@ -362,6 +363,7 @@ func (s *svc) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorag } id := &provider.ResourceId{OpaqueId: req.Id.OpaqueId} + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), id) s.providerCache.RemoveListStorageProviders(id) if dsRes.Status.Code != rpc.Code_CODE_OK { @@ -606,6 +608,7 @@ func (s *svc) InitiateFileUpload(ctx context.Context, req *provider.InitiateFile } } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return &gateway.InitiateFileUploadResponse{ Opaque: storageRes.Opaque, Status: storageRes.Status, @@ -642,6 +645,7 @@ func (s *svc) CreateContainer(ctx context.Context, req *provider.CreateContainer }, nil } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -684,6 +688,7 @@ func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provide }, nil } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -710,6 +715,8 @@ func (s *svc) Move(ctx context.Context, req *provider.MoveRequest) (*provider.Mo req.Source = sref req.Destination = dref + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Source.ResourceId) + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Destination.ResourceId) return c.Move(ctx, req) } @@ -732,6 +739,7 @@ func (s *svc) SetArbitraryMetadata(ctx context.Context, req *provider.SetArbitra return nil, errors.Wrap(err, "gateway: error calling SetArbitraryMetadata") } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -753,6 +761,7 @@ func (s *svc) UnsetArbitraryMetadata(ctx context.Context, req *provider.UnsetArb } return nil, errors.Wrap(err, "gateway: error calling UnsetArbitraryMetadata") } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -776,6 +785,7 @@ func (s *svc) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provi return nil, errors.Wrap(err, "gateway: error calling SetLock") } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -816,6 +826,7 @@ func (s *svc) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) return nil, errors.Wrap(err, "gateway: error calling RefreshLock") } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -836,10 +847,12 @@ func (s *svc) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provide return nil, errors.Wrap(err, "gateway: error calling Unlock") } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } // Stat returns the Resoure info for a given resource by forwarding the request to the responsible provider. +// TODO cache info func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { c, _, ref, err := s.findAndUnwrapUnique(ctx, req.Ref) if err != nil { @@ -914,6 +927,7 @@ func (s *svc) RestoreFileVersion(ctx context.Context, req *provider.RestoreFileV }, nil } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -969,6 +983,7 @@ func (s *svc) RestoreRecycleItem(ctx context.Context, req *provider.RestoreRecyc }, nil } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -991,6 +1006,7 @@ func (s *svc) PurgeRecycle(ctx context.Context, req *provider.PurgeRecycleReques }, nil } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Ref.ResourceId) return res, nil } @@ -1090,6 +1106,7 @@ func (s *svc) getStorageProviderClient(_ context.Context, p *registry.ProviderIn return &cachedAPIClient{ c: c, + statCache: s.statCache, createPersonalSpaceCache: s.createPersonalSpaceCache, }, nil } diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovidercache.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovidercache.go index f3db156ec2d..8dd5d720b5e 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovidercache.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/storageprovidercache.go @@ -20,6 +20,7 @@ package gateway import ( "context" + "strings" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -83,9 +84,40 @@ func (c *cachedRegistryClient) GetHome(ctx context.Context, in *registry.GetHome type cachedAPIClient struct { c provider.ProviderAPIClient + statCache cache.StatCache createPersonalSpaceCache cache.CreatePersonalSpaceCache } +// Stat looks in cache first before forwarding to storage provider +func (c *cachedAPIClient) Stat(ctx context.Context, in *provider.StatRequest, opts ...grpc.CallOption) (*provider.StatResponse, error) { + key := c.statCache.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId(), in.GetRef(), in.GetArbitraryMetadataKeys(), in.GetFieldMask().GetPaths()) + if key != "" { + s := &provider.StatResponse{} + if err := c.statCache.PullFromCache(key, s); err == nil { + return s, nil + } + } + + resp, err := c.c.Stat(ctx, in, opts...) + switch { + case err != nil: + return nil, err + case resp.Status.Code != rpc.Code_CODE_OK: + return resp, nil + case key == "": + return resp, nil + case strings.Contains(key, "sid:"+utils.ShareStorageProviderID): + // We cannot cache shares at the moment: + // we do not know when to invalidate them + // FIXME: find a way to cache/invalidate them too + return resp, nil + case utils.ReadPlainFromOpaque(resp.GetInfo().GetOpaque(), "status") == "processing": + return resp, nil + default: + return resp, c.statCache.PushToCache(key, resp) + } +} + // CreateHome caches calls to CreateHome locally - anyways they only need to be called once per user func (c *cachedAPIClient) CreateHome(ctx context.Context, in *provider.CreateHomeRequest, opts ...grpc.CallOption) (*provider.CreateHomeResponse, error) { key := c.createPersonalSpaceCache.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId()) @@ -108,37 +140,8 @@ func (c *cachedAPIClient) CreateHome(ctx context.Context, in *provider.CreateHom } } -// CreateStorageSpace creates a storage space -func (c *cachedAPIClient) CreateStorageSpace(ctx context.Context, in *provider.CreateStorageSpaceRequest, opts ...grpc.CallOption) (*provider.CreateStorageSpaceResponse, error) { - if in.Type == "personal" { - key := c.createPersonalSpaceCache.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId()) - if key != "" { - s := &provider.CreateStorageSpaceResponse{} - if err := c.createPersonalSpaceCache.PullFromCache(key, s); err == nil { - return s, nil - } - } - resp, err := c.c.CreateStorageSpace(ctx, in, opts...) - switch { - case err != nil: - return nil, err - case resp.Status.Code != rpc.Code_CODE_OK && resp.Status.Code != rpc.Code_CODE_ALREADY_EXISTS: - return resp, nil - case key == "": - return resp, nil - default: - return resp, c.createPersonalSpaceCache.PushToCache(key, resp) - } - } - return c.c.CreateStorageSpace(ctx, in, opts...) -} - // methods below here are not cached, they just call the client directly -// Stat returns the Resoure info for a given resource -func (c *cachedAPIClient) Stat(ctx context.Context, in *provider.StatRequest, opts ...grpc.CallOption) (*provider.StatResponse, error) { - return c.c.Stat(ctx, in, opts...) -} func (c *cachedAPIClient) AddGrant(ctx context.Context, in *provider.AddGrantRequest, opts ...grpc.CallOption) (*provider.AddGrantResponse, error) { return c.c.AddGrant(ctx, in, opts...) } @@ -226,6 +229,29 @@ func (c *cachedAPIClient) Unlock(ctx context.Context, in *provider.UnlockRequest func (c *cachedAPIClient) GetHome(ctx context.Context, in *provider.GetHomeRequest, opts ...grpc.CallOption) (*provider.GetHomeResponse, error) { return c.c.GetHome(ctx, in, opts...) } +func (c *cachedAPIClient) CreateStorageSpace(ctx context.Context, in *provider.CreateStorageSpaceRequest, opts ...grpc.CallOption) (*provider.CreateStorageSpaceResponse, error) { + if in.Type == "personal" { + key := c.createPersonalSpaceCache.GetKey(ctxpkg.ContextMustGetUser(ctx).GetId()) + if key != "" { + s := &provider.CreateStorageSpaceResponse{} + if err := c.createPersonalSpaceCache.PullFromCache(key, s); err == nil { + return s, nil + } + } + resp, err := c.c.CreateStorageSpace(ctx, in, opts...) + switch { + case err != nil: + return nil, err + case resp.Status.Code != rpc.Code_CODE_OK && resp.Status.Code != rpc.Code_CODE_ALREADY_EXISTS: + return resp, nil + case key == "": + return resp, nil + default: + return resp, c.createPersonalSpaceCache.PushToCache(key, resp) + } + } + return c.c.CreateStorageSpace(ctx, in, opts...) +} func (c *cachedAPIClient) ListStorageSpaces(ctx context.Context, in *provider.ListStorageSpacesRequest, opts ...grpc.CallOption) (*provider.ListStorageSpacesResponse, error) { return c.c.ListStorageSpaces(ctx, in, opts...) } @@ -235,6 +261,7 @@ func (c *cachedAPIClient) UpdateStorageSpace(ctx context.Context, in *provider.U func (c *cachedAPIClient) DeleteStorageSpace(ctx context.Context, in *provider.DeleteStorageSpaceRequest, opts ...grpc.CallOption) (*provider.DeleteStorageSpaceResponse, error) { return c.c.DeleteStorageSpace(ctx, in, opts...) } + func (c *cachedAPIClient) TouchFile(ctx context.Context, in *provider.TouchFileRequest, opts ...grpc.CallOption) (*provider.TouchFileResponse, error) { return c.c.TouchFile(ctx, in, opts...) } diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/usershareprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/usershareprovider.go index 910375d4704..ebfd5241dc4 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/usershareprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/gateway/usershareprovider.go @@ -154,6 +154,7 @@ func (s *svc) updateShare(ctx context.Context, req *collaboration.UpdateShareReq } } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), res.Share.ResourceId) return res, nil } @@ -197,6 +198,7 @@ func (s *svc) updateSpaceShare(ctx context.Context, req *collaboration.UpdateSha return res, nil } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.GetShare().GetResourceId()) s.providerCache.RemoveListStorageProviders(req.GetShare().GetResourceId()) return res, nil } @@ -280,6 +282,7 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update }, nil } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.Share.Share.ResourceId) return c.UpdateReceivedShare(ctx, req) /* TODO: Leftover from master merge. Do we need this? @@ -548,7 +551,7 @@ func (s *svc) addShare(ctx context.Context, req *collaboration.CreateShareReques } if s.c.CommitShareToStorageGrant { - // If the share is a denial we call denyGrant instead. + // If the share is a denial we call denyGrant instead. var status *rpc.Status if grants.PermissionsEqual(req.Grant.Permissions.Permissions, &provider.ResourcePermissions{}) { status, err = s.denyGrant(ctx, req.ResourceInfo.Id, req.Grant.Grantee, nil) @@ -566,7 +569,7 @@ func (s *svc) addShare(ctx context.Context, req *collaboration.CreateShareReques switch status.Code { case rpc.Code_CODE_OK: - // ok + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.ResourceInfo.Id) case rpc.Code_CODE_UNIMPLEMENTED: appctx.GetLogger(ctx).Debug().Interface("status", status).Interface("req", req).Msg("storing grants not supported, ignoring") rollBackFn(status) @@ -614,6 +617,7 @@ func (s *svc) addSpaceShare(ctx context.Context, req *collaboration.CreateShareR switch st.Code { case rpc.Code_CODE_OK: + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), req.ResourceInfo.Id) s.providerCache.RemoveListStorageProviders(req.ResourceInfo.Id) case rpc.Code_CODE_UNIMPLEMENTED: appctx.GetLogger(ctx).Debug().Interface("status", st).Interface("req", req).Msg("storing grants not supported, ignoring") @@ -692,6 +696,7 @@ func (s *svc) removeShare(ctx context.Context, req *collaboration.RemoveShareReq } } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), share.ResourceId) return res, nil } @@ -724,6 +729,7 @@ func (s *svc) removeSpaceShare(ctx context.Context, ref *provider.ResourceId, gr Status: removeGrantStatus, }, err } + s.statCache.RemoveStatContext(ctx, ctxpkg.ContextMustGetUser(ctx).GetId(), ref) s.providerCache.RemoveListStorageProviders(ref) return &collaboration.RemoveShareResponse{Status: status.NewOK(ctx)}, nil } diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/dav.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/dav.go index db26d729bd9..ec3fc85a3fe 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/dav.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/dav.go @@ -255,7 +255,7 @@ func (h *DavHandler) Handler(s *svc) http.Handler { sig := q.Get("signature") expiration := q.Get("expiration") // We restrict the pre-signed urls to downloads. - if sig != "" && expiration != "" && r.Method != http.MethodGet { + if sig != "" && expiration != "" && !(r.Method == http.MethodGet || r.Method == http.MethodHead) { w.WriteHeader(http.StatusUnauthorized) return } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/events/files.go b/vendor/github.com/cs3org/reva/v2/pkg/events/files.go index cc21a4b07d1..e4b1017fd23 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/events/files.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/events/files.go @@ -88,6 +88,36 @@ func (FileDownloaded) Unmarshal(v []byte) (interface{}, error) { return e, err } +// FileLocked is emitted when a file is locked +type FileLocked struct { + Executant *user.UserId + Ref *provider.Reference + Owner *user.UserId + Timestamp *types.Timestamp +} + +// Unmarshal to fulfill umarshaller interface +func (FileLocked) Unmarshal(v []byte) (interface{}, error) { + e := FileLocked{} + err := json.Unmarshal(v, &e) + return e, err +} + +// FileUnlocked is emitted when a file is unlocked +type FileUnlocked struct { + Executant *user.UserId + Ref *provider.Reference + Owner *user.UserId + Timestamp *types.Timestamp +} + +// Unmarshal to fulfill umarshaller interface +func (FileUnlocked) Unmarshal(v []byte) (interface{}, error) { + e := FileUnlocked{} + err := json.Unmarshal(v, &e) + return e, err +} + // ItemTrashed is emitted when a file or folder is trashed type ItemTrashed struct { SpaceOwner *user.UserId diff --git a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/datatx.go b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/datatx.go index cdbb27052e4..23328aadd96 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/datatx.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/datatx.go @@ -28,6 +28,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/v2/pkg/events" "github.com/cs3org/reva/v2/pkg/storage" + "github.com/cs3org/reva/v2/pkg/storage/cache" "github.com/cs3org/reva/v2/pkg/utils" ) @@ -52,3 +53,8 @@ func EmitFileUploadedEvent(spaceOwnerOrManager, executant *userv1beta1.UserId, r return events.Publish(context.Background(), publisher, uploadedEv) } + +// InvalidateCache is a helper function which invalidates the stat cache +func InvalidateCache(owner *userv1beta1.UserId, ref *provider.Reference, statCache cache.StatCache) { + statCache.RemoveStatContext(context.TODO(), owner, ref.GetResourceId()) +} diff --git a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/simple/simple.go b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/simple/simple.go index 607d6336adc..6699c9f77a2 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/simple/simple.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/simple/simple.go @@ -48,6 +48,7 @@ func init() { type manager struct { conf *cache.Config publisher events.Publisher + statCache cache.StatCache } func parseConfig(m map[string]interface{}) (*cache.Config, error) { @@ -69,6 +70,7 @@ func New(m map[string]interface{}, publisher events.Publisher) (datatx.DataTX, e return &manager{ conf: c, publisher: publisher, + statCache: cache.GetStatCache(*c), }, nil } @@ -108,6 +110,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { Body: r.Body, Length: r.ContentLength, }, func(spaceOwner, owner *userpb.UserId, ref *provider.Reference) { + datatx.InvalidateCache(owner, ref, m.statCache) if err := datatx.EmitFileUploadedEvent(spaceOwner, owner, ref, m.publisher); err != nil { sublog.Error().Err(err).Msg("failed to publish FileUploaded event") } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/spaces/spaces.go b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/spaces/spaces.go index ce585ab5426..d39b12baa53 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/spaces/spaces.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/spaces/spaces.go @@ -50,6 +50,7 @@ func init() { type manager struct { conf *cache.Config publisher events.Publisher + statCache cache.StatCache } func parseConfig(m map[string]interface{}) (*cache.Config, error) { @@ -71,6 +72,7 @@ func New(m map[string]interface{}, publisher events.Publisher) (datatx.DataTX, e return &manager{ conf: c, publisher: publisher, + statCache: cache.GetStatCache(*c), }, nil } @@ -115,6 +117,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { Body: r.Body, Length: r.ContentLength, }, func(spaceOwner, owner *userpb.UserId, ref *provider.Reference) { + datatx.InvalidateCache(owner, ref, m.statCache) if err := datatx.EmitFileUploadedEvent(spaceOwner, owner, ref, m.publisher); err != nil { sublog.Error().Err(err).Msg("failed to publish FileUploaded event") } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/tus/tus.go b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/tus/tus.go index f86b100866c..e9b2a07b039 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/tus/tus.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/tus/tus.go @@ -37,6 +37,7 @@ import ( "github.com/cs3org/reva/v2/pkg/rhttp/datatx/manager/registry" "github.com/cs3org/reva/v2/pkg/rhttp/datatx/metrics" "github.com/cs3org/reva/v2/pkg/storage" + "github.com/cs3org/reva/v2/pkg/storage/cache" "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/mitchellh/mapstructure" ) @@ -46,6 +47,7 @@ func init() { } type TusConfig struct { + cache.Config CorsEnabled bool `mapstructure:"cors_enabled"` CorsAllowOrigin string `mapstructure:"cors_allow_origin"` CorsAllowCredentials bool `mapstructure:"cors_allow_credentials"` @@ -58,6 +60,7 @@ type TusConfig struct { type manager struct { conf *TusConfig publisher events.Publisher + statCache cache.StatCache } func parseConfig(m map[string]interface{}) (*TusConfig, error) { @@ -78,6 +81,7 @@ func New(m map[string]interface{}, publisher events.Publisher) (datatx.DataTX, e return &manager{ conf: c, publisher: publisher, + statCache: cache.GetStatCache(c.Config), }, nil } @@ -138,6 +142,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { up := ups[0] executant := up.Executant() ref := up.Reference() + datatx.InvalidateCache(&executant, &ref, m.statCache) if m.publisher != nil { if err := datatx.EmitFileUploadedEvent(up.SpaceOwner(), &executant, &ref, m.publisher); err != nil { appctx.GetLogger(context.Background()).Error().Err(err).Msg("failed to publish FileUploaded event") diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go index f06a50f80ad..35cc29663fc 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go @@ -40,6 +40,7 @@ import ( "github.com/cs3org/reva/v2/pkg/rhttp/datatx/metrics" "github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download" "github.com/cs3org/reva/v2/pkg/storage" + "github.com/cs3org/reva/v2/pkg/storage/cache" "github.com/cs3org/reva/v2/pkg/storage/utils/chunking" "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/aspects" "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/lookup" @@ -107,6 +108,7 @@ type Decomposedfs struct { p permissions.Permissions chunkHandler *chunking.ChunkHandler stream events.Stream + cache cache.StatCache sessionStore SessionStore UserCache *ttlcache.Cache @@ -207,6 +209,7 @@ func New(o *options.Options, aspects aspects.Aspects) (storage.FS, error) { p: aspects.Permissions, chunkHandler: chunking.NewChunkHandler(filepath.Join(o.Root, "uploads")), stream: aspects.EventStream, + cache: cache.GetStatCache(o.StatCache), UserCache: ttlcache.NewCache(), userSpaceIndex: userSpaceIndex, groupSpaceIndex: groupSpaceIndex, @@ -321,6 +324,9 @@ func (fs *Decomposedfs) Postprocessing(ch <-chan events.Event) { fs.sessionStore.Cleanup(ctx, session, revertNodeMetadata, keepUpload, unmarkPostprocessing) + // remove cache entry in gateway + fs.cache.RemoveStatContext(ctx, ev.ExecutingUser.GetId(), &provider.ResourceId{SpaceId: n.SpaceID, OpaqueId: n.ID}) + if err := events.Publish( ctx, fs.stream, @@ -488,6 +494,9 @@ func (fs *Decomposedfs) Postprocessing(ch <-chan events.Event) { } metrics.UploadSessionsScanned.Inc() + + // remove cache entry in gateway + fs.cache.RemoveStatContext(ctx, ev.ExecutingUser.GetId(), &provider.ResourceId{SpaceId: n.SpaceID, OpaqueId: n.ID}) default: log.Error().Interface("event", ev).Msg("Unknown event") } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/options/options.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/options/options.go index 086490879b7..f21912687c2 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/options/options.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/options/options.go @@ -73,10 +73,9 @@ type Options struct { Tokens TokenOptions `mapstructure:"tokens"` - // FileMetadataCache for file metadata + StatCache cache.Config `mapstructure:"statcache"` FileMetadataCache cache.Config `mapstructure:"filemetadatacache"` - // IDCache for symlink lookups of direntry to node id - IDCache cache.Config `mapstructure:"idcache"` + IDCache cache.Config `mapstructure:"idcache"` MaxAcquireLockCycles int `mapstructure:"max_acquire_lock_cycles"` LockCycleDurationFactor int `mapstructure:"lock_cycle_duration_factor"` diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/tree.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/tree.go index 1a1dae32f90..6fc5176af31 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/tree.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/tree.go @@ -70,7 +70,6 @@ type Tree struct { options *options.Options - // used to cache symlink lookups for child names to node ids idCache store.Store } diff --git a/vendor/modules.txt b/vendor/modules.txt index 2c30375ccc6..ab737afc434 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -359,7 +359,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.19.2-0.20240307091744-fa2caba1f4e4 +# github.com/cs3org/reva/v2 v2.19.2-0.20240312144105-9d61fada7d92 ## explicit; go 1.21 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime