66 "net/http"
77 "net/url"
88 "slices"
9+ "strings"
910
11+ "github.com/CiscoM31/godata"
1012 gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
1113 grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1"
1214 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
@@ -40,16 +42,17 @@ import (
4042)
4143
4244const (
43- invalidIdMsg = "invalid driveID or itemID"
44- parseDriveIDErrMsg = "could not parse driveID"
45+ invalidIdMsg = "invalid driveID or itemID"
46+ parseDriveIDErrMsg = "could not parse driveID"
47+ federatedRolesODataFilter = "@libre.graph.permissions.roles.allowedValues/rolePermissions/any(p:contains(p/condition, '@Subject.UserType==\" Federated\" '))"
4548)
4649
4750// DriveItemPermissionsProvider contains the methods related to handling permissions on drive items
4851type DriveItemPermissionsProvider interface {
4952 Invite (ctx context.Context , resourceId * storageprovider.ResourceId , invite libregraph.DriveItemInvite ) (libregraph.Permission , error )
5053 SpaceRootInvite (ctx context.Context , driveID * storageprovider.ResourceId , invite libregraph.DriveItemInvite ) (libregraph.Permission , error )
51- ListPermissions (ctx context.Context , itemID * storageprovider.ResourceId , listFederatedRoles , selectRoles bool ) (libregraph.CollectionOfPermissionsWithAllowedValues , error )
52- ListSpaceRootPermissions (ctx context.Context , driveID * storageprovider.ResourceId ) (libregraph.CollectionOfPermissionsWithAllowedValues , error )
54+ ListPermissions (ctx context.Context , itemID * storageprovider.ResourceId , listFederatedRoles bool , selectedAttrs map [ string ] struct {} ) (libregraph.CollectionOfPermissionsWithAllowedValues , error )
55+ ListSpaceRootPermissions (ctx context.Context , driveID * storageprovider.ResourceId , selectedAttrs map [ string ] struct {} ) (libregraph.CollectionOfPermissionsWithAllowedValues , error )
5356 DeletePermission (ctx context.Context , itemID * storageprovider.ResourceId , permissionID string ) error
5457 DeleteSpaceRootPermission (ctx context.Context , driveID * storageprovider.ResourceId , permissionID string ) error
5558 UpdatePermission (ctx context.Context , itemID * storageprovider.ResourceId , permissionID string , newPermission libregraph.Permission ) (libregraph.Permission , error )
@@ -341,7 +344,7 @@ func (s DriveItemPermissionsService) SpaceRootInvite(ctx context.Context, driveI
341344}
342345
343346// ListPermissions lists the permissions of a driveItem
344- func (s DriveItemPermissionsService ) ListPermissions (ctx context.Context , itemID * storageprovider.ResourceId , listFederatedRoles , selectRoles bool ) (libregraph.CollectionOfPermissionsWithAllowedValues , error ) {
347+ func (s DriveItemPermissionsService ) ListPermissions (ctx context.Context , itemID * storageprovider.ResourceId , listFederatedRoles bool , selectedAttrs map [ string ] struct {} ) (libregraph.CollectionOfPermissionsWithAllowedValues , error ) {
345348 collectionOfPermissions := libregraph.CollectionOfPermissionsWithAllowedValues {}
346349 gatewayClient , err := s .gatewaySelector .Next ()
347350 if err != nil {
@@ -362,17 +365,22 @@ func (s DriveItemPermissionsService) ListPermissions(ctx context.Context, itemID
362365 permissionSet := statResponse .GetInfo ().GetPermissionSet ()
363366 allowedActions := unifiedrole .CS3ResourcePermissionsToLibregraphActions (permissionSet )
364367
365- collectionOfPermissions = libregraph.CollectionOfPermissionsWithAllowedValues {
366- LibreGraphPermissionsActionsAllowedValues : allowedActions ,
367- LibreGraphPermissionsRolesAllowedValues : conversions .ToValueSlice (
368+ collectionOfPermissions = libregraph.CollectionOfPermissionsWithAllowedValues {}
369+
370+ if _ , ok := selectedAttrs ["@libre.graph.permissions.actions.allowedValues" ]; ok || len (selectedAttrs ) == 0 {
371+ collectionOfPermissions .LibreGraphPermissionsActionsAllowedValues = allowedActions
372+ }
373+
374+ if _ , ok := selectedAttrs ["@libre.graph.permissions.roles.allowedValues" ]; ok || len (selectedAttrs ) == 0 {
375+ collectionOfPermissions .LibreGraphPermissionsRolesAllowedValues = conversions .ToValueSlice (
368376 unifiedrole .GetRolesByPermissions (
369377 unifiedrole .GetRoles (unifiedrole .RoleFilterIDs (s .config .UnifiedRoles .AvailableRoles ... )),
370378 allowedActions ,
371379 condition ,
372380 listFederatedRoles ,
373381 false ,
374382 ),
375- ),
383+ )
376384 }
377385
378386 for i , definition := range collectionOfPermissions .LibreGraphPermissionsRolesAllowedValues {
@@ -381,10 +389,8 @@ func (s DriveItemPermissionsService) ListPermissions(ctx context.Context, itemID
381389 collectionOfPermissions .LibreGraphPermissionsRolesAllowedValues [i ] = definition
382390 }
383391
384- if selectRoles {
385- // drop the actions
386- collectionOfPermissions .LibreGraphPermissionsActionsAllowedValues = nil
387- // no need to fetch shares, we are only interested in the roles
392+ if len (selectedAttrs ) > 0 {
393+ // no need to fetch shares, we are only interested allowedActions and/or allowedRoles
388394 return collectionOfPermissions , nil
389395 }
390396
@@ -438,7 +444,7 @@ func (s DriveItemPermissionsService) ListPermissions(ctx context.Context, itemID
438444}
439445
440446// ListSpaceRootPermissions handles ListPermissions request on project spaces
441- func (s DriveItemPermissionsService ) ListSpaceRootPermissions (ctx context.Context , driveID * storageprovider.ResourceId ) (libregraph.CollectionOfPermissionsWithAllowedValues , error ) {
447+ func (s DriveItemPermissionsService ) ListSpaceRootPermissions (ctx context.Context , driveID * storageprovider.ResourceId , selectedAttrs map [ string ] struct {} ) (libregraph.CollectionOfPermissionsWithAllowedValues , error ) {
442448 collectionOfPermissions := libregraph.CollectionOfPermissionsWithAllowedValues {}
443449 gatewayClient , err := s .gatewaySelector .Next ()
444450 if err != nil {
@@ -456,7 +462,7 @@ func (s DriveItemPermissionsService) ListSpaceRootPermissions(ctx context.Contex
456462 }
457463
458464 rootResourceID := space .GetRoot ()
459- return s .ListPermissions (ctx , rootResourceID , false , false ) // federated roles are not supported for spaces
465+ return s .ListPermissions (ctx , rootResourceID , false , selectedAttrs ) // federated roles are not supported for spaces
460466}
461467
462468// DeletePermission deletes a permission from a drive item
@@ -701,14 +707,26 @@ func (api DriveItemPermissionsApi) ListPermissions(w http.ResponseWriter, r *htt
701707 return
702708 }
703709
710+ sanitizedPath := strings .TrimPrefix (r .URL .Path , "/graph/v1.0/" )
711+ odataReq , err := godata .ParseRequest (r .Context (), sanitizedPath , r .URL .Query ())
712+ if err != nil {
713+ api .logger .Debug ().Err (err ).Interface ("query" , r .URL .Query ()).Msg ("Error parsing ListPermissionRequest: query error" )
714+ errorcode .InvalidRequest .Render (w , r , http .StatusBadRequest , err .Error ())
715+ return
716+ }
717+
704718 var listFederatedRoles bool
705- if GetFilterParam (r ) == "@libre.graph.permissions.roles.allowedValues/rolePermissions/any(p:contains(p/condition, '@Subject.UserType==\" Federated\" '))" {
706- listFederatedRoles = true
719+ if odataReq .Query .Filter != nil {
720+ if odataReq .Query .Filter .RawValue == federatedRolesODataFilter {
721+ listFederatedRoles = true
722+ }
707723 }
708724
709- var selectRoles bool
710- if GetSelectParam (r ) == "@libre.graph.permissions.roles.allowedValues" {
711- selectRoles = true
725+ selectRoles , err := api .listPermissionsQuerySelectValues (odataReq .Query )
726+ if err != nil {
727+ api .logger .Debug ().Err (err ).Interface ("query" , r .URL .Query ()).Msg ("Error parsing ListPermissionRequest: query error" )
728+ errorcode .InvalidRequest .Render (w , r , http .StatusBadRequest , err .Error ())
729+ return
712730 }
713731
714732 ctx := r .Context ()
@@ -746,8 +764,23 @@ func (api DriveItemPermissionsApi) ListSpaceRootPermissions(w http.ResponseWrite
746764 return
747765 }
748766
767+ sanitizedPath := strings .TrimPrefix (r .URL .Path , "/graph/v1.0/" )
768+ odataReq , err := godata .ParseRequest (r .Context (), sanitizedPath , r .URL .Query ())
769+ if err != nil {
770+ api .logger .Debug ().Err (err ).Interface ("query" , r .URL .Query ()).Msg ("Error parsing ListPermissionRequest: query error" )
771+ errorcode .InvalidRequest .Render (w , r , http .StatusBadRequest , err .Error ())
772+ return
773+ }
774+
775+ selected , err := api .listPermissionsQuerySelectValues (odataReq .Query )
776+ if err != nil {
777+ api .logger .Debug ().Err (err ).Interface ("query" , r .URL .Query ()).Msg ("Error parsing ListPermissionRequest: query error" )
778+ errorcode .InvalidRequest .Render (w , r , http .StatusBadRequest , err .Error ())
779+ return
780+ }
781+
749782 ctx := r .Context ()
750- permissions , err := api .driveItemPermissionsService .ListSpaceRootPermissions (ctx , & driveID )
783+ permissions , err := api .driveItemPermissionsService .ListSpaceRootPermissions (ctx , & driveID , selected )
751784
752785 if err != nil {
753786 errorcode .RenderError (w , r , err )
@@ -903,3 +936,19 @@ func (api DriveItemPermissionsApi) UpdateSpaceRootPermission(w http.ResponseWrit
903936 render .Status (r , http .StatusOK )
904937 render .JSON (w , r , & updatedPermission )
905938}
939+
940+ func (api DriveItemPermissionsApi ) listPermissionsQuerySelectValues (odataQuery * godata.GoDataQuery ) (map [string ]struct {}, error ) {
941+ selectedAttrs := map [string ]struct {}{}
942+ if odataQuery .Select != nil {
943+ for _ , item := range odataQuery .Select .SelectItems {
944+ // for now we only support a limitted set of $select attributes
945+ if item .Segments [0 ].Value == "@libre.graph.permissions.roles.allowedValues" || item .Segments [0 ].Value == "@libre.graph.permissions.actions.allowedValues" {
946+ selectedAttrs [item .Segments [0 ].Value ] = struct {}{}
947+ } else {
948+ api .logger .Debug ().Msg ("Error parsing ListPermissionRequest: unsupported select item" )
949+ return selectedAttrs , errorcode .New (errorcode .InvalidRequest , "unsupported select item" )
950+ }
951+ }
952+ }
953+ return selectedAttrs , nil
954+ }
0 commit comments