bump reva to latest edge (#7727)

* bump reva to latest edge

To get https://github.com/cs3org/reva/pull/4336

* graph: Import unified role related code from reva

The UnifiedRole related types are pretty specific to the graph service.
Maintaining them as part of reva makes things more complex that required.

* chore: add failing cases to the expected failures

---------

Co-authored-by: Florian Schade <f.schade@icloud.com>
This commit is contained in:
Ralf Haferkamp
2023-11-17 09:18:45 +01:00
committed by GitHub
parent 6bfbbc3877
commit 50f63bf436
20 changed files with 173 additions and 69 deletions

View File

@@ -3,3 +3,4 @@ Enhancement: Bump reva
bumps reva version
https://github.com/owncloud/ocis/pull/7721
https://github.com/owncloud/ocis/pull/7727

2
go.mod
View File

@@ -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

4
go.sum
View File

@@ -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=

View File

@@ -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(),
}
}

View File

@@ -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()

View File

@@ -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

View File

@@ -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"),

View File

@@ -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) {

View File

@@ -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:

View File

@@ -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)

View File

@@ -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:

View File

@@ -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

View File

@@ -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 {

View File

@@ -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:

View File

@@ -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 isSpaceRoot(ri) {
return NewSpaceEditorRole()
}
}
if p == PermissionRead|PermissionShare {
return NewViewerRole(true)
}
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
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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

View File

@@ -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,

2
vendor/modules.txt vendored
View File

@@ -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