diff --git a/changelog/unreleased/bump-reva.md b/changelog/unreleased/bump-reva.md index 7840d319dac..298963d5e90 100644 --- a/changelog/unreleased/bump-reva.md +++ b/changelog/unreleased/bump-reva.md @@ -3,3 +3,4 @@ Enhancement: Bump reva bumps reva version https://github.com/owncloud/ocis/pull/7721 +https://github.com/owncloud/ocis/pull/7727 diff --git a/go.mod b/go.mod index 72afa1f60d2..a2b7a7eb7ab 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.7.0 github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 - github.com/cs3org/reva/v2 v2.16.1-0.20231113153113-e258a7c4dfb0 + github.com/cs3org/reva/v2 v2.16.1-0.20231115174649-4c665a7f03ac 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 9663d29f787..1a92f50b2bc 100644 --- a/go.sum +++ b/go.sum @@ -1013,8 +1013,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.16.1-0.20231113153113-e258a7c4dfb0 h1:k7WdgewYRI5sWqfnyV3GG+nPCxyAZfh1YEkqZep1Nf8= -github.com/cs3org/reva/v2 v2.16.1-0.20231113153113-e258a7c4dfb0/go.mod h1:utPCNSrWDdAwz2biLrKvzO6nDH9L7vRVGNzof13r8Kw= +github.com/cs3org/reva/v2 v2.16.1-0.20231115174649-4c665a7f03ac h1:0JZeSa52mBW4aC5wFO7+MPTka4ccH3H1HBD9HL5z/+4= +github.com/cs3org/reva/v2 v2.16.1-0.20231115174649-4c665a7f03ac/go.mod h1:utPCNSrWDdAwz2biLrKvzO6nDH9L7vRVGNzof13r8Kw= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/services/graph/pkg/service/v0/rolemanagement.go b/services/graph/pkg/service/v0/rolemanagement.go index 0a3f9034bc7..ee29d0f8765 100644 --- a/services/graph/pkg/service/v0/rolemanagement.go +++ b/services/graph/pkg/service/v0/rolemanagement.go @@ -5,11 +5,11 @@ import ( "net/http" "net/url" - "github.com/cs3org/reva/v2/pkg/conversions" "github.com/go-chi/chi/v5" "github.com/go-chi/render" libregraph "github.com/owncloud/libre-graph-api-go" "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode" + "github.com/owncloud/ocis/v2/services/graph/pkg/unifiedrole" ) // GetRoleDefinitions a list of permission roles than can be used when sharing with users or groups @@ -39,14 +39,14 @@ func (g Graph) GetRoleDefinition(w http.ResponseWriter, r *http.Request) { func getRoleDefinitionList(resharing bool) []*libregraph.UnifiedRoleDefinition { return []*libregraph.UnifiedRoleDefinition{ - conversions.NewViewerUnifiedRole(resharing), - conversions.NewSpaceViewerUnifiedRole(), - conversions.NewEditorUnifiedRole(resharing), - conversions.NewSpaceEditorUnifiedRole(), - conversions.NewFileEditorUnifiedRole(), - conversions.NewCoownerUnifiedRole(), - conversions.NewUploaderUnifiedRole(), - conversions.NewManagerUnifiedRole(), + unifiedrole.NewViewerUnifiedRole(resharing), + unifiedrole.NewSpaceViewerUnifiedRole(), + unifiedrole.NewEditorUnifiedRole(resharing), + unifiedrole.NewSpaceEditorUnifiedRole(), + unifiedrole.NewFileEditorUnifiedRole(resharing), + unifiedrole.NewCoownerUnifiedRole(), + unifiedrole.NewUploaderUnifiedRole(), + unifiedrole.NewManagerUnifiedRole(), } } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/conversions/unifiedrole.go b/services/graph/pkg/unifiedrole/unifiedrole.go similarity index 90% rename from vendor/github.com/cs3org/reva/v2/pkg/conversions/unifiedrole.go rename to services/graph/pkg/unifiedrole/unifiedrole.go index 100e2bf50ad..b6d007bd6be 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/conversions/unifiedrole.go +++ b/services/graph/pkg/unifiedrole/unifiedrole.go @@ -1,6 +1,7 @@ -package conversions +package unifiedrole import ( + "github.com/cs3org/reva/v2/pkg/conversions" libregraph "github.com/owncloud/libre-graph-api-go" "google.golang.org/protobuf/proto" ) @@ -33,7 +34,7 @@ const ( // NewViewerUnifiedRole creates a viewer role. `sharing` indicates if sharing permission should be added func NewViewerUnifiedRole(sharing bool) *libregraph.UnifiedRoleDefinition { - r := NewViewerRole(sharing) + r := conversions.NewViewerRole(sharing) return &libregraph.UnifiedRoleDefinition{ Id: proto.String(UnifiedRoleViewerID), Description: proto.String("Allows reading the shared file or folder"), @@ -50,7 +51,7 @@ func NewViewerUnifiedRole(sharing bool) *libregraph.UnifiedRoleDefinition { // NewSpaceViewerUnifiedRole creates a spaceviewer role func NewSpaceViewerUnifiedRole() *libregraph.UnifiedRoleDefinition { - r := NewSpaceViewerRole() + r := conversions.NewSpaceViewerRole() return &libregraph.UnifiedRoleDefinition{ Id: proto.String(UnifiedRoleSpaceViewerID), Description: proto.String("Allows reading the shared space"), @@ -67,7 +68,7 @@ func NewSpaceViewerUnifiedRole() *libregraph.UnifiedRoleDefinition { // NewEditorUnifiedRole creates an editor role. `sharing` indicates if sharing permission should be added func NewEditorUnifiedRole(sharing bool) *libregraph.UnifiedRoleDefinition { - r := NewEditorRole(sharing) + r := conversions.NewEditorRole(sharing) return &libregraph.UnifiedRoleDefinition{ Id: proto.String(UnifiedRoleEditorID), Description: proto.String("Allows creating, reading, updating and deleting the shared file or folder"), @@ -84,7 +85,7 @@ func NewEditorUnifiedRole(sharing bool) *libregraph.UnifiedRoleDefinition { // NewSpaceEditorUnifiedRole creates an editor role func NewSpaceEditorUnifiedRole() *libregraph.UnifiedRoleDefinition { - r := NewSpaceEditorRole() + r := conversions.NewSpaceEditorRole() return &libregraph.UnifiedRoleDefinition{ Id: proto.String(UnifiedRoleSpaceEditorID), Description: proto.String("Allows creating, reading, updating and deleting file or folder in the shared space"), @@ -100,8 +101,8 @@ func NewSpaceEditorUnifiedRole() *libregraph.UnifiedRoleDefinition { } // NewFileEditorUnifiedRole creates a file-editor role -func NewFileEditorUnifiedRole() *libregraph.UnifiedRoleDefinition { - r := NewFileEditorRole() +func NewFileEditorUnifiedRole(sharing bool) *libregraph.UnifiedRoleDefinition { + r := conversions.NewFileEditorRole(sharing) return &libregraph.UnifiedRoleDefinition{ Id: proto.String(UnifiedRoleFileEditorID), Description: proto.String("Allows reading and updating file"), @@ -118,7 +119,7 @@ func NewFileEditorUnifiedRole() *libregraph.UnifiedRoleDefinition { // NewCoownerUnifiedRole creates a coowner role. func NewCoownerUnifiedRole() *libregraph.UnifiedRoleDefinition { - r := NewCoownerRole() + r := conversions.NewCoownerRole() return &libregraph.UnifiedRoleDefinition{ Id: proto.String(UnifiedRoleCoownerID), Description: proto.String("Grants co-owner permissions on a resource"), @@ -135,7 +136,7 @@ func NewCoownerUnifiedRole() *libregraph.UnifiedRoleDefinition { // NewUploaderUnifiedRole creates an uploader role func NewUploaderUnifiedRole() *libregraph.UnifiedRoleDefinition { - r := NewUploaderRole() + r := conversions.NewUploaderRole() return &libregraph.UnifiedRoleDefinition{ Id: proto.String(UnifiedRoleUploaderID), Description: proto.String("Allows upload file or folder"), @@ -152,7 +153,7 @@ func NewUploaderUnifiedRole() *libregraph.UnifiedRoleDefinition { // NewManagerUnifiedRole creates a manager role func NewManagerUnifiedRole() *libregraph.UnifiedRoleDefinition { - r := NewManagerRole() + r := conversions.NewManagerRole() return &libregraph.UnifiedRoleDefinition{ Id: proto.String(UnifiedRoleManagerID), Description: proto.String("Grants manager permissions on a resource. Semantically equivalent to co-owner"), @@ -167,27 +168,27 @@ func NewManagerUnifiedRole() *libregraph.UnifiedRoleDefinition { } } -func displayName(role *Role) *string { +func displayName(role *conversions.Role) *string { if role == nil { return nil } var displayName string switch role.Name { - case RoleViewer: + case conversions.RoleViewer: displayName = "Viewer" - case RoleSpaceViewer: + case conversions.RoleSpaceViewer: displayName = "Space Viewer" - case RoleEditor: + case conversions.RoleEditor: displayName = "Editor" - case RoleSpaceEditor: + case conversions.RoleSpaceEditor: displayName = "Space Editor" - case RoleFileEditor: + case conversions.RoleFileEditor: displayName = "File Editor" - case RoleCoowner: + case conversions.RoleCoowner: displayName = "Co Owner" - case RoleUploader: + case conversions.RoleUploader: displayName = "Uploader" - case RoleManager: + case conversions.RoleManager: displayName = "Manager" default: return nil @@ -195,9 +196,9 @@ func displayName(role *Role) *string { return proto.String(displayName) } -func convert(role *Role) []string { +func convert(role *conversions.Role) []string { actions := make([]string, 0, 8) - if role == nil && role.cS3ResourcePermissions == nil { + if role == nil && role.CS3ResourcePermissions() == nil { return actions } p := role.CS3ResourcePermissions() diff --git a/tests/acceptance/expected-failures-API-on-OCIS-storage.md b/tests/acceptance/expected-failures-API-on-OCIS-storage.md index a44d61d6b39..a824da0232e 100644 --- a/tests/acceptance/expected-failures-API-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-API-on-OCIS-storage.md @@ -45,6 +45,11 @@ _ocdav: double-check the webdav property parsing when custom namespaces are used - [coreApiVersions/fileVersionAuthor.feature:297](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiVersions/fileVersionAuthor.feature#L297) - [coreApiVersions/fileVersionAuthor.feature:316](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiVersions/fileVersionAuthor.feature#L316) +#### [moving a file into a shared folder as the sharee and as the sharer](https://github.com/owncloud/ocis/issues/1287) + +- [coreApiVersions/fileVersions.feature:382](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiVersions/fileVersions.feature#382) Scenario: moving a file (with versions) into a shared folder as the sharee and as the sharer +- [coreApiVersions/fileVersions.feature:383](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiVersions/fileVersions.feature#383) Scenario: moving a file (with versions) into a shared folder as the sharee and as the sharer + ### Sync Synchronization features like etag propagation, setting mtime and locking files diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/publicshareprovider/publicshareprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/publicshareprovider/publicshareprovider.go index e8f18aea6c5..f142d76fa0a 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/publicshareprovider/publicshareprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/publicshareprovider/publicshareprovider.go @@ -25,6 +25,7 @@ import ( 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" + "github.com/cs3org/reva/v2/pkg/conversions" ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/publicshare" @@ -44,6 +45,7 @@ type config struct { Driver string `mapstructure:"driver"` Drivers map[string]map[string]interface{} `mapstructure:"drivers"` AllowedPathsForShares []string `mapstructure:"allowed_paths_for_shares"` + EnableExpiredSharesCleanup bool `mapstructure:"enable_expired_shares_cleanup"` WriteableShareMustHavePassword bool `mapstructure:"writeable_share_must_have_password"` } @@ -136,6 +138,12 @@ func (s *service) CreatePublicShare(ctx context.Context, req *link.CreatePublicS log := appctx.GetLogger(ctx) log.Info().Str("publicshareprovider", "create").Msg("create public share") + if !conversions.SufficientCS3Permissions(req.GetResourceInfo().GetPermissionSet(), req.GetGrant().GetPermissions().GetPermissions()) { + return &link.CreatePublicShareResponse{ + Status: status.NewInvalid(ctx, "insufficient permissions to create that kind of share"), + }, nil + } + if !s.isPathAllowed(req.ResourceInfo.Path) { return &link.CreatePublicShareResponse{ Status: status.NewInvalid(ctx, "share creation is not allowed for the specified path"), diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go index 2486031118d..86a76eb528a 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go @@ -25,7 +25,12 @@ import ( userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/mitchellh/mapstructure" + "github.com/pkg/errors" + "google.golang.org/grpc" + "github.com/cs3org/reva/v2/pkg/appctx" + "github.com/cs3org/reva/v2/pkg/conversions" ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/rgrpc" @@ -33,9 +38,6 @@ import ( "github.com/cs3org/reva/v2/pkg/share" "github.com/cs3org/reva/v2/pkg/share/manager/registry" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" - "google.golang.org/grpc" ) func init() { @@ -135,31 +137,45 @@ func (s *service) isPathAllowed(path string) bool { } func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShareRequest) (*collaboration.CreateShareResponse, error) { - u := ctxpkg.ContextMustGetUser(ctx) - if req.Grant.Grantee.Type == provider.GranteeType_GRANTEE_TYPE_USER && req.Grant.Grantee.GetUserId().Idp == "" { + user := ctxpkg.ContextMustGetUser(ctx) + + if req.GetGrant().GetGrantee().GetType() == provider.GranteeType_GRANTEE_TYPE_USER && req.GetGrant().GetGrantee().GetUserId().GetIdp() == "" { // use logged in user Idp as default. - g := &userpb.UserId{OpaqueId: req.Grant.Grantee.GetUserId().OpaqueId, Idp: u.Id.Idp, Type: userpb.UserType_USER_TYPE_PRIMARY} - req.Grant.Grantee.Id = &provider.Grantee_UserId{UserId: g} + req.GetGrant().GetGrantee().Id = &provider.Grantee_UserId{ + UserId: &userpb.UserId{ + OpaqueId: req.GetGrant().GetGrantee().GetUserId().GetOpaqueId(), + Idp: user.GetId().GetIdp(), + Type: userpb.UserType_USER_TYPE_PRIMARY}, + } } - if !s.isPathAllowed(req.ResourceInfo.Path) { + // check if the requested share creation has sufficient permissions to do so. + if shareCreationAllowed := conversions.SufficientCS3Permissions( + req.GetResourceInfo().GetPermissionSet(), + req.GetGrant().GetPermissions().GetPermissions(), + ); !shareCreationAllowed { + return &collaboration.CreateShareResponse{ + Status: status.NewInvalid(ctx, "insufficient permissions to create that kind of share"), + }, nil + } + + if !s.isPathAllowed(req.GetResourceInfo().GetPath()) { return &collaboration.CreateShareResponse{ Status: status.NewInvalid(ctx, "share creation is not allowed for the specified path"), }, nil } - share, err := s.sm.Share(ctx, req.ResourceInfo, req.Grant) + createdShare, err := s.sm.Share(ctx, req.GetResourceInfo(), req.GetGrant()) if err != nil { return &collaboration.CreateShareResponse{ Status: status.NewStatusFromErrType(ctx, "error creating share", err), }, nil } - res := &collaboration.CreateShareResponse{ + return &collaboration.CreateShareResponse{ Status: status.NewOK(ctx), - Share: share, - } - return res, nil + Share: createdShare, + }, nil } func (s *service) RemoveShare(ctx context.Context, req *collaboration.RemoveShareRequest) (*collaboration.RemoveShareResponse, error) { diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/locks.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/locks.go index b56b6c4d86b..332b9d22760 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/locks.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/locks.go @@ -614,6 +614,24 @@ func (s *svc) handleUnlock(w http.ResponseWriter, r *http.Request, ns string) (s return http.StatusInternalServerError, errtypes.NewErrtypeFromStatus(cs3Status) } + return s.unlockReference(ctx, w, r, ref) +} + +func (s *svc) handleSpaceUnlock(w http.ResponseWriter, r *http.Request, spaceID string) (status int, err error) { + ctx, span := appctx.GetTracerProvider(r.Context()).Tracer(tracerName).Start(r.Context(), fmt.Sprintf("%s %v", r.Method, r.URL.Path)) + defer span.End() + + span.SetAttributes(attribute.String("component", "ocdav")) + + ref, err := spacelookup.MakeStorageSpaceReference(spaceID, r.URL.Path) + if err != nil { + return http.StatusBadRequest, fmt.Errorf("invalid space id") + } + + return s.unlockReference(ctx, w, r, &ref) +} + +func (s *svc) unlockReference(ctx context.Context, _ http.ResponseWriter, r *http.Request, ref *provider.Reference) (retStatus int, retErr error) { // http://www.webdav.org/specs/rfc4918.html#HEADER_Lock-Token says that the // Lock-Token value should be a Coded-URL OR a token. We strip its angle brackets. t := r.Header.Get(net.HeaderLockToken) @@ -621,7 +639,7 @@ func (s *svc) handleUnlock(w http.ResponseWriter, r *http.Request, ns string) (s t = t[1 : len(t)-1] } - switch err = s.LockSystem.Unlock(r.Context(), time.Now(), ref, t); err { + switch err := s.LockSystem.Unlock(ctx, time.Now(), ref, t); err { case nil: return http.StatusNoContent, err case errors.ErrForbidden: diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/meta.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/meta.go index 09e54bfa257..9cd939057e4 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/meta.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/meta.go @@ -158,7 +158,7 @@ func (h *MetaHandler) handlePathForUser(w http.ResponseWriter, r *http.Request, prop.Escaped("oc:meta-path-for-user", pathRes.Path), prop.Escaped("oc:id", id), prop.Escaped("oc:fileid", id), - prop.Escaped("oc:spaceid", rid.GetStorageId()), + prop.Escaped("oc:spaceid", storagespace.FormatStorageID(rid.GetStorageId(), rid.GetSpaceId())), }, } baseURI := ctx.Value(net.CtxKeyBaseURI).(string) diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spaces.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spaces.go index a5404b102cd..e8706becffa 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spaces.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spaces.go @@ -86,7 +86,7 @@ func (h *SpacesHandler) Handler(s *svc, trashbinHandler *TrashbinHandler) http.H case MethodLock: status, err = s.handleSpacesLock(w, r, spaceID) case MethodUnlock: - status, err = s.handleUnlock(w, r, spaceID) + status, err = s.handleSpaceUnlock(w, r, spaceID) case MethodMkcol: status, err = s.handleSpacesMkCol(w, r, spaceID) case MethodMove: diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go index 051783b5414..092d6c3b4a0 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go @@ -160,7 +160,7 @@ func (h *Handler) createPublicLinkShare(w http.ResponseWriter, r *http.Request, p := role.OCSPermissions() p &^= conversions.PermissionCreate p &^= conversions.PermissionDelete - permissions = conversions.RoleFromOCSPermissions(p).CS3ResourcePermissions() + permissions = conversions.RoleFromOCSPermissions(p, statInfo).CS3ResourcePermissions() } if !sufficientPermissions(statInfo.PermissionSet, permissions, true) { @@ -636,7 +636,7 @@ func ocPublicPermToCs3(pk *int) (*provider.ResourcePermissions, error) { return nil, err } - return conversions.RoleFromOCSPermissions(perm).CS3ResourcePermissions(), nil + return conversions.RoleFromOCSPermissions(perm, nil).CS3ResourcePermissions(), nil } // pointer will be nil if no permission is set diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index 1ec428fce02..2621a331326 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -465,7 +465,7 @@ func (h *Handler) extractPermissions(reqRole string, reqPermissions string, ri * Error: err, } } - role = conversions.RoleFromOCSPermissions(perm) + role = conversions.RoleFromOCSPermissions(perm, ri) } } @@ -481,7 +481,7 @@ func (h *Handler) extractPermissions(reqRole string, reqPermissions string, ri * Error: errors.New("cannot set the requested share permissions"), } } - role = conversions.RoleFromOCSPermissions(permissions) + role = conversions.RoleFromOCSPermissions(permissions, ri) } if !sufficientPermissions(ri.PermissionSet, role.CS3ResourcePermissions(), false) && role.Name != conversions.RoleDenied { diff --git a/vendor/github.com/cs3org/reva/v2/pkg/cbox/utils/conversions.go b/vendor/github.com/cs3org/reva/v2/pkg/cbox/utils/conversions.go index 250b26f9990..a2cc7d18188 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/cbox/utils/conversions.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/cbox/utils/conversions.go @@ -150,7 +150,7 @@ func IntTosharePerm(p int, itemType string) *provider.ResourcePermissions { if itemType == "folder" { return conversions.NewEditorRole(false).CS3ResourcePermissions() } - return conversions.NewFileEditorRole().CS3ResourcePermissions() + return conversions.NewFileEditorRole(false).CS3ResourcePermissions() case 4: return conversions.NewUploaderRole().CS3ResourcePermissions() default: diff --git a/vendor/github.com/cs3org/reva/v2/pkg/conversions/role.go b/vendor/github.com/cs3org/reva/v2/pkg/conversions/role.go index 6971957c8fa..4b323a9aeda 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/conversions/role.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/conversions/role.go @@ -21,6 +21,7 @@ package conversions import ( "fmt" + "reflect" "strings" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -153,7 +154,7 @@ func RoleFromName(name string, sharing bool) *Role { case RoleSpaceEditor: return NewSpaceEditorRole() case RoleFileEditor: - return NewFileEditorRole() + return NewFileEditorRole(sharing) case RoleUploader: return NewUploaderRole() case RoleManager: @@ -270,10 +271,15 @@ func NewSpaceEditorRole() *Role { } // NewFileEditorRole creates a file-editor role -func NewFileEditorRole() *Role { +func NewFileEditorRole(sharing bool) *Role { + p := PermissionRead | PermissionWrite + if sharing { + p |= PermissionShare + } return &Role{ Name: RoleEditor, cS3ResourcePermissions: &provider.ResourcePermissions{ + AddGrant: sharing, GetPath: true, GetQuota: true, InitiateFileDownload: true, @@ -284,7 +290,7 @@ func NewFileEditorRole() *Role { InitiateFileUpload: true, RestoreRecycleItem: true, }, - ocsPermissions: PermissionRead | PermissionWrite, + ocsPermissions: p, } } @@ -372,8 +378,7 @@ func NewManagerRole() *Role { // RoleFromOCSPermissions tries to map ocs permissions to a role // TODO: rethink using this. ocs permissions cannot be assigned 1:1 to roles -// NOTE: If resharing=false in the system this function will return SpaceViewerRole instead ViewerRole -func RoleFromOCSPermissions(p Permissions) *Role { +func RoleFromOCSPermissions(p Permissions, ri *provider.ResourceInfo) *Role { if p == PermissionInvalid { return NewNoneRole() } @@ -384,14 +389,18 @@ func RoleFromOCSPermissions(p Permissions) *Role { return NewEditorRole(true) } - return NewSpaceEditorRole() - } - if p == PermissionRead|PermissionShare { - return NewViewerRole(true) + if isSpaceRoot(ri) { + return NewSpaceEditorRole() + } } - if p == PermissionRead { + + if p == PermissionRead && isSpaceRoot(ri) { return NewSpaceViewerRole() } + + if p == PermissionRead|PermissionShare && !isSpaceRoot(ri) { + return NewViewerRole(true) + } } if p == PermissionCreate { return NewUploaderRole() @@ -400,6 +409,22 @@ func RoleFromOCSPermissions(p Permissions) *Role { return NewLegacyRoleFromOCSPermissions(p) } +func isSpaceRoot(ri *provider.ResourceInfo) bool { + if ri == nil { + return false + } + if ri.Type != provider.ResourceType_RESOURCE_TYPE_CONTAINER { + return false + } + + if ri.GetId().GetOpaqueId() != ri.GetSpace().GetRoot().GetOpaqueId() || + ri.GetId().GetSpaceId() != ri.GetSpace().GetRoot().GetSpaceId() || + ri.GetId().GetStorageId() != ri.GetSpace().GetRoot().GetStorageId() { + return false + } + return true +} + // NewLegacyRoleFromOCSPermissions tries to map a legacy combination of ocs permissions to cs3 resource permissions as a legacy role func NewLegacyRoleFromOCSPermissions(p Permissions) *Role { r := &Role{ @@ -508,3 +533,33 @@ func RoleFromResourcePermissions(rp *provider.ResourcePermissions, islink bool) // TODO what about even more granular cs3 permissions?, eg. only stat return r } + +// SufficientCS3Permissions returns true if the `existing` permissions contain the `requested` permissions +func SufficientCS3Permissions(existing, requested *provider.ResourcePermissions) bool { + if existing == nil || requested == nil { + return false + } + // empty permissions represent a denial + if grants.PermissionsEqual(requested, &provider.ResourcePermissions{}) { + return existing.DenyGrant + } + requestedPermissionsType := reflect.TypeOf(provider.ResourcePermissions{}) + numFields := requestedPermissionsType.NumField() + requestedPermissionsValues := reflect.ValueOf(requested) + existingPermissionsValues := reflect.ValueOf(existing) + + for i := 0; i < numFields; i++ { + permissionName := requestedPermissionsType.Field(i).Name + // filter out irrelevant fields + if strings.Contains(permissionName, "XXX") { + continue + } + existingPermission := reflect.Indirect(existingPermissionsValues).FieldByName(permissionName).Bool() + requestedPermission := requestedPermissionsValues.Elem().Field(i).Bool() + // every requested permission needs to exist for the creator + if requestedPermission && !existingPermission { + return false + } + } + return true +} diff --git a/vendor/github.com/cs3org/reva/v2/pkg/publicshare/manager/owncloudsql/conversions.go b/vendor/github.com/cs3org/reva/v2/pkg/publicshare/manager/owncloudsql/conversions.go index 4bbf8c8e749..edca2554e56 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/publicshare/manager/owncloudsql/conversions.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/publicshare/manager/owncloudsql/conversions.go @@ -162,7 +162,7 @@ func intTosharePerm(p int) (*provider.ResourcePermissions, error) { return nil, err } - return conversions.RoleFromOCSPermissions(perms).CS3ResourcePermissions(), nil + return conversions.RoleFromOCSPermissions(perms, nil).CS3ResourcePermissions(), nil } func formatUserID(u *userpb.UserId) string { diff --git a/vendor/github.com/cs3org/reva/v2/pkg/share/manager/owncloudsql/conversions.go b/vendor/github.com/cs3org/reva/v2/pkg/share/manager/owncloudsql/conversions.go index 8801cb40621..f3aa081d768 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/share/manager/owncloudsql/conversions.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/share/manager/owncloudsql/conversions.go @@ -214,7 +214,7 @@ func intTosharePerm(p int) (*provider.ResourcePermissions, error) { return nil, err } - return conversions.RoleFromOCSPermissions(perms).CS3ResourcePermissions(), nil + return conversions.RoleFromOCSPermissions(perms, nil).CS3ResourcePermissions(), nil } func intToShareState(g int) collaboration.ShareState { diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/filecache/filecache.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/filecache/filecache.go index a9fac0630d3..82497c932d0 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/filecache/filecache.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/filecache/filecache.go @@ -362,7 +362,7 @@ func (c *Cache) Permissions(ctx context.Context, storage interface{}, p string) return nil, err } - return conversions.RoleFromOCSPermissions(perms).CS3ResourcePermissions(), nil + return conversions.RoleFromOCSPermissions(perms, nil).CS3ResourcePermissions(), nil } // InsertOrUpdate creates or updates a cache entry diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/owncloudsql.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/owncloudsql.go index 2e09d1e480f..67ba8123938 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/owncloudsql.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/owncloudsql.go @@ -650,7 +650,7 @@ func (fs *owncloudsqlfs) readPermissions(ctx context.Context, ip string) (p *pro if err != nil { return nil, err } - return conversions.RoleFromOCSPermissions(perms).CS3ResourcePermissions(), nil + return conversions.RoleFromOCSPermissions(perms, nil).CS3ResourcePermissions(), nil } // The os not exists error is buried inside the xattr error, diff --git a/vendor/modules.txt b/vendor/modules.txt index b7246cc7305..139e221f408 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -357,7 +357,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.16.1-0.20231113153113-e258a7c4dfb0 +# github.com/cs3org/reva/v2 v2.16.1-0.20231115174649-4c665a7f03ac ## explicit; go 1.20 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime