diff --git a/changelog/unreleased/bump-reva.md b/changelog/unreleased/bump-reva.md index 780a5550c..f736cbb3b 100644 --- a/changelog/unreleased/bump-reva.md +++ b/changelog/unreleased/bump-reva.md @@ -16,3 +16,4 @@ Changelog for reva 2.13.3 (2023-05-17) * Enhancement [cs3org/reva#3895](https://github.com/cs3org/reva/pull/3895): Add missing expiry date to shares https://github.com/owncloud/ocis/pull/6305 +https://github.com/owncloud/ocis/pull/6339 diff --git a/go.mod b/go.mod index 44f06943a..8b0f0358a 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/coreos/go-oidc v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.4.0 github.com/cs3org/go-cs3apis v0.0.0-20221012090518-ef2996678965 - github.com/cs3org/reva/v2 v2.13.3 + github.com/cs3org/reva/v2 v2.13.4-0.20230517171752-b39e78fd7b28 github.com/disintegration/imaging v1.6.2 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e github.com/egirna/icap-client v0.1.1 diff --git a/go.sum b/go.sum index 462aa78bc..1e0927a11 100644 --- a/go.sum +++ b/go.sum @@ -627,8 +627,8 @@ github.com/crewjam/httperr v0.2.0 h1:b2BfXR8U3AlIHwNeFFvZ+BV1LFvKLlzMjzaTnZMybNo github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4= github.com/crewjam/saml v0.4.13 h1:TYHggH/hwP7eArqiXSJUvtOPNzQDyQ7vwmwEqlFWhMc= github.com/crewjam/saml v0.4.13/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA= -github.com/cs3org/reva/v2 v2.13.3 h1:XP17/bl2EtwYcoX755hcg43EIagP1CAw/+loVFvHHM4= -github.com/cs3org/reva/v2 v2.13.3/go.mod h1:MoymB39kU/myG7LFkaCwqtoXQHct+/8uoZAvJEmNi+I= +github.com/cs3org/reva/v2 v2.13.4-0.20230517171752-b39e78fd7b28 h1:y8oUHEWGXrs9/jdU0sG3zNRyoDBONyxCRJJfb9Nsbqw= +github.com/cs3org/reva/v2 v2.13.4-0.20230517171752-b39e78fd7b28/go.mod h1:MoymB39kU/myG7LFkaCwqtoXQHct+/8uoZAvJEmNi+I= 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/vendor/github.com/cs3org/reva/v2/internal/http/services/appprovider/appprovider.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/appprovider/appprovider.go index 1f79b14f1..c12165788 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/appprovider/appprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/appprovider/appprovider.go @@ -33,6 +33,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/v2/internal/http/services/datagateway" + "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net" ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/rgrpc/status" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" @@ -283,26 +284,32 @@ func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { return } - // Stat the newly created file - statRes, err := client.Stat(ctx, statFileReq) - if err != nil { - writeError(w, r, appErrorServerError, "statting the created file failed", err) - return - } + var fileid string + if httpRes.Header.Get(net.HeaderOCFileID) != "" { + fileid = httpRes.Header.Get(net.HeaderOCFileID) + } else { + // Stat the newly created file + statRes, err := client.Stat(ctx, statFileReq) + if err != nil { + writeError(w, r, appErrorServerError, "statting the created file failed", err) + return + } - if statRes.Status.Code != rpc.Code_CODE_OK { - writeError(w, r, appErrorServerError, "statting the created file failed", nil) - return - } + if statRes.Status.Code != rpc.Code_CODE_OK { + writeError(w, r, appErrorServerError, "statting the created file failed", nil) + return + } - if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_FILE { - writeError(w, r, appErrorInvalidParameter, "the given file id does not point to a file", nil) - return + if statRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_FILE { + writeError(w, r, appErrorInvalidParameter, "the given file id does not point to a file", nil) + return + } + fileid = storagespace.FormatResourceID(*statRes.Info.Id) } js, err := json.Marshal( map[string]interface{}{ - "file_id": storagespace.FormatResourceID(*statRes.Info.Id), + "file_id": fileid, }, ) if err != nil { diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go index af5ea00e6..14a6cd2de 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go @@ -278,6 +278,12 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. if length == 0 || httpRes.Header.Get(net.HeaderUploadOffset) == r.Header.Get(net.HeaderUploadLength) { // get uploaded file metadata + if resid, err := storagespace.ParseID(httpRes.Header.Get(net.HeaderOCFileID)); err == nil { + sReq.Ref = &provider.Reference{ + ResourceId: &resid, + } + } + sRes, err := s.gwClient.Stat(ctx, sReq) if err != nil { log.Error().Err(err).Msg("error sending grpc stat request") diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/data/capabilities.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/data/capabilities.go index 79bb05e8b..281918da7 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/data/capabilities.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/data/capabilities.go @@ -80,8 +80,16 @@ type CapabilitiesCore struct { // CapabilitiesGraph holds the graph capabilities type CapabilitiesGraph struct { - PersonalDataExport ocsBool `json:"personal-data-export" xml:"personal-data-export" mapstructure:"personal_data_export"` - ReadOnlyUserAttributes []string `json:"read_only_user_attributes" xml:"read_only_user_attributes" mapstructure:"read_only_user_attributes"` + PersonalDataExport ocsBool `json:"personal-data-export" xml:"personal-data-export" mapstructure:"personal_data_export"` + Users CapabilitiesGraphUsers `json:"users" xml:"users" mapstructure:"users"` +} + +// CapabilitiesGraphUsers holds the graph user capabilities +type CapabilitiesGraphUsers struct { + ReadOnlyAttributes []string `json:"read_only_attributes" xml:"read_only_attributes" mapstructure:"read_only_attributes"` + CreateDisabled ocsBool `json:"create_disabled" xml:"create_disabled" mapstructure:"create_disabled"` + DeleteDisabled ocsBool `json:"delete_disabled" xml:"delete_disabled" mapstructure:"delete_disabled"` + ChangePasswordSelfDisabled ocsBool `json:"change_password_self_disabled" xml:"change_password_self_disabled" mapstructure:"change_password_self_disabled"` } // Status holds basic status information 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 0a5a626d6..f98ce8adb 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 @@ -40,6 +40,7 @@ import ( "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/cs3org/reva/v2/pkg/utils" "github.com/mitchellh/mapstructure" ) @@ -144,6 +145,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { metrics.UploadsActive.Sub(1) }() // set etag, mtime and file id + setHeaders(fs, w, r) handler.PostFile(w, r) case "HEAD": handler.HeadFile(w, r) @@ -153,7 +155,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { metrics.UploadsActive.Sub(1) }() // set etag, mtime and file id - setExpiresHeader(fs, w, r) + setHeaders(fs, w, r) handler.PatchFile(w, r) case "DELETE": handler.DelFile(w, r) @@ -180,7 +182,7 @@ type composable interface { UseIn(composer *tusd.StoreComposer) } -func setExpiresHeader(fs storage.FS, w http.ResponseWriter, r *http.Request) { +func setHeaders(fs storage.FS, w http.ResponseWriter, r *http.Request) { ctx := r.Context() id := path.Base(r.URL.Path) datastore, ok := fs.(tusd.DataStore) @@ -202,4 +204,10 @@ func setExpiresHeader(fs storage.FS, w http.ResponseWriter, r *http.Request) { if expires != "" { w.Header().Set(net.HeaderTusUploadExpires, expires) } + resourceid := provider.ResourceId{ + StorageId: info.MetaData["providerID"], + SpaceId: info.Storage["SpaceRoot"], + OpaqueId: info.Storage["NodeId"], + } + w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(resourceid)) } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/spaces.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/spaces.go index 00926d7d6..77fda6136 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/spaces.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/spaces.go @@ -652,26 +652,9 @@ func (fs *Decomposedfs) DeleteStorageSpace(ctx context.Context, req *provider.De return errtypes.InternalError(fmt.Sprintf("space %s does not have a spacetype, possible corrupt decompsedfs", n.ID)) } - // - a User with the "delete-all-spaces" permission can delete any space - // - spaces of type personal can also be deleted by users with the "delete-all-home-spaces" permission - // - otherwise a space can be deleted by its manager (i.e. users have the "remove" grant) - switch { - case fs.p.DeleteAllSpaces(ctx): - // We are allowed to delete any space, no further permission checks needed - case st == "personal": - if !fs.p.DeleteAllHomeSpaces(ctx) { - return errtypes.PermissionDenied(fmt.Sprintf("user is not allowed to delete home space %s", n.ID)) - } - default: - // managers and users with 'space ability' permission are allowed to disable or purge a drive - if !fs.p.SpaceAbility(ctx, spaceID) { - rp, err := fs.p.AssemblePermissions(ctx, n) - if err != nil || !IsManager(rp) { - return errtypes.PermissionDenied(fmt.Sprintf("user is not allowed to delete spaces %s", n.ID)) - } - } + if err := canDeleteSpace(ctx, spaceID, st, purge, n, fs.p); err != nil { + return err } - if purge { if !n.IsDisabled() { return errtypes.NewErrtypeFromStatus(status.NewInvalid(ctx, "can't purge enabled space")) @@ -1056,3 +1039,35 @@ func isGrantExpired(g *provider.Grant) bool { func (fs *Decomposedfs) getSpaceRoot(spaceID string) string { return filepath.Join(fs.o.Root, "spaces", lookup.Pathify(spaceID, 1, 2)) } + +// Space deletion can be tricky as there are lots of different cases: +// - spaces of type personal can only be disabled and deleted by users with the "delete-all-home-spaces" permission +// - a user with the "delete-all-spaces" permission may delete but not enable/disable any project space +// - a user with the "Drive.ReadWriteEnabled" permission may enable/disable but not delete any project space +// - a project space can always be enabled/disabled/deleted by its manager (i.e. users have the "remove" grant) +func canDeleteSpace(ctx context.Context, spaceID string, typ string, purge bool, n *node.Node, p Permissions) error { + // delete-all-home spaces allows to disable and delete a personal space + if typ == "personal" { + if p.DeleteAllHomeSpaces(ctx) { + return nil + } + return errtypes.PermissionDenied("user is not allowed to delete a personal space") + } + + // space managers are allowed to disable and delete their project spaces + if rp, err := p.AssemblePermissions(ctx, n); err == nil && IsManager(rp) { + return nil + } + + // delete-all-spaces permissions allows to delete (purge, NOT disable) project spaces + if purge && p.DeleteAllSpaces(ctx) { + return nil + } + + // Drive.ReadWriteEnabled allows to disable a space + if !purge && p.SpaceAbility(ctx, spaceID) { + return nil + } + + return errtypes.PermissionDenied(fmt.Sprintf("user is not allowed to delete space %s", n.ID)) +} diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/processing.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/processing.go index eab37f520..3ba1a0445 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/processing.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/processing.go @@ -154,6 +154,7 @@ func New(ctx context.Context, info tusd.FileInfo, lu *lookup.Lookup, tp Tree, p "BinPath": binPath, "NodeId": n.ID, + "NodeExists": "true", "NodeParentId": n.ParentID, "NodeName": n.Name, "SpaceRoot": spaceRoot, @@ -166,6 +167,11 @@ func New(ctx context.Context, info tusd.FileInfo, lu *lookup.Lookup, tp Tree, p "LogLevel": log.GetLevel().String(), } + if !n.Exists { + // fill future node info + info.Storage["NodeId"] = uuid.New().String() + info.Storage["NodeExists"] = "false" + } // Create binary file in the upload folder with no content log.Debug().Interface("info", info).Msg("Decomposedfs: built storage info") file, err := os.OpenFile(binPath, os.O_CREATE|os.O_WRONLY, defaultFilePerm) @@ -267,8 +273,8 @@ func CreateNodeForUpload(upload *Upload, initAttrs node.Attributes) (*node.Node, } var f *lockedfile.File - switch n.ID { - case "": + switch upload.Info.Storage["NodeExists"] { + case "false": f, err = initNewNode(upload, n, uint64(fsize)) default: f, err = updateExistingNode(upload, n, spaceID, uint64(fsize)) @@ -320,8 +326,6 @@ func CreateNodeForUpload(upload *Upload, initAttrs node.Attributes) (*node.Node, } func initNewNode(upload *Upload, n *node.Node, fsize uint64) (*lockedfile.File, error) { - n.ID = uuid.New().String() - // create folder structure (if needed) if err := os.MkdirAll(filepath.Dir(n.InternalPath()), 0700); err != nil { return nil, err diff --git a/vendor/modules.txt b/vendor/modules.txt index ca132f4f5..3a63944c1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -349,7 +349,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.13.3 +# github.com/cs3org/reva/v2 v2.13.4-0.20230517171752-b39e78fd7b28 ## explicit; go 1.19 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime