Merge pull request #9188 from rhafer/issue/9128

[full-ci] Bump reva for: https://github.com/cs3org/reva/pull/4685
This commit is contained in:
Jörn Friedrich Dreyer
2024-05-21 17:45:08 +02:00
committed by GitHub
15 changed files with 213 additions and 46 deletions

View File

@@ -2,6 +2,7 @@ Enhancement: Bump Reva
bumps reva version
https://github.com/owncloud/ocis/pull/9188
https://github.com/owncloud/ocis/pull/9132
https://github.com/owncloud/ocis/pull/9041
https://github.com/owncloud/ocis/pull/9002

2
go.mod
View File

@@ -15,7 +15,7 @@ require (
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/coreos/go-oidc/v3 v3.10.0
github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781
github.com/cs3org/reva/v2 v2.19.2-0.20240510133919-1732d68a5591
github.com/cs3org/reva/v2 v2.19.2-0.20240521134642-8fb71adbe500
github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
github.com/egirna/icap-client v0.1.1

4
go.sum
View File

@@ -1025,8 +1025,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.20240510133919-1732d68a5591 h1:6rfzawhTzz96p8ifzcjNiMknAfAdVpfqdyzmpp3+6w8=
github.com/cs3org/reva/v2 v2.19.2-0.20240510133919-1732d68a5591/go.mod h1:BOlJApKFrWRiaOoBCRxCTG5bghTTMlYaEZrRxOzKaS8=
github.com/cs3org/reva/v2 v2.19.2-0.20240521134642-8fb71adbe500 h1:BsbDsBAnEJlCN8PU6XhDgQNX9/aSrVcyDocrBR6GI5g=
github.com/cs3org/reva/v2 v2.19.2-0.20240521134642-8fb71adbe500/go.mod h1:BOlJApKFrWRiaOoBCRxCTG5bghTTMlYaEZrRxOzKaS8=
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=

View File

@@ -23,8 +23,8 @@ const (
UnifiedRoleSpaceEditorID = "58c63c02-1d89-4572-916a-870abc5a1b7d"
// UnifiedRoleFileEditorID Unified role file editor id.
UnifiedRoleFileEditorID = "2d00ce52-1fc2-4dbc-8b95-a73b73395f5a"
// UnifiedRoleUploaderID Unified role uploader id.
UnifiedRoleUploaderID = "1c996275-f1c9-4e71-abdf-a42f6495e960"
// UnifiedRoleEditorLiteID Unified role editor-lite id.
UnifiedRoleEditorLiteID = "1c996275-f1c9-4e71-abdf-a42f6495e960"
// UnifiedRoleManagerID Unified role manager id.
UnifiedRoleManagerID = "312c0871-5ef7-4b3a-85b6-0e4074c64049"
// UnifiedRoleSecureViewerID Unified role secure viewer id.
@@ -66,7 +66,7 @@ var legacyNames map[string]string = map[string]string{
UnifiedRoleSpaceEditorID: "editor",
UnifiedRoleEditorID: conversions.RoleEditor,
UnifiedRoleFileEditorID: conversions.RoleFileEditor,
UnifiedRoleUploaderID: conversions.RoleUploader,
UnifiedRoleEditorLiteID: conversions.RoleEditorLite,
UnifiedRoleManagerID: conversions.RoleManager,
UnifiedRoleSecureViewerID: conversions.RoleSecureViewer,
}
@@ -160,11 +160,11 @@ func NewFileEditorUnifiedRole() *libregraph.UnifiedRoleDefinition {
}
}
// NewUploaderUnifiedRole creates an uploader role
func NewUploaderUnifiedRole() *libregraph.UnifiedRoleDefinition {
r := conversions.NewUploaderRole()
// NewEditorLiteUnifiedRole creates an editor-lite role
func NewEditorLiteUnifiedRole() *libregraph.UnifiedRoleDefinition {
r := conversions.NewEditorLiteRole()
return &libregraph.UnifiedRoleDefinition{
Id: proto.String(UnifiedRoleUploaderID),
Id: proto.String(UnifiedRoleEditorLiteID),
Description: proto.String("View, download and upload."),
DisplayName: displayName(r),
RolePermissions: []libregraph.UnifiedRolePermission{
@@ -239,7 +239,7 @@ func GetBuiltinRoleDefinitionList() []*libregraph.UnifiedRoleDefinition {
NewEditorUnifiedRole(),
NewSpaceEditorUnifiedRole(),
NewFileEditorUnifiedRole(),
NewUploaderUnifiedRole(),
NewEditorLiteUnifiedRole(),
NewManagerUnifiedRole(),
NewSecureViewerUnifiedRole(),
}
@@ -501,7 +501,7 @@ func displayName(role *conversions.Role) *string {
displayName = canEdit
case conversions.RoleFileEditor:
displayName = canEdit
case conversions.RoleUploader:
case conversions.RoleEditorLite:
displayName = "Can upload"
case conversions.RoleManager:
displayName = "Can manage"

View File

@@ -171,8 +171,8 @@ var _ = Describe("unifiedroles", func() {
unifiedrole.UnifiedRoleConditionFolder,
[]*libregraph.UnifiedRoleDefinition{
unifiedrole.NewSecureViewerUnifiedRole(),
unifiedrole.NewUploaderUnifiedRole(),
unifiedrole.NewViewerUnifiedRole(),
unifiedrole.NewEditorLiteUnifiedRole(),
unifiedrole.NewEditorUnifiedRole(),
},
),
@@ -194,8 +194,8 @@ var _ = Describe("unifiedroles", func() {
unifiedrole.UnifiedRoleConditionFolder,
[]*libregraph.UnifiedRoleDefinition{
unifiedrole.NewSecureViewerUnifiedRole(),
unifiedrole.NewUploaderUnifiedRole(),
unifiedrole.NewViewerUnifiedRole(),
unifiedrole.NewEditorLiteUnifiedRole(),
unifiedrole.NewEditorUnifiedRole(),
},
),
@@ -221,10 +221,11 @@ var _ = Describe("unifiedroles", func() {
Entry(
"mixed",
append(rolesToAction(unifiedrole.NewUploaderUnifiedRole()), unifiedrole.DriveItemQuotaRead),
append(rolesToAction(unifiedrole.NewEditorLiteUnifiedRole()), unifiedrole.DriveItemQuotaRead),
unifiedrole.UnifiedRoleConditionFolder,
[]*libregraph.UnifiedRoleDefinition{
unifiedrole.NewUploaderUnifiedRole(),
unifiedrole.NewSecureViewerUnifiedRole(),
unifiedrole.NewEditorLiteUnifiedRole(),
},
),
)

View File

@@ -106,19 +106,19 @@ Feature: List a sharing permissions
"description": {
"type": "string",
"enum": [
"View, download and upload."
"View and download."
]
},
"displayName": {
"type": "string",
"enum": [
"Can upload"
"Can view"
]
},
"id": {
"type": "string",
"enum": [
"1c996275-f1c9-4e71-abdf-a42f6495e960"
"b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5"
]
}
}
@@ -141,19 +141,19 @@ Feature: List a sharing permissions
"description": {
"type": "string",
"enum": [
"View and download."
"View, download and upload."
]
},
"displayName": {
"type": "string",
"enum": [
"Can view"
"Can upload"
]
},
"id": {
"type": "string",
"enum": [
"b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5"
"1c996275-f1c9-4e71-abdf-a42f6495e960"
]
}
}
@@ -855,13 +855,13 @@ Feature: List a sharing permissions
"const": 2
},
"description": {
"const": "View, download and upload."
"const": "View and download."
},
"displayName": {
"const": "Can upload"
"const": "Can view"
},
"id": {
"const": "1c996275-f1c9-4e71-abdf-a42f6495e960"
"const": "b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5"
}
}
},
@@ -878,13 +878,13 @@ Feature: List a sharing permissions
"const": 3
},
"description": {
"const": "View and download."
"const": "View, download and upload."
},
"displayName": {
"const": "Can view"
"const": "Can upload"
},
"id": {
"const": "b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5"
"const": "1c996275-f1c9-4e71-abdf-a42f6495e960"
}
}
},

View File

@@ -27,16 +27,21 @@ import (
providerpb "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1"
registry "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1"
providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/v2/pkg/appctx"
"github.com/cs3org/reva/v2/pkg/auth/scope"
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/errtypes"
"github.com/cs3org/reva/v2/pkg/rgrpc/status"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/token"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/pkg/errors"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
@@ -169,11 +174,9 @@ func (s *svc) openLocalResources(ctx context.Context, ri *storageprovider.Resour
return nil, errors.Wrap(err, "gateway: error calling GetAppProviderClient")
}
appProviderReq := &providerpb.OpenInAppRequest{
ResourceInfo: ri,
ViewMode: providerpb.ViewMode(vm),
AccessToken: accessToken,
Opaque: opaque,
appProviderReq, err := buildOpenInAppRequest(ctx, ri, vm, s.tokenmgr, accessToken, opaque)
if err != nil {
return nil, errors.Wrap(err, "gateway: error building OpenInApp request")
}
res, err := appProviderClient.OpenInApp(ctx, appProviderReq)
@@ -184,6 +187,41 @@ func (s *svc) openLocalResources(ctx context.Context, ri *storageprovider.Resour
return res, nil
}
func buildOpenInAppRequest(ctx context.Context, ri *storageprovider.ResourceInfo, vm gateway.OpenInAppRequest_ViewMode, tokenmgr token.Manager, accessToken string, opaque *typespb.Opaque) (*providerpb.OpenInAppRequest, error) {
// in case of a view only mode and a stat permission we need to create a view only token
if vm == gateway.OpenInAppRequest_VIEW_MODE_VIEW_ONLY && ri.GetPermissionSet().GetStat() {
// Limit scope to the resource
scope, err := scope.AddResourceInfoScope(ri, providerv1beta1.Role_ROLE_VIEWER, nil)
if err != nil {
return nil, err
}
// build a fake user object for the token
currentuser := ctxpkg.ContextMustGetUser(ctx)
scopedUser := &userpb.User{
Id: ri.GetOwner(), // the owner of the resource is always set, right?
DisplayName: "View Only user for " + currentuser.GetUsername(),
}
// mint a view only token
viewOnlyToken, err := tokenmgr.MintToken(ctx, scopedUser, scope)
if err != nil {
return nil, err
}
// TODO we should not append the token to the opaque, we should have a dedicated field in the request
opaque = utils.AppendPlainToOpaque(opaque, "viewOnlyToken", viewOnlyToken)
}
return &providerpb.OpenInAppRequest{
ResourceInfo: ri,
ViewMode: providerpb.ViewMode(vm),
AccessToken: accessToken,
// ViewOnlyToken: viewOnlyToken // scoped to the shared resource if the stat response hase a ViewOnly permission
Opaque: opaque,
}, nil
}
func (s *svc) findAppProvider(ctx context.Context, ri *storageprovider.ResourceInfo, app string) (*registry.ProviderInfo, error) {
c, err := pool.GetAppRegistryClient(s.c.AppRegistryEndpoint)
if err != nil {

View File

@@ -20,6 +20,7 @@ package ocdav
import (
"context"
"fmt"
"net/http"
"path"
"path/filepath"
@@ -28,6 +29,7 @@ import (
gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userv1beta1 "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"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/config"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/errors"
@@ -36,12 +38,18 @@ import (
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/v2/pkg/rhttp/router"
"github.com/cs3org/reva/v2/pkg/storage/utils/grants"
"github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/cs3org/reva/v2/pkg/utils"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc/metadata"
)
const (
_trashbinPath = "trash-bin"
// WwwAuthenticate captures the Www-Authenticate header string.
WwwAuthenticate = "Www-Authenticate"
)
// DavHandler routes to the different sub handlers
@@ -248,6 +256,39 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
var hasValidBasicAuthHeader bool
var pass string
var err error
// If user is authenticated
_, userExists := ctxpkg.ContextGetUser(ctx)
if userExists {
client, err := s.gatewaySelector.Next()
if err != nil {
log.Error().Err(err).Msg("error sending grpc stat request")
w.WriteHeader(http.StatusInternalServerError)
return
}
psRes, err := client.GetPublicShare(ctx, &link.GetPublicShareRequest{
Ref: &link.PublicShareReference{
Spec: &link.PublicShareReference_Token{
Token: token,
},
}})
if err != nil && !strings.Contains(err.Error(), "core access token not found") {
log.Error().Err(err).Msg("error sending grpc stat request")
w.WriteHeader(http.StatusInternalServerError)
return
}
// If the link is internal then 307 redirect
if psRes.Status.Code == rpc.Code_CODE_OK && grants.PermissionsEqual(psRes.Share.Permissions.GetPermissions(), &provider.ResourcePermissions{}) {
if psRes.GetShare().GetResourceId() != nil {
rUrl := path.Join("/dav/spaces", storagespace.FormatResourceID(*psRes.GetShare().GetResourceId()))
http.Redirect(w, r, rUrl, http.StatusTemporaryRedirect)
return
}
log.Debug().Str("token", token).Interface("status", res.Status).Msg("resource id not found")
w.WriteHeader(http.StatusNotFound)
return
}
}
if _, pass, hasValidBasicAuthHeader = r.BasicAuth(); hasValidBasicAuthHeader {
res, err = handleBasicAuth(r.Context(), s.gatewaySelector, token, pass)
} else {
@@ -286,6 +327,17 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
return
}
if userExists {
// Build new context without an authenticated user.
// the public link should be resolved by the 'publicshares' authenticated user
baseURI := ctx.Value(net.CtxKeyBaseURI).(string)
logger := appctx.GetLogger(ctx)
span := trace.SpanFromContext(ctx)
span.End()
ctx = trace.ContextWithSpan(context.Background(), span)
ctx = appctx.WithLogger(ctx, logger)
ctx = context.WithValue(ctx, net.CtxKeyBaseURI, baseURI)
}
ctx = ctxpkg.ContextSetToken(ctx, res.Token)
ctx = ctxpkg.ContextSetUser(ctx, res.User)
ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, res.Token)
@@ -301,6 +353,16 @@ func (h *DavHandler) Handler(s *svc) http.Handler {
return
case sRes.Status.Code == rpc.Code_CODE_PERMISSION_DENIED:
fallthrough
case sRes.Status.Code == rpc.Code_CODE_OK && grants.PermissionsEqual(sRes.GetInfo().GetPermissionSet(), &provider.ResourcePermissions{}):
// If the link is internal
if !userExists {
w.Header().Add(WwwAuthenticate, fmt.Sprintf("Bearer realm=\"%s\", charset=\"UTF-8\"", r.Host))
w.WriteHeader(http.StatusUnauthorized)
b, err := errors.Marshal(http.StatusUnauthorized, "No 'Authorization: Bearer' header found", "")
errors.HandleWebdavError(log, w, b, err)
return
}
fallthrough
case sRes.Status.Code == rpc.Code_CODE_NOT_FOUND:
log.Debug().Str("token", token).Interface("status", res.Status).Msg("resource not found")
w.WriteHeader(http.StatusNotFound) // log the difference

View File

@@ -89,6 +89,21 @@ var (
"latitude",
"longitude",
}
imageKeys = []string{
"width",
"height",
}
photoKeys = []string{
"cameraMake",
"cameraModel",
"exposureDenominator",
"exposureNumerator",
"fNumber",
"focalLength",
"iso",
"orientation",
"takenDateTime",
}
)
type countingReader struct {
@@ -853,6 +868,10 @@ func metadataKeys(pf XML) ([]string, []string) {
metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.audio", audioKeys)...)
case "http://owncloud.org/ns/location":
metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.location", locationKeys)...)
case "http://owncloud.org/ns/image":
metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.image", imageKeys)...)
case "http://owncloud.org/ns/photo":
metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.photo", photoKeys)...)
default:
metadataKeys = append(metadataKeys, key)
}
@@ -910,7 +929,7 @@ func requiresExplicitFetching(n *xml.Name) bool {
}
case net.NsOwncloud:
switch n.Local {
case "favorite", "share-types", "checksums", "size", "tags", "audio", "location":
case "favorite", "share-types", "checksums", "size", "tags", "audio", "location", "image", "photo":
return true
default:
return false
@@ -1253,6 +1272,8 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:tags", k["tags"]))
appendMetadataProp(k, "oc", "audio", "libre.graph.audio", audioKeys)
appendMetadataProp(k, "oc", "location", "libre.graph.location", locationKeys)
appendMetadataProp(k, "oc", "image", "libre.graph.image", imageKeys)
appendMetadataProp(k, "oc", "photo", "libre.graph.photo", photoKeys)
}
// ls do not report any properties as missing by default
@@ -1534,6 +1555,14 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
if k := md.GetArbitraryMetadata().GetMetadata(); k != nil {
appendMetadataProp(k, "oc", "location", "libre.graph.location", locationKeys)
}
case "image":
if k := md.GetArbitraryMetadata().GetMetadata(); k != nil {
appendMetadataProp(k, "oc", "image", "libre.graph.image", imageKeys)
}
case "photo":
if k := md.GetArbitraryMetadata().GetMetadata(); k != nil {
appendMetadataProp(k, "oc", "photo", "libre.graph.photo", photoKeys)
}
case "name":
appendToOK(prop.Escaped("oc:name", md.Name))
case "shareid":

View File

@@ -48,7 +48,9 @@ const (
RoleFileEditor = "file-editor"
// RoleCoowner grants co-owner permissions on a resource.
RoleCoowner = "coowner"
// RoleUploader grants uploader permission to upload onto a resource.
// RoleEditorLite grants permission to upload and download to a resource.
RoleEditorLite = "editor-lite"
// RoleUploader grants uploader permission to upload onto a resource (no download).
RoleUploader = "uploader"
// RoleManager grants manager permissions on a resource. Semantically equivalent to co-owner.
RoleManager = "manager"
@@ -313,7 +315,24 @@ func NewCoownerRole() *Role {
}
}
// NewUploaderRole creates an uploader role
// NewEditorLiteRole creates an editor-lite role
func NewEditorLiteRole() *Role {
return &Role{
Name: RoleEditorLite,
cS3ResourcePermissions: &provider.ResourcePermissions{
Stat: true,
GetPath: true,
CreateContainer: true,
InitiateFileUpload: true,
InitiateFileDownload: true,
ListContainer: true,
Move: true,
},
ocsPermissions: PermissionCreate,
}
}
// NewUploaderRole creates an uploader role with no download permissions
func NewUploaderRole() *Role {
return &Role{
Name: RoleUploader,
@@ -524,6 +543,10 @@ func RoleFromResourcePermissions(rp *provider.ResourcePermissions, islink bool)
}
}
if r.ocsPermissions == PermissionCreate {
if rp.GetPath && rp.InitiateFileDownload && rp.ListContainer && rp.Move {
r.Name = RoleEditorLite
return r
}
r.Name = RoleUploader
return r
}

View File

@@ -794,6 +794,7 @@ var mimeTypes = map[string]string{
"s3m": "audio/s3m",
"saf": "application/vnd.yamaha.smaf-audio",
"sass": "text/x-sass",
"sb3": "application/x.scratch.sb3",
"sbml": "application/sbml+xml",
"sc": "application/vnd.ibm.secure-container",
"scd": "application/x-msschedule",

View File

@@ -53,7 +53,7 @@ const serverStateMetadata = "METADATA"
var serverState = serverStateEmpty
var responses = map[string]Response{
`POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/AddGrant {"ref":{"path":"/subdir"},"g":{"grantee":{"type":1,"Id":{"UserId":{"opaque_id":"4c510ada-c86b-4815-8820-42cdf82c3d51"}}},"permissions":{"move":true,"stat":true}}} EMPTY`: {200, ``, serverStateGrantAdded},
`POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/AddGrant {"ref":{"path":"/subdir"},"g":{"grantee":{"type":1,"Id":{"UserId":{"opaque_id":"4c510ada-c86b-4815-8820-42cdf82c3d51"}}},"permissions":{"initiate_file_download":true,"move":true,"stat":true}}} EMPTY`: {200, ``, serverStateGrantAdded},
`POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/CreateDir {"path":"/subdir"} EMPTY`: {200, ``, serverStateSubdir},
`POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/CreateDir {"path":"/subdir"} HOME`: {200, ``, serverStateSubdir},
@@ -149,7 +149,7 @@ var responses = map[string]Response{
`POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/UnsetArbitraryMetadata {"ref":{"path":"/subdir"},"keys":["foo"]}`: {200, ``, serverStateSubdir},
`POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/UpdateGrant {"ref":{"path":"/subdir"},"g":{"grantee":{"type":1,"Id":{"UserId":{"opaque_id":"4c510ada-c86b-4815-8820-42cdf82c3d51"}}},"permissions":{"delete":true,"move":true,"stat":true}}}`: {200, ``, serverStateGrantUpdated},
`POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/UpdateGrant {"ref":{"path":"/subdir"},"g":{"grantee":{"type":1,"Id":{"UserId":{"opaque_id":"4c510ada-c86b-4815-8820-42cdf82c3d51"}}},"permissions":{"delete":true,"initiate_file_download":true,"move":true,"stat":true}}}`: {200, ``, serverStateGrantUpdated},
`POST /apps/sciencemesh/~tester/api/storage/GetHome `: {200, `yes we are`, serverStateHome},
`POST /apps/sciencemesh/~tester/api/storage/CreateHome `: {201, ``, serverStateEmpty},

View File

@@ -316,10 +316,15 @@ func (e *ACE) granteeType() provider.GranteeType {
// grantPermissionSet returns the set of CS3 resource permissions representing the ACE
func (e *ACE) grantPermissionSet() *provider.ResourcePermissions {
p := &provider.ResourcePermissions{}
// r
if strings.Contains(e.permissions, "r") {
// t
if strings.Contains(e.permissions, "t") {
p.Stat = true
p.GetPath = true
}
// r
if strings.Contains(e.permissions, "r") {
p.Stat = true // currently assumed
p.GetPath = true // currently assumed
p.InitiateFileDownload = true
p.ListContainer = true
}
@@ -336,10 +341,9 @@ func (e *ACE) grantPermissionSet() *provider.ResourcePermissions {
p.CreateContainer = true
}
// x
// if strings.Contains(e.Permissions, "x") {
// TODO execute file permission?
// TODO change directory permission?
// }
if strings.Contains(e.permissions, "x") {
p.ListContainer = true
}
// d
if strings.Contains(e.permissions, "d") {
p.Delete = true
@@ -436,10 +440,17 @@ func unmarshalKV(s string) (*ACE, error) {
return e, nil
}
// getACEPerm produces an NFSv4.x inspired permission string from a CS3 resource permissions set
func getACEPerm(set *provider.ResourcePermissions) string {
var b strings.Builder
if set.Stat || set.InitiateFileDownload || set.ListContainer || set.GetPath {
if set.Stat || set.GetPath {
b.WriteString("t")
}
if set.ListContainer { // we have no dedicated traversal permission, but to listing a container allows traversing it
b.WriteString("x")
}
if set.InitiateFileDownload {
b.WriteString("r")
}
if set.InitiateFileUpload || set.Move {

View File

@@ -100,6 +100,7 @@ func ServiceAccountPermissions() provider.ResourcePermissions {
RestoreRecycleItem: true, // for cli restore command
Delete: true, // for cli restore command with replace option
CreateContainer: true, // for space provisioning
AddGrant: true, // for initial project space member assignment
}
}

2
vendor/modules.txt vendored
View File

@@ -366,7 +366,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.20240510133919-1732d68a5591
# github.com/cs3org/reva/v2 v2.19.2-0.20240521134642-8fb71adbe500
## explicit; go 1.21
github.com/cs3org/reva/v2/cmd/revad/internal/grace
github.com/cs3org/reva/v2/cmd/revad/runtime