Skip to content

Commit c59601d

Browse files
authored
Merge pull request #916 from rhafer/issue/485
graph: Add more $select options to ListPermissions endpoint
2 parents db7d053 + 45be2ef commit c59601d

4 files changed

Lines changed: 108 additions & 68 deletions

File tree

services/graph/mocks/drive_item_permissions_provider.go

Lines changed: 30 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/graph/pkg/service/v0/api_driveitem_permissions.go

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import (
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

4244
const (
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
4851
type 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

Comments
 (0)