diff --git a/pkg/services/dashboards/accesscontrol.go b/pkg/services/dashboards/accesscontrol.go index fef2c57390b..d01f9d719cf 100644 --- a/pkg/services/dashboards/accesscontrol.go +++ b/pkg/services/dashboards/accesscontrol.go @@ -96,6 +96,28 @@ func NewFolderIDScopeResolver(db Store, folderDB folder.FolderStore, folderSvc f }) } +// NewFolderUIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "folders:uid:" +// into uid based scopes for folder and its parents +func NewFolderUIDScopeResolver(db Store, folderDB folder.FolderStore, folderSvc folder.Service) (string, ac.ScopeAttributeResolver) { + prefix := ScopeFoldersProvider.GetResourceScopeUID("") + return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) { + if !strings.HasPrefix(scope, prefix) { + return nil, ac.ErrInvalidScope + } + + uid, err := ac.ParseScopeUID(scope) + if err != nil { + return nil, err + } + + inheritedScopes, err := GetInheritedScopes(ctx, orgID, uid, folderSvc) + if err != nil { + return nil, err + } + return append(inheritedScopes, ScopeFoldersProvider.GetResourceScopeUID(uid)), nil + }) +} + // NewDashboardIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "dashboards:id:" // into uid based scopes for both dashboard and folder func NewDashboardIDScopeResolver(db Store, folderDB folder.FolderStore, folderSvc folder.Service) (string, ac.ScopeAttributeResolver) { diff --git a/pkg/services/folder/folderimpl/folder.go b/pkg/services/folder/folderimpl/folder.go index 3d4ea736581..21e8423d376 100644 --- a/pkg/services/folder/folderimpl/folder.go +++ b/pkg/services/folder/folderimpl/folder.go @@ -48,7 +48,7 @@ func ProvideService( features featuremgmt.FeatureToggles, ) folder.Service { store := ProvideStore(db, cfg, features) - svr := &Service{ + srv := &Service{ cfg: cfg, log: log.New("folder-service"), dashboardStore: dashboardStore, @@ -59,12 +59,13 @@ func ProvideService( bus: bus, } if features.IsEnabled(featuremgmt.FlagNestedFolders) { - svr.DBMigration(db) + srv.DBMigration(db) } - ac.RegisterScopeAttributeResolver(dashboards.NewFolderNameScopeResolver(dashboardStore, folderStore, svr)) - ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(dashboardStore, folderStore, svr)) - return svr + ac.RegisterScopeAttributeResolver(dashboards.NewFolderNameScopeResolver(dashboardStore, folderStore, srv)) + ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(dashboardStore, folderStore, srv)) + ac.RegisterScopeAttributeResolver(dashboards.NewFolderUIDScopeResolver(dashboardStore, folderStore, srv)) + return srv } func (s *Service) DBMigration(db db.DB) { diff --git a/pkg/services/folder/folderimpl/folder_test.go b/pkg/services/folder/folderimpl/folder_test.go index 1bfea0b8e92..8da103d558c 100644 --- a/pkg/services/folder/folderimpl/folder_test.go +++ b/pkg/services/folder/folderimpl/folder_test.go @@ -40,7 +40,7 @@ func TestIntegrationProvideFolderService(t *testing.T) { ac := acmock.New() ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, nil, nil, nil, &featuremgmt.FeatureManager{}) - require.Len(t, ac.Calls.RegisterAttributeScopeResolver, 2) + require.Len(t, ac.Calls.RegisterAttributeScopeResolver, 3) }) }