diff --git a/pkg/services/accesscontrol/resourcepermissions/service.go b/pkg/services/accesscontrol/resourcepermissions/service.go index 2d3a2de07ec..923735d44d5 100644 --- a/pkg/services/accesscontrol/resourcepermissions/service.go +++ b/pkg/services/accesscontrol/resourcepermissions/service.go @@ -6,6 +6,8 @@ import ( "fmt" "sort" + "golang.org/x/exp/slices" + "github.com/grafana/grafana/pkg/api/routing" "github.com/grafana/grafana/pkg/apimachinery/identity" "github.com/grafana/grafana/pkg/infra/db" @@ -83,16 +85,18 @@ func New(cfg *setting.Cfg, } s := &Service{ - ac: ac, - store: NewStore(cfg, sqlStore, features), - options: options, - license: license, - permissions: permissions, - actions: actions, - sqlStore: sqlStore, - service: service, - teamService: teamService, - userService: userService, + ac: ac, + features: features, + store: NewStore(cfg, sqlStore, features), + options: options, + license: license, + permissions: permissions, + actions: actions, + sqlStore: sqlStore, + service: service, + teamService: teamService, + userService: userService, + actionSetSvc: actionSetService, } s.api = newApi(cfg, ac, router, s) @@ -108,18 +112,20 @@ func New(cfg *setting.Cfg, // Service is used to create access control sub system including api / and service for managed resource permission type Service struct { - ac accesscontrol.AccessControl - service accesscontrol.Service - store Store - api *api - license licensing.Licensing + ac accesscontrol.AccessControl + features featuremgmt.FeatureToggles + service accesscontrol.Service + store Store + api *api + license licensing.Licensing - options Options - permissions []string - actions []string - sqlStore db.DB - teamService team.Service - userService user.Service + options Options + permissions []string + actions []string + sqlStore db.DB + teamService team.Service + userService user.Service + actionSetSvc ActionSetService } func (s *Service) GetPermissions(ctx context.Context, user identity.Requester, resourceID string) ([]accesscontrol.ResourcePermission, error) { @@ -132,9 +138,21 @@ func (s *Service) GetPermissions(ctx context.Context, user identity.Requester, r } } - return s.store.GetResourcePermissions(ctx, user.GetOrgID(), GetResourcePermissionsQuery{ + actions := s.actions + if s.features.IsEnabled(ctx, featuremgmt.FlagAccessActionSets) { + for _, action := range s.actions { + actionSets := s.actionSetSvc.ResolveAction(action) + for _, actionSet := range actionSets { + if !slices.Contains(actions, actionSet) { + actions = append(actions, actionSet) + } + } + } + } + + resourcePermissions, err := s.store.GetResourcePermissions(ctx, user.GetOrgID(), GetResourcePermissionsQuery{ User: user, - Actions: s.actions, + Actions: actions, Resource: s.options.Resource, ResourceID: resourceID, ResourceAttribute: s.options.ResourceAttribute, @@ -142,6 +160,35 @@ func (s *Service) GetPermissions(ctx context.Context, user identity.Requester, r OnlyManaged: s.options.OnlyManaged, EnforceAccessControl: s.license.FeatureEnabled("accesscontrol.enforcement"), }) + if err != nil { + return nil, err + } + + if s.features.IsEnabled(ctx, featuremgmt.FlagAccessActionSets) { + for i := range resourcePermissions { + actions := resourcePermissions[i].Actions + var expandedActions []string + for _, action := range actions { + if isFolderOrDashboardAction(action) { + actionSetActions := s.actionSetSvc.ResolveActionSet(action) + if len(actionSetActions) > 0 { + for _, actionSetAction := range actionSetActions { + // This check is needed for resolving inherited permissions - we don't want to include + // actions that are not related to dashboards when expanding folder action sets + if slices.Contains(s.actions, actionSetAction) { + expandedActions = append(expandedActions, actionSetAction) + } + } + continue + } + } + expandedActions = append(expandedActions, action) + } + resourcePermissions[i].Actions = expandedActions + } + } + + return resourcePermissions, nil } func (s *Service) SetUserPermission(ctx context.Context, orgID int64, user accesscontrol.User, resourceID, permission string) (*accesscontrol.ResourcePermission, error) {