diff --git a/pkg/api/annotations_test.go b/pkg/api/annotations_test.go index cffc023b909..823fc70ad24 100644 --- a/pkg/api/annotations_test.go +++ b/pkg/api/annotations_test.go @@ -407,8 +407,6 @@ func TestAPI_Annotations(t *testing.T) { dashService.On("GetDashboard", mock.Anything, mock.Anything).Return(&dashboards.Dashboard{UID: dashUID, FolderUID: folderUID, FolderID: 1}, nil) folderService := &foldertest.FakeService{} folderService.ExpectedFolder = &folder.Folder{UID: folderUID, ID: 1} - folderDB := &foldertest.FakeFolderStore{} - folderDB.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(&folder.Folder{UID: folderUID, ID: 1}, nil) hs.DashboardService = dashService hs.folderService = folderService hs.AccessControl = acimpl.ProvideAccessControl(featuremgmt.WithFeatures()) diff --git a/pkg/api/folder_bench_test.go b/pkg/api/folder_bench_test.go index c9a6bae4874..167aa242c1e 100644 --- a/pkg/api/folder_bench_test.go +++ b/pkg/api/folder_bench_test.go @@ -430,14 +430,12 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog dashStore, err := database.ProvideDashboardStore(sc.db, sc.cfg, features, tagimpl.ProvideService(sc.db)) require.NoError(b, err) - folderStore := folderimpl.ProvideDashboardFolderStore(sc.db) - ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures()) cfg := setting.NewCfg() actionSets := resourcepermissions.NewActionSetService() fStore := folderimpl.ProvideStore(sc.db) folderServiceWithFlagOn := folderimpl.ProvideService( - fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore, + fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, nil, sc.db, features, supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), sort.ProvideService(), apiserver.WithoutRestConfig) acSvc := acimpl.ProvideOSSService( sc.cfg, acdb.ProvideService(sc.db), actionSets, localcache.ProvideService(), @@ -449,7 +447,6 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog dashboardSvc, err := dashboardservice.ProvideDashboardServiceImpl( sc.cfg, dashStore, - folderStore, features, folderPermissions, ac, diff --git a/pkg/registry/apis/dashboard/register.go b/pkg/registry/apis/dashboard/register.go index 3479cae5dc6..08cf99809cf 100644 --- a/pkg/registry/apis/dashboard/register.go +++ b/pkg/registry/apis/dashboard/register.go @@ -47,7 +47,6 @@ import ( dashsvc "github.com/grafana/grafana/pkg/services/dashboards/service" "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/librarypanels" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" "github.com/grafana/grafana/pkg/services/provisioning" @@ -89,7 +88,6 @@ type DashboardsAPIBuilder struct { scheme *runtime.Scheme search *SearchHandler dashStore dashboards.Store - folderStore folder.FolderStore QuotaService quota.Service ProvisioningService provisioning.ProvisioningService cfg *setting.Cfg @@ -125,7 +123,6 @@ func RegisterAPIService( dual dualwrite.Service, sorter sort.Service, quotaService quota.Service, - folderStore folder.FolderStore, libraryPanelSvc librarypanels.Service, restConfigProvider apiserver.RestConfigProvider, userService user.Service, @@ -149,7 +146,6 @@ func RegisterAPIService( dashboardProvisioningService: provisioningDashboardService, search: NewSearchHandler(tracing, dual, legacyDashboardSearcher, unified, features), dashStore: dashStore, - folderStore: folderStore, QuotaService: quotaService, ProvisioningService: provisioning, cfg: cfg, diff --git a/pkg/registry/apis/folders/legacy_storage.go b/pkg/registry/apis/folders/legacy_storage.go index 380cb6f4ace..d2a2c4fdfac 100644 --- a/pkg/registry/apis/folders/legacy_storage.go +++ b/pkg/registry/apis/folders/legacy_storage.go @@ -31,7 +31,7 @@ var ( ) type legacyStorage struct { - service folder.Service + service folder.LegacyService namespacer request.NamespaceMapper tableConverter rest.TableConvertor } @@ -243,6 +243,7 @@ func (s *legacyStorage) Update(ctx context.Context, return nil, created, fmt.Errorf("expected old object to be a folder also") } + changed := false mOld, _ := utils.MetaAccessor(old) mNew, _ := utils.MetaAccessor(f) oldParent := mOld.GetFolder() @@ -257,9 +258,9 @@ func (s *legacyStorage) Update(ctx context.Context, if err != nil { return nil, created, err } + changed = true } - changed := false cmd := &folder.UpdateFolderCommand{ SignedInUser: user, UID: name, diff --git a/pkg/registry/apis/folders/register.go b/pkg/registry/apis/folders/register.go index e33cf83dc1f..4467eac5065 100644 --- a/pkg/registry/apis/folders/register.go +++ b/pkg/registry/apis/folders/register.go @@ -17,17 +17,16 @@ import ( "k8s.io/kube-openapi/pkg/common" "k8s.io/kube-openapi/pkg/spec3" - "github.com/grafana/grafana/apps/iam/pkg/reconcilers" - "github.com/grafana/grafana/pkg/services/authz/zanzana" - authlib "github.com/grafana/authlib/types" folders "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" + "github.com/grafana/grafana/apps/iam/pkg/reconcilers" "github.com/grafana/grafana/pkg/apimachinery/identity" grafanaregistry "github.com/grafana/grafana/pkg/apiserver/registry/generic" grafanarest "github.com/grafana/grafana/pkg/apiserver/rest" "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/apiserver/builder" "github.com/grafana/grafana/pkg/services/apiserver/endpoints/request" + "github.com/grafana/grafana/pkg/services/authz/zanzana" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/setting" @@ -48,7 +47,7 @@ var errNoResource = errors.New("resource name is required") type FolderAPIBuilder struct { features featuremgmt.FeatureToggles namespacer request.NamespaceMapper - folderSvc folder.Service + folderSvc folder.LegacyService folderPermissionsSvc accesscontrol.FolderPermissionsService acService accesscontrol.Service ac accesscontrol.AccessControl @@ -66,7 +65,7 @@ type FolderAPIBuilder struct { func RegisterAPIService(cfg *setting.Cfg, features featuremgmt.FeatureToggles, apiregistration builder.APIRegistrar, - folderSvc folder.Service, + folderSvc folder.LegacyService, folderPermissionsSvc accesscontrol.FolderPermissionsService, accessControl accesscontrol.AccessControl, acService accesscontrol.Service, @@ -190,13 +189,13 @@ func (b *FolderAPIBuilder) UpdateAPIGroupInfo(apiGroupInfo *genericapiserver.API } storage[resourceInfo.StoragePath()] = folderStore - b.parents = newParentsGetter(folderStore, folderValidationRules.maxDepth) // used for validation + b.parents = newParentsGetter(folderStore, folder.MaxNestedFolderDepth) // used for validation storage[resourceInfo.StoragePath("parents")] = &subParentsREST{ getter: folderStore, parents: b.parents, } storage[resourceInfo.StoragePath("counts")] = &subCountREST{searcher: b.searcher} - storage[resourceInfo.StoragePath("access")] = &subAccessREST{b.folderSvc, b.ac} + storage[resourceInfo.StoragePath("access")] = &subAccessREST{folderStore, b.ac} // Adds a path to return children of a given folder storage[resourceInfo.StoragePath("children")] = &subChildrenREST{ @@ -226,12 +225,6 @@ func (b *FolderAPIBuilder) GetAuthorizer() authorizer.Authorizer { return b.authorizer } -var folderValidationRules = struct { - maxDepth int -}{ - maxDepth: 5, // why different than folder.MaxNestedFolderDepth?? (4) -} - func (b *FolderAPIBuilder) Mutate(ctx context.Context, a admission.Attributes, _ admission.ObjectInterfaces) error { verb := a.GetOperation() if verb == admission.Create || verb == admission.Update { @@ -259,7 +252,7 @@ func (b *FolderAPIBuilder) Validate(ctx context.Context, a admission.Attributes, switch a.GetOperation() { case admission.Create: - return validateOnCreate(ctx, f, b.parents, folderValidationRules.maxDepth) + return validateOnCreate(ctx, f, b.parents, folder.MaxNestedFolderDepth) case admission.Delete: return validateOnDelete(ctx, f, b.searcher) case admission.Update: @@ -267,7 +260,7 @@ func (b *FolderAPIBuilder) Validate(ctx context.Context, a admission.Attributes, if !ok { return fmt.Errorf("obj is not folders.Folder") } - return validateOnUpdate(ctx, f, old, b.storage, b.parents, folderValidationRules.maxDepth) + return validateOnUpdate(ctx, f, old, b.storage, b.parents, folder.MaxNestedFolderDepth) default: return nil } diff --git a/pkg/registry/apis/folders/sub_access.go b/pkg/registry/apis/folders/sub_access.go index 26882678925..2b6bb443252 100644 --- a/pkg/registry/apis/folders/sub_access.go +++ b/pkg/registry/apis/folders/sub_access.go @@ -4,8 +4,7 @@ import ( "context" "net/http" - "github.com/grafana/grafana/pkg/services/apiserver/endpoints/request" - "github.com/grafana/grafana/pkg/services/folder" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/registry/rest" @@ -16,8 +15,8 @@ import ( ) type subAccessREST struct { - service folder.Service - ac accesscontrol.AccessControl + getter rest.Getter + ac accesscontrol.AccessControl } var _ = rest.Connecter(&subAccessREST{}) @@ -47,36 +46,28 @@ func (r *subAccessREST) NewConnectOptions() (runtime.Object, bool, string) { } func (r *subAccessREST) Connect(ctx context.Context, name string, opts runtime.Object, responder rest.Responder) (http.Handler, error) { - ns, err := request.NamespaceInfoFrom(ctx, true) - if err != nil { - return nil, err - } user, err := identity.GetRequester(ctx) if err != nil { return nil, err } - // Can view is managed here (and in the Authorizer) - f, err := r.service.Get(ctx, &folder.GetFolderQuery{ - UID: &name, - OrgID: ns.OrgID, - SignedInUser: user, - }) + // Must be able to get the resource + _, err = r.getter.Get(ctx, name, &v1.GetOptions{}) if err != nil { return nil, err } return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { access := &folders.FolderAccessInfo{} - canEditEvaluator := accesscontrol.EvalPermission(dashboards.ActionFoldersWrite, dashboards.ScopeFoldersProvider.GetResourceScopeUID(f.UID)) + canEditEvaluator := accesscontrol.EvalPermission(dashboards.ActionFoldersWrite, dashboards.ScopeFoldersProvider.GetResourceScopeUID(name)) access.CanEdit, _ = r.ac.Evaluate(ctx, user, canEditEvaluator) access.CanSave = access.CanEdit canAdminEvaluator := accesscontrol.EvalAll( - accesscontrol.EvalPermission(dashboards.ActionFoldersPermissionsRead, dashboards.ScopeFoldersProvider.GetResourceScopeUID(f.UID)), - accesscontrol.EvalPermission(dashboards.ActionFoldersPermissionsWrite, dashboards.ScopeFoldersProvider.GetResourceScopeUID(f.UID)), + accesscontrol.EvalPermission(dashboards.ActionFoldersPermissionsRead, dashboards.ScopeFoldersProvider.GetResourceScopeUID(name)), + accesscontrol.EvalPermission(dashboards.ActionFoldersPermissionsWrite, dashboards.ScopeFoldersProvider.GetResourceScopeUID(name)), ) access.CanAdmin, _ = r.ac.Evaluate(ctx, user, canAdminEvaluator) - canDeleteEvaluator := accesscontrol.EvalPermission(dashboards.ActionFoldersDelete, dashboards.ScopeFoldersProvider.GetResourceScopeUID(f.UID)) + canDeleteEvaluator := accesscontrol.EvalPermission(dashboards.ActionFoldersDelete, dashboards.ScopeFoldersProvider.GetResourceScopeUID(name)) access.CanDelete, _ = r.ac.Evaluate(ctx, user, canDeleteEvaluator) responder.Object(http.StatusOK, access) }), nil diff --git a/pkg/server/wire.go b/pkg/server/wire.go index 8dd9b0f9d9c..32bed9be52f 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -344,10 +344,9 @@ var wireBasicSet = wire.NewSet( dashboardstore.ProvideDashboardStore, folderimpl.ProvideService, wire.Bind(new(folder.Service), new(*folderimpl.Service)), + wire.Bind(new(folder.LegacyService), new(*folderimpl.Service)), folderimpl.ProvideStore, wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), - folderimpl.ProvideDashboardFolderStore, - wire.Bind(new(folder.FolderStore), new(*folderimpl.DashboardFolderStoreImpl)), dashboardimportservice.ProvideService, wire.Bind(new(dashboardimport.Service), new(*dashboardimportservice.ImportDashboardService)), plugindashboardsservice.ProvideService, diff --git a/pkg/server/wire_gen.go b/pkg/server/wire_gen.go index 62420dc7034..7eb34a312ef 100644 --- a/pkg/server/wire_gen.go +++ b/pkg/server/wire_gen.go @@ -424,7 +424,6 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api if err != nil { return nil, err } - dashboardFolderStoreImpl := folderimpl.ProvideDashboardFolderStore(sqlStore) publicDashboardStoreImpl := database3.ProvideStore(sqlStore, cfg, featureToggles) publicDashboardServiceWrapperImpl := service3.ProvideServiceWrapper(publicDashboardStoreImpl) registerer := metrics.ProvideRegisterer() @@ -508,7 +507,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api } dualwriteService := dualwrite.ProvideService(featureToggles, registerer, kvStore, cfg) sortService := sort.ProvideService() - folderimplService := folderimpl.ProvideService(folderStoreImpl, accessControl, inProcBus, dashboardsStore, dashboardFolderStoreImpl, userService, sqlStore, featureToggles, bundleregistryService, publicDashboardServiceWrapperImpl, cfg, registerer, tracer, resourceClient, dualwriteService, sortService, eventualRestConfigProvider) + folderimplService := folderimpl.ProvideService(folderStoreImpl, accessControl, inProcBus, dashboardsStore, userService, sqlStore, featureToggles, bundleregistryService, publicDashboardServiceWrapperImpl, cfg, registerer, tracer, resourceClient, dualwriteService, sortService, eventualRestConfigProvider) searchService := searchV2.ProvideService(cfg, sqlStore, entityEventsService, acimplService, tracingService, featureToggles, orgService, userService, folderimplService) systemUsers := store.ProvideSystemUsersService() storageService, err := store.ProvideService(sqlStore, featureToggles, cfg, quotaService, systemUsers) @@ -554,7 +553,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api return nil, err } k8sHandlerWithFallback := client.ProvideK8sClientWithFallback(cfg, eventualRestConfigProvider, dashboardsStore, userService, resourceClient, featureToggles, dualwriteService, sortService, registerer) - dashboardServiceImpl, err := service7.ProvideDashboardServiceImpl(cfg, dashboardsStore, dashboardFolderStoreImpl, featureToggles, folderPermissionsService, accessControl, acimplService, folderimplService, registerer, quotaService, orgService, publicDashboardServiceWrapperImpl, dualwriteService, serverLockService, kvStore, k8sHandlerWithFallback) + dashboardServiceImpl, err := service7.ProvideDashboardServiceImpl(cfg, dashboardsStore, featureToggles, folderPermissionsService, accessControl, acimplService, folderimplService, registerer, quotaService, orgService, publicDashboardServiceWrapperImpl, dualwriteService, serverLockService, kvStore, k8sHandlerWithFallback) if err != nil { return nil, err } @@ -794,7 +793,7 @@ func Initialize(ctx context.Context, cfg *setting.Cfg, opts Options, apiOpts api identitySynchronizer := authnimpl.ProvideIdentitySynchronizer(authnimplService) ldapImpl := service12.ProvideService(cfg, featureToggles, ssosettingsimplService) apiService := api4.ProvideService(cfg, routeRegisterImpl, accessControl, userService, authinfoimplService, ossGroups, identitySynchronizer, orgService, ldapImpl, userAuthTokenService, bundleregistryService) - dashboardsAPIBuilder := dashboard.RegisterAPIService(cfg, featureToggles, apiserverService, dashboardService, dashboardProvisioningService, pluginstoreService, service15, dashboardServiceImpl, dashboardPermissionsService, accessControl, accessClient, provisioningServiceImpl, dashboardsStore, registerer, sqlStore, tracingService, resourceClient, dualwriteService, sortService, quotaService, dashboardFolderStoreImpl, libraryPanelService, eventualRestConfigProvider, userService) + dashboardsAPIBuilder := dashboard.RegisterAPIService(cfg, featureToggles, apiserverService, dashboardService, dashboardProvisioningService, pluginstoreService, service15, dashboardServiceImpl, dashboardPermissionsService, accessControl, accessClient, provisioningServiceImpl, dashboardsStore, registerer, sqlStore, tracingService, resourceClient, dualwriteService, sortService, quotaService, libraryPanelService, eventualRestConfigProvider, userService) snapshotsAPIBuilder := dashboardsnapshot.RegisterAPIService(serviceImpl, apiserverService, cfg, featureToggles, sqlStore, registerer) featureFlagAPIBuilder := featuretoggle.RegisterAPIService(featureManager, accessControl, apiserverService, cfg, registerer) dataSourceAPIBuilder, err := datasource.RegisterAPIService(featureToggles, apiserverService, middlewareHandler, scopedPluginDatasourceProvider, plugincontextProvider, pluginstoreService, accessControl, registerer) @@ -1010,7 +1009,6 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac if err != nil { return nil, err } - dashboardFolderStoreImpl := folderimpl.ProvideDashboardFolderStore(sqlStore) publicDashboardStoreImpl := database3.ProvideStore(sqlStore, cfg, featureToggles) publicDashboardServiceWrapperImpl := service3.ProvideServiceWrapper(publicDashboardStoreImpl) registerer := metrics.ProvideRegistererForTest() @@ -1094,7 +1092,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac } dualwriteService := dualwrite.ProvideService(featureToggles, registerer, kvStore, cfg) sortService := sort.ProvideService() - folderimplService := folderimpl.ProvideService(folderStoreImpl, accessControl, inProcBus, dashboardsStore, dashboardFolderStoreImpl, userService, sqlStore, featureToggles, bundleregistryService, publicDashboardServiceWrapperImpl, cfg, registerer, tracer, resourceClient, dualwriteService, sortService, eventualRestConfigProvider) + folderimplService := folderimpl.ProvideService(folderStoreImpl, accessControl, inProcBus, dashboardsStore, userService, sqlStore, featureToggles, bundleregistryService, publicDashboardServiceWrapperImpl, cfg, registerer, tracer, resourceClient, dualwriteService, sortService, eventualRestConfigProvider) searchService := searchV2.ProvideService(cfg, sqlStore, entityEventsService, acimplService, tracingService, featureToggles, orgService, userService, folderimplService) systemUsers := store.ProvideSystemUsersService() storageService, err := store.ProvideService(sqlStore, featureToggles, cfg, quotaService, systemUsers) @@ -1140,7 +1138,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac return nil, err } k8sHandlerWithFallback := client.ProvideK8sClientWithFallback(cfg, eventualRestConfigProvider, dashboardsStore, userService, resourceClient, featureToggles, dualwriteService, sortService, registerer) - dashboardServiceImpl, err := service7.ProvideDashboardServiceImpl(cfg, dashboardsStore, dashboardFolderStoreImpl, featureToggles, folderPermissionsService, accessControl, acimplService, folderimplService, registerer, quotaService, orgService, publicDashboardServiceWrapperImpl, dualwriteService, serverLockService, kvStore, k8sHandlerWithFallback) + dashboardServiceImpl, err := service7.ProvideDashboardServiceImpl(cfg, dashboardsStore, featureToggles, folderPermissionsService, accessControl, acimplService, folderimplService, registerer, quotaService, orgService, publicDashboardServiceWrapperImpl, dualwriteService, serverLockService, kvStore, k8sHandlerWithFallback) if err != nil { return nil, err } @@ -1382,7 +1380,7 @@ func InitializeForTest(ctx context.Context, t sqlutil.ITestDB, testingT interfac identitySynchronizer := authnimpl.ProvideIdentitySynchronizer(authnimplService) ldapImpl := service12.ProvideService(cfg, featureToggles, ssosettingsimplService) apiService := api4.ProvideService(cfg, routeRegisterImpl, accessControl, userService, authinfoimplService, ossGroups, identitySynchronizer, orgService, ldapImpl, userAuthTokenService, bundleregistryService) - dashboardsAPIBuilder := dashboard.RegisterAPIService(cfg, featureToggles, apiserverService, dashboardService, dashboardProvisioningService, pluginstoreService, service15, dashboardServiceImpl, dashboardPermissionsService, accessControl, accessClient, provisioningServiceImpl, dashboardsStore, registerer, sqlStore, tracingService, resourceClient, dualwriteService, sortService, quotaService, dashboardFolderStoreImpl, libraryPanelService, eventualRestConfigProvider, userService) + dashboardsAPIBuilder := dashboard.RegisterAPIService(cfg, featureToggles, apiserverService, dashboardService, dashboardProvisioningService, pluginstoreService, service15, dashboardServiceImpl, dashboardPermissionsService, accessControl, accessClient, provisioningServiceImpl, dashboardsStore, registerer, sqlStore, tracingService, resourceClient, dualwriteService, sortService, quotaService, libraryPanelService, eventualRestConfigProvider, userService) snapshotsAPIBuilder := dashboardsnapshot.RegisterAPIService(serviceImpl, apiserverService, cfg, featureToggles, sqlStore, registerer) featureFlagAPIBuilder := featuretoggle.RegisterAPIService(featureManager, accessControl, apiserverService, cfg, registerer) dataSourceAPIBuilder, err := datasource.RegisterAPIService(featureToggles, apiserverService, middlewareHandler, scopedPluginDatasourceProvider, plugincontextProvider, pluginstoreService, accessControl, registerer) @@ -1640,7 +1638,7 @@ var withOTelSet = wire.NewSet( otelTracer, grpcserver.ProvideService, interceptors.ProvideAuthenticator, ) -var wireBasicSet = wire.NewSet(annotationsimpl.ProvideService, wire.Bind(new(annotations.Repository), new(*annotationsimpl.RepositoryImpl)), New, api.ProvideHTTPServer, query.ProvideService, wire.Bind(new(query.Service), new(*query.ServiceImpl)), bus.ProvideBus, wire.Bind(new(bus.Bus), new(*bus.InProcBus)), rendering.ProvideService, wire.Bind(new(rendering.Service), new(*rendering.RenderingService)), routing.ProvideRegister, wire.Bind(new(routing.RouteRegister), new(*routing.RouteRegisterImpl)), hooks.ProvideService, kvstore.ProvideService, localcache.ProvideService, bundleregistry.ProvideService, wire.Bind(new(supportbundles.Service), new(*bundleregistry.Service)), updatemanager.ProvideGrafanaService, updatemanager.ProvidePluginsService, service.ProvideService, wire.Bind(new(usagestats.Service), new(*service.UsageStats)), validator3.ProvideService, legacy.ProvideLegacyMigrator, pluginsintegration.WireSet, dashboards.ProvideFileStoreManager, wire.Bind(new(dashboards.FileStore), new(*dashboards.FileStoreManager)), cloudwatch.ProvideService, cloudmonitoring.ProvideService, azuremonitor.ProvideService, postgres.ProvideService, mysql.ProvideService, mssql.ProvideService, store.ProvideEntityEventsService, dualwrite.ProvideService, httpclientprovider.New, wire.Bind(new(httpclient.Provider), new(*httpclient2.Provider)), serverlock.ProvideService, annotationsimpl.ProvideCleanupService, wire.Bind(new(annotations.Cleaner), new(*annotationsimpl.CleanupServiceImpl)), cleanup.ProvideService, shorturlimpl.ProvideService, wire.Bind(new(shorturls.Service), new(*shorturlimpl.ShortURLService)), queryhistory.ProvideService, wire.Bind(new(queryhistory.Service), new(*queryhistory.QueryHistoryService)), correlations.ProvideService, wire.Bind(new(correlations.Service), new(*correlations.CorrelationsService)), quotaimpl.ProvideService, remotecache.ProvideService, wire.Bind(new(remotecache.CacheStorage), new(*remotecache.RemoteCache)), authinfoimpl.ProvideService, wire.Bind(new(login.AuthInfoService), new(*authinfoimpl.Service)), authinfoimpl.ProvideStore, datasourceproxy.ProvideService, sort.ProvideService, search2.ProvideService, searchV2.ProvideService, searchV2.ProvideSearchHTTPService, store.ProvideService, store.ProvideSystemUsersService, live.ProvideService, pushhttp.ProvideService, contexthandler.ProvideService, service12.ProvideService, wire.Bind(new(service12.LDAP), new(*service12.LDAPImpl)), jwt.ProvideService, wire.Bind(new(jwt.JWTService), new(*jwt.AuthService)), store2.ProvideDBStore, image.ProvideDeleteExpiredService, ngalert.ProvideService, librarypanels.ProvideService, wire.Bind(new(librarypanels.Service), new(*librarypanels.LibraryPanelService)), libraryelements.ProvideService, wire.Bind(new(libraryelements.Service), new(*libraryelements.LibraryElementService)), notifications.ProvideService, notifications.ProvideSmtpService, github.ProvideFactory, tracing.ProvideService, tracing.ProvideTracingConfig, wire.Bind(new(tracing.Tracer), new(*tracing.TracingService)), withOTelSet, testdatasource.ProvideService, api4.ProvideService, opentsdb.ProvideService, socialimpl.ProvideService, influxdb.ProvideService, wire.Bind(new(social.Service), new(*socialimpl.SocialService)), tempo.ProvideService, loki.ProvideService, graphite.ProvideService, prometheus.ProvideService, elasticsearch.ProvideService, pyroscope.ProvideService, parca.ProvideService, zipkin.ProvideService, jaeger.ProvideService, service9.ProvideCacheService, wire.Bind(new(datasources.CacheService), new(*service9.CacheServiceImpl)), service2.ProvideEncryptionService, wire.Bind(new(encryption2.Internal), new(*service2.Service)), manager.ProvideSecretsService, wire.Bind(new(secrets.Service), new(*manager.SecretsService)), database.ProvideSecretsStore, wire.Bind(new(secrets.Store), new(*database.SecretsStoreImpl)), garbagecollectionworker.ProvideWorker, grafanads.ProvideService, wire.Bind(new(dashboardsnapshots.Store), new(*database5.DashboardSnapshotStore)), database5.ProvideStore, wire.Bind(new(dashboardsnapshots.Service), new(*service10.ServiceImpl)), service10.ProvideService, service9.ProvideService, wire.Bind(new(datasources.DataSourceService), new(*service9.Service)), service9.ProvideLegacyDataSourceLookup, retriever.ProvideService, wire.Bind(new(serviceaccounts.ServiceAccountRetriever), new(*retriever.Service)), ossaccesscontrol.ProvideServiceAccountPermissions, wire.Bind(new(accesscontrol.ServiceAccountPermissionsService), new(*ossaccesscontrol.ServiceAccountPermissionsService)), manager3.ProvideServiceAccountsService, proxy.ProvideServiceAccountsProxy, wire.Bind(new(serviceaccounts.Service), new(*proxy.ServiceAccountsProxy)), dsquerierclient.NewNullQSDatasourceClientBuilder, expr.ProvideService, featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, service7.ProvideDashboardServiceImpl, wire.Bind(new(dashboards2.PermissionsRegistrationService), new(*service7.DashboardServiceImpl)), service7.ProvideDashboardService, service7.ProvideDashboardProvisioningService, service7.ProvideDashboardPluginService, database2.ProvideDashboardStore, folderimpl.ProvideService, wire.Bind(new(folder.Service), new(*folderimpl.Service)), folderimpl.ProvideStore, wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), folderimpl.ProvideDashboardFolderStore, wire.Bind(new(folder.FolderStore), new(*folderimpl.DashboardFolderStoreImpl)), service11.ProvideService, wire.Bind(new(dashboardimport.Service), new(*service11.ImportDashboardService)), service8.ProvideService, wire.Bind(new(plugindashboards.Service), new(*service8.Service)), service8.ProvideDashboardUpdater, kvstore2.ProvideService, avatar.ProvideAvatarCacheServer, statscollector.ProvideService, csrf.ProvideCSRFFilter, wire.Bind(new(csrf.Service), new(*csrf.CSRF)), ossaccesscontrol.ProvideTeamPermissions, wire.Bind(new(accesscontrol.TeamPermissionsService), new(*ossaccesscontrol.TeamPermissionsService)), ossaccesscontrol.ProvideFolderPermissions, wire.Bind(new(accesscontrol.FolderPermissionsService), new(*ossaccesscontrol.FolderPermissionsService)), ossaccesscontrol.ProvideDashboardPermissions, wire.Bind(new(accesscontrol.DashboardPermissionsService), new(*ossaccesscontrol.DashboardPermissionsService)), ossaccesscontrol.ProvideReceiverPermissionsService, wire.Bind(new(accesscontrol.ReceiverPermissionsService), new(*ossaccesscontrol.ReceiverPermissionsService)), starimpl.ProvideService, playlistimpl.ProvideService, apikeyimpl.ProvideService, dashverimpl.ProvideService, service3.ProvideService, wire.Bind(new(publicdashboards.Service), new(*service3.PublicDashboardServiceImpl)), database3.ProvideStore, wire.Bind(new(publicdashboards.Store), new(*database3.PublicDashboardStoreImpl)), metric.ProvideService, api2.ProvideApi, api3.ProvideApi, userimpl.ProvideService, orgimpl.ProvideService, orgimpl.ProvideDeletionService, statsimpl.ProvideService, grpccontext.ProvideContextHandler, grpcserver.ProvideHealthService, grpcserver.ProvideReflectionService, resolver.ProvideEntityReferenceResolver, teamimpl.ProvideService, teamapi.ProvideTeamAPI, tempuserimpl.ProvideService, loginattemptimpl.ProvideService, wire.Bind(new(loginattempt.Service), new(*loginattemptimpl.Service)), migrations2.ProvideDataSourceMigrationService, migrations2.ProvideSecretMigrationProvider, wire.Bind(new(migrations2.SecretMigrationProvider), new(*migrations2.SecretMigrationProviderImpl)), promtypemigration.ProvideAzurePromMigrationService, promtypemigration.ProvideAmazonPromMigrationService, promtypemigration.ProvidePromTypeMigrationProvider, wire.Bind(new(promtypemigration.PromTypeMigrationProvider), new(*promtypemigration.PromTypeMigrationProviderImpl)), resourcepermissions.NewActionSetService, wire.Bind(new(accesscontrol.ActionResolver), new(resourcepermissions.ActionSetService)), wire.Bind(new(pluginaccesscontrol.ActionSetRegistry), new(resourcepermissions.ActionSetService)), permreg.ProvidePermissionRegistry, acimpl.ProvideAccessControl, dualwrite2.ProvideZanzanaReconciler, navtreeimpl.ProvideService, wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)), wire.Bind(new(notifications.TempUserStore), new(tempuser.Service)), tagimpl.ProvideService, wire.Bind(new(tag.Service), new(*tagimpl.Service)), authnimpl.ProvideService, authnimpl.ProvideIdentitySynchronizer, authnimpl.ProvideAuthnService, authnimpl.ProvideAuthnServiceAuthenticateOnly, authnimpl.ProvideRegistration, supportbundlesimpl.ProvideService, extsvcaccounts.ProvideExtSvcAccountsService, wire.Bind(new(serviceaccounts.ExtSvcAccountsService), new(*extsvcaccounts.ExtSvcAccountsService)), registry2.ProvideExtSvcRegistry, wire.Bind(new(extsvcauth.ExternalServiceRegistry), new(*registry2.Registry)), anonstore.ProvideAnonDBStore, wire.Bind(new(anonstore.AnonStore), new(*anonstore.AnonDBStore)), loggermw.Provide, slogadapter.Provide, signingkeysimpl.ProvideEmbeddedSigningKeysService, wire.Bind(new(signingkeys.Service), new(*signingkeysimpl.Service)), ssosettingsimpl.ProvideService, wire.Bind(new(ssosettings.Service), new(*ssosettingsimpl.Service)), idimpl.ProvideService, wire.Bind(new(auth.IDService), new(*idimpl.Service)), cloudmigrationimpl.ProvideService, userimpl.ProvideVerifier, connectors.ProvideOrgRoleMapper, wire.Bind(new(user.Verifier), new(*userimpl.Verifier)), authz.WireSet, metadata.ProvideSecureValueMetadataStorage, metadata.ProvideKeeperMetadataStorage, metadata.ProvideDecryptStorage, decrypt.ProvideDecryptAuthorizer, decrypt.ProvideDecryptService, inline.ProvideInlineSecureValueService, encryption.ProvideDataKeyStorage, encryption.ProvideGlobalDataKeyStorage, encryption.ProvideEncryptedValueStorage, encryption.ProvideGlobalEncryptedValueStorage, service5.ProvideSecureValueService, validator.ProvideKeeperValidator, validator.ProvideSecureValueValidator, mutator.ProvideKeeperMutator, mutator.ProvideSecureValueMutator, migrator2.NewWithEngine, database4.ProvideDatabase, clock.ProvideClock, wire.Bind(new(contracts.Database), new(*database4.Database)), wire.Bind(new(contracts.Clock), new(*clock.Clock)), manager2.ProvideEncryptionManager, service4.ProvideAESGCMCipherService, resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, apiserver.WireSet, apiregistry.WireSet, appregistry.WireSet, client.ProvideK8sClientWithFallback) +var wireBasicSet = wire.NewSet(annotationsimpl.ProvideService, wire.Bind(new(annotations.Repository), new(*annotationsimpl.RepositoryImpl)), New, api.ProvideHTTPServer, query.ProvideService, wire.Bind(new(query.Service), new(*query.ServiceImpl)), bus.ProvideBus, wire.Bind(new(bus.Bus), new(*bus.InProcBus)), rendering.ProvideService, wire.Bind(new(rendering.Service), new(*rendering.RenderingService)), routing.ProvideRegister, wire.Bind(new(routing.RouteRegister), new(*routing.RouteRegisterImpl)), hooks.ProvideService, kvstore.ProvideService, localcache.ProvideService, bundleregistry.ProvideService, wire.Bind(new(supportbundles.Service), new(*bundleregistry.Service)), updatemanager.ProvideGrafanaService, updatemanager.ProvidePluginsService, service.ProvideService, wire.Bind(new(usagestats.Service), new(*service.UsageStats)), validator3.ProvideService, legacy.ProvideLegacyMigrator, pluginsintegration.WireSet, dashboards.ProvideFileStoreManager, wire.Bind(new(dashboards.FileStore), new(*dashboards.FileStoreManager)), cloudwatch.ProvideService, cloudmonitoring.ProvideService, azuremonitor.ProvideService, postgres.ProvideService, mysql.ProvideService, mssql.ProvideService, store.ProvideEntityEventsService, dualwrite.ProvideService, httpclientprovider.New, wire.Bind(new(httpclient.Provider), new(*httpclient2.Provider)), serverlock.ProvideService, annotationsimpl.ProvideCleanupService, wire.Bind(new(annotations.Cleaner), new(*annotationsimpl.CleanupServiceImpl)), cleanup.ProvideService, shorturlimpl.ProvideService, wire.Bind(new(shorturls.Service), new(*shorturlimpl.ShortURLService)), queryhistory.ProvideService, wire.Bind(new(queryhistory.Service), new(*queryhistory.QueryHistoryService)), correlations.ProvideService, wire.Bind(new(correlations.Service), new(*correlations.CorrelationsService)), quotaimpl.ProvideService, remotecache.ProvideService, wire.Bind(new(remotecache.CacheStorage), new(*remotecache.RemoteCache)), authinfoimpl.ProvideService, wire.Bind(new(login.AuthInfoService), new(*authinfoimpl.Service)), authinfoimpl.ProvideStore, datasourceproxy.ProvideService, sort.ProvideService, search2.ProvideService, searchV2.ProvideService, searchV2.ProvideSearchHTTPService, store.ProvideService, store.ProvideSystemUsersService, live.ProvideService, pushhttp.ProvideService, contexthandler.ProvideService, service12.ProvideService, wire.Bind(new(service12.LDAP), new(*service12.LDAPImpl)), jwt.ProvideService, wire.Bind(new(jwt.JWTService), new(*jwt.AuthService)), store2.ProvideDBStore, image.ProvideDeleteExpiredService, ngalert.ProvideService, librarypanels.ProvideService, wire.Bind(new(librarypanels.Service), new(*librarypanels.LibraryPanelService)), libraryelements.ProvideService, wire.Bind(new(libraryelements.Service), new(*libraryelements.LibraryElementService)), notifications.ProvideService, notifications.ProvideSmtpService, github.ProvideFactory, tracing.ProvideService, tracing.ProvideTracingConfig, wire.Bind(new(tracing.Tracer), new(*tracing.TracingService)), withOTelSet, testdatasource.ProvideService, api4.ProvideService, opentsdb.ProvideService, socialimpl.ProvideService, influxdb.ProvideService, wire.Bind(new(social.Service), new(*socialimpl.SocialService)), tempo.ProvideService, loki.ProvideService, graphite.ProvideService, prometheus.ProvideService, elasticsearch.ProvideService, pyroscope.ProvideService, parca.ProvideService, zipkin.ProvideService, jaeger.ProvideService, service9.ProvideCacheService, wire.Bind(new(datasources.CacheService), new(*service9.CacheServiceImpl)), service2.ProvideEncryptionService, wire.Bind(new(encryption2.Internal), new(*service2.Service)), manager.ProvideSecretsService, wire.Bind(new(secrets.Service), new(*manager.SecretsService)), database.ProvideSecretsStore, wire.Bind(new(secrets.Store), new(*database.SecretsStoreImpl)), garbagecollectionworker.ProvideWorker, grafanads.ProvideService, wire.Bind(new(dashboardsnapshots.Store), new(*database5.DashboardSnapshotStore)), database5.ProvideStore, wire.Bind(new(dashboardsnapshots.Service), new(*service10.ServiceImpl)), service10.ProvideService, service9.ProvideService, wire.Bind(new(datasources.DataSourceService), new(*service9.Service)), service9.ProvideLegacyDataSourceLookup, retriever.ProvideService, wire.Bind(new(serviceaccounts.ServiceAccountRetriever), new(*retriever.Service)), ossaccesscontrol.ProvideServiceAccountPermissions, wire.Bind(new(accesscontrol.ServiceAccountPermissionsService), new(*ossaccesscontrol.ServiceAccountPermissionsService)), manager3.ProvideServiceAccountsService, proxy.ProvideServiceAccountsProxy, wire.Bind(new(serviceaccounts.Service), new(*proxy.ServiceAccountsProxy)), dsquerierclient.NewNullQSDatasourceClientBuilder, expr.ProvideService, featuremgmt.ProvideManagerService, featuremgmt.ProvideToggles, service7.ProvideDashboardServiceImpl, wire.Bind(new(dashboards2.PermissionsRegistrationService), new(*service7.DashboardServiceImpl)), service7.ProvideDashboardService, service7.ProvideDashboardProvisioningService, service7.ProvideDashboardPluginService, database2.ProvideDashboardStore, folderimpl.ProvideService, wire.Bind(new(folder.Service), new(*folderimpl.Service)), wire.Bind(new(folder.LegacyService), new(*folderimpl.Service)), folderimpl.ProvideStore, wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), service11.ProvideService, wire.Bind(new(dashboardimport.Service), new(*service11.ImportDashboardService)), service8.ProvideService, wire.Bind(new(plugindashboards.Service), new(*service8.Service)), service8.ProvideDashboardUpdater, kvstore2.ProvideService, avatar.ProvideAvatarCacheServer, statscollector.ProvideService, csrf.ProvideCSRFFilter, wire.Bind(new(csrf.Service), new(*csrf.CSRF)), ossaccesscontrol.ProvideTeamPermissions, wire.Bind(new(accesscontrol.TeamPermissionsService), new(*ossaccesscontrol.TeamPermissionsService)), ossaccesscontrol.ProvideFolderPermissions, wire.Bind(new(accesscontrol.FolderPermissionsService), new(*ossaccesscontrol.FolderPermissionsService)), ossaccesscontrol.ProvideDashboardPermissions, wire.Bind(new(accesscontrol.DashboardPermissionsService), new(*ossaccesscontrol.DashboardPermissionsService)), ossaccesscontrol.ProvideReceiverPermissionsService, wire.Bind(new(accesscontrol.ReceiverPermissionsService), new(*ossaccesscontrol.ReceiverPermissionsService)), starimpl.ProvideService, playlistimpl.ProvideService, apikeyimpl.ProvideService, dashverimpl.ProvideService, service3.ProvideService, wire.Bind(new(publicdashboards.Service), new(*service3.PublicDashboardServiceImpl)), database3.ProvideStore, wire.Bind(new(publicdashboards.Store), new(*database3.PublicDashboardStoreImpl)), metric.ProvideService, api2.ProvideApi, api3.ProvideApi, userimpl.ProvideService, orgimpl.ProvideService, orgimpl.ProvideDeletionService, statsimpl.ProvideService, grpccontext.ProvideContextHandler, grpcserver.ProvideHealthService, grpcserver.ProvideReflectionService, resolver.ProvideEntityReferenceResolver, teamimpl.ProvideService, teamapi.ProvideTeamAPI, tempuserimpl.ProvideService, loginattemptimpl.ProvideService, wire.Bind(new(loginattempt.Service), new(*loginattemptimpl.Service)), migrations2.ProvideDataSourceMigrationService, migrations2.ProvideSecretMigrationProvider, wire.Bind(new(migrations2.SecretMigrationProvider), new(*migrations2.SecretMigrationProviderImpl)), promtypemigration.ProvideAzurePromMigrationService, promtypemigration.ProvideAmazonPromMigrationService, promtypemigration.ProvidePromTypeMigrationProvider, wire.Bind(new(promtypemigration.PromTypeMigrationProvider), new(*promtypemigration.PromTypeMigrationProviderImpl)), resourcepermissions.NewActionSetService, wire.Bind(new(accesscontrol.ActionResolver), new(resourcepermissions.ActionSetService)), wire.Bind(new(pluginaccesscontrol.ActionSetRegistry), new(resourcepermissions.ActionSetService)), permreg.ProvidePermissionRegistry, acimpl.ProvideAccessControl, dualwrite2.ProvideZanzanaReconciler, navtreeimpl.ProvideService, wire.Bind(new(accesscontrol.AccessControl), new(*acimpl.AccessControl)), wire.Bind(new(notifications.TempUserStore), new(tempuser.Service)), tagimpl.ProvideService, wire.Bind(new(tag.Service), new(*tagimpl.Service)), authnimpl.ProvideService, authnimpl.ProvideIdentitySynchronizer, authnimpl.ProvideAuthnService, authnimpl.ProvideAuthnServiceAuthenticateOnly, authnimpl.ProvideRegistration, supportbundlesimpl.ProvideService, extsvcaccounts.ProvideExtSvcAccountsService, wire.Bind(new(serviceaccounts.ExtSvcAccountsService), new(*extsvcaccounts.ExtSvcAccountsService)), registry2.ProvideExtSvcRegistry, wire.Bind(new(extsvcauth.ExternalServiceRegistry), new(*registry2.Registry)), anonstore.ProvideAnonDBStore, wire.Bind(new(anonstore.AnonStore), new(*anonstore.AnonDBStore)), loggermw.Provide, slogadapter.Provide, signingkeysimpl.ProvideEmbeddedSigningKeysService, wire.Bind(new(signingkeys.Service), new(*signingkeysimpl.Service)), ssosettingsimpl.ProvideService, wire.Bind(new(ssosettings.Service), new(*ssosettingsimpl.Service)), idimpl.ProvideService, wire.Bind(new(auth.IDService), new(*idimpl.Service)), cloudmigrationimpl.ProvideService, userimpl.ProvideVerifier, connectors.ProvideOrgRoleMapper, wire.Bind(new(user.Verifier), new(*userimpl.Verifier)), authz.WireSet, metadata.ProvideSecureValueMetadataStorage, metadata.ProvideKeeperMetadataStorage, metadata.ProvideDecryptStorage, decrypt.ProvideDecryptAuthorizer, decrypt.ProvideDecryptService, inline.ProvideInlineSecureValueService, encryption.ProvideDataKeyStorage, encryption.ProvideGlobalDataKeyStorage, encryption.ProvideEncryptedValueStorage, encryption.ProvideGlobalEncryptedValueStorage, service5.ProvideSecureValueService, validator.ProvideKeeperValidator, validator.ProvideSecureValueValidator, mutator.ProvideKeeperMutator, mutator.ProvideSecureValueMutator, migrator2.NewWithEngine, database4.ProvideDatabase, clock.ProvideClock, wire.Bind(new(contracts.Database), new(*database4.Database)), wire.Bind(new(contracts.Clock), new(*clock.Clock)), manager2.ProvideEncryptionManager, service4.ProvideAESGCMCipherService, resource.ProvideStorageMetrics, resource.ProvideIndexMetrics, apiserver.WireSet, apiregistry.WireSet, appregistry.WireSet, client.ProvideK8sClientWithFallback) var wireSet = wire.NewSet( wireBasicSet, metrics.WireSet, sqlstore.ProvideService, metrics2.ProvideService, wire.Bind(new(notifications.Service), new(*notifications.NotificationService)), wire.Bind(new(notifications.WebhookSender), new(*notifications.NotificationService)), wire.Bind(new(notifications.EmailSender), new(*notifications.NotificationService)), wire.Bind(new(db.DB), new(*sqlstore.SQLStore)), prefimpl.ProvideService, oauthtoken.ProvideService, wire.Bind(new(oauthtoken.OAuthTokenService), new(*oauthtoken.Service)), wire.Bind(new(cleanup.AlertRuleService), new(*store2.DBstore)), diff --git a/pkg/services/accesscontrol/ossaccesscontrol/testutil/testutil.go b/pkg/services/accesscontrol/ossaccesscontrol/testutil/testutil.go index abfce0c4b9c..920d7b826d0 100644 --- a/pkg/services/accesscontrol/ossaccesscontrol/testutil/testutil.go +++ b/pkg/services/accesscontrol/ossaccesscontrol/testutil/testutil.go @@ -47,9 +47,8 @@ func ProvideFolderPermissions( } fStore := folderimpl.ProvideStore(sqlStore) - folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) fService := folderimpl.ProvideService( - fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, + fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, nil, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), sort.ProvideService(), apiserver.WithoutRestConfig) acSvc := acimpl.ProvideOSSService( diff --git a/pkg/services/dashboards/accesscontrol.go b/pkg/services/dashboards/accesscontrol.go index 664874d872e..bfeb6802e94 100644 --- a/pkg/services/dashboards/accesscontrol.go +++ b/pkg/services/dashboards/accesscontrol.go @@ -5,10 +5,11 @@ import ( "errors" "strings" + "go.opentelemetry.io/otel" + "github.com/grafana/grafana/pkg/apimachinery/identity" ac "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/folder" - "go.opentelemetry.io/otel" ) const ( @@ -45,8 +46,10 @@ var ( tracer = otel.Tracer("github.com/grafana/grafana/pkg/services/dashboards") ) +type UIDLookup = func(ctx context.Context, orgID int64, id int64) (string, error) + // NewFolderIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "folders:id:" into an uid based scope. -func NewFolderIDScopeResolver(folderDB folder.FolderStore, folderSvc folder.Service) (string, ac.ScopeAttributeResolver) { +func NewFolderIDScopeResolver(lookup UIDLookup, folderSvc folder.Service) (string, ac.ScopeAttributeResolver) { prefix := ScopeFoldersProvider.GetResourceScope("") return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) { ctx, span := tracer.Start(ctx, "dashboards.NewFolderIDScopeResolver") @@ -66,17 +69,17 @@ func NewFolderIDScopeResolver(folderDB folder.FolderStore, folderSvc folder.Serv } return identity.WithServiceIdentityFn(ctx, orgID, func(ctx context.Context) ([]string, error) { - folder, err := folderDB.GetFolderByID(ctx, orgID, id) + uid, err := lookup(ctx, orgID, id) if err != nil { return nil, err } - result, err := GetInheritedScopes(ctx, folder.OrgID, folder.UID, folderSvc) + result, err := GetInheritedScopes(ctx, orgID, uid, folderSvc) if err != nil { return nil, err } - return append([]string{ScopeFoldersProvider.GetResourceScopeUID(folder.UID)}, result...), nil + return append([]string{ScopeFoldersProvider.GetResourceScopeUID(uid)}, result...), nil }) }) } diff --git a/pkg/services/dashboards/accesscontrol_test.go b/pkg/services/dashboards/accesscontrol_test.go index a08313052f8..463a372a4c0 100644 --- a/pkg/services/dashboards/accesscontrol_test.go +++ b/pkg/services/dashboards/accesscontrol_test.go @@ -2,24 +2,28 @@ package dashboards import ( "context" + "fmt" "math/rand" "testing" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ac "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/folder/foldertest" ) +func noOpLookup(ctx context.Context, orgID int64, id int64) (string, error) { + return fmt.Sprintf("%d", id), nil +} + func TestNewFolderIDScopeResolver(t *testing.T) { t.Run("prefix should be expected", func(t *testing.T) { - prefix, _ := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService()) + prefix, _ := NewFolderIDScopeResolver(noOpLookup, foldertest.NewFakeService()) require.Equal(t, "folders:id:", prefix) }) t.Run("resolver should fail if input scope is not expected", func(t *testing.T) { - _, resolver := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService()) + _, resolver := NewFolderIDScopeResolver(noOpLookup, foldertest.NewFakeService()) _, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:uid:123") require.ErrorIs(t, err, ac.ErrInvalidScope) @@ -29,7 +33,7 @@ func TestNewFolderIDScopeResolver(t *testing.T) { var ( orgId = rand.Int63() scope = "folders:id:0" - _, resolver = NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService()) + _, resolver = NewFolderIDScopeResolver(noOpLookup, foldertest.NewFakeService()) ) resolved, err := resolver.Resolve(context.Background(), orgId, scope) @@ -40,15 +44,15 @@ func TestNewFolderIDScopeResolver(t *testing.T) { }) t.Run("resolver should fail if resource of input scope is empty", func(t *testing.T) { - _, resolver := NewFolderIDScopeResolver(foldertest.NewFakeFolderStore(t), foldertest.NewFakeService()) + _, resolver := NewFolderIDScopeResolver(noOpLookup, foldertest.NewFakeService()) _, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:id:") require.ErrorIs(t, err, ac.ErrInvalidScope) }) t.Run("returns 'not found' if folder does not exist", func(t *testing.T) { - folderStore := foldertest.NewFakeFolderStore(t) - folderStore.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once() - _, resolver := NewFolderIDScopeResolver(folderStore, foldertest.NewFakeService()) + _, resolver := NewFolderIDScopeResolver(func(ctx context.Context, orgID int64, id int64) (string, error) { + return "", ErrDashboardNotFound + }, foldertest.NewFakeService()) orgId := rand.Int63() scope := "folders:id:10" diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index 4826b9b0a56..4294a2c7d5b 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -83,7 +83,6 @@ type DashboardServiceImpl struct { cfg *setting.Cfg log log.Logger dashboardStore dashboards.Store - folderStore folder.FolderStore folderService folder.Service orgService org.Service features featuremgmt.FeatureToggles @@ -373,7 +372,6 @@ var _ registry.BackgroundService = (*DashboardServiceImpl)(nil) func ProvideDashboardServiceImpl( cfg *setting.Cfg, dashboardStore dashboards.Store, - folderStore folder.FolderStore, features featuremgmt.FeatureToggles, folderPermissionsService accesscontrol.FolderPermissionsService, ac accesscontrol.AccessControl, @@ -396,7 +394,6 @@ func ProvideDashboardServiceImpl( folderPermissions: folderPermissionsService, ac: ac, acService: acService, - folderStore: folderStore, folderService: folderSvc, orgService: orgService, k8sclient: k8sClient, diff --git a/pkg/services/dashboards/service/dashboard_service_test.go b/pkg/services/dashboards/service/dashboard_service_test.go index c00885bdc9a..8fa4453d7c7 100644 --- a/pkg/services/dashboards/service/dashboard_service_test.go +++ b/pkg/services/dashboards/service/dashboard_service_test.go @@ -2094,7 +2094,6 @@ func TestSetDefaultPermissionsAfterCreate(t *testing.T) { // Setup mocks and service dashboardStore := &dashboards.FakeDashboardStore{} - folderStore := foldertest.FakeFolderStore{} features := featuremgmt.WithFeatures() if tc.featureKubernetesDashboards { features = featuremgmt.WithFeatures(featuremgmt.FlagKubernetesDashboards) @@ -2107,7 +2106,6 @@ func TestSetDefaultPermissionsAfterCreate(t *testing.T) { cfg: setting.NewCfg(), log: log.New("test-logger"), dashboardStore: dashboardStore, - folderStore: &folderStore, features: features, dashboardPermissions: permService, folderPermissions: permService, diff --git a/pkg/services/folder/folderimpl/dashboard_folder_store.go b/pkg/services/folder/folderimpl/dashboard_folder_store.go index 7241d3485d3..3715bc7baeb 100644 --- a/pkg/services/folder/folderimpl/dashboard_folder_store.go +++ b/pkg/services/folder/folderimpl/dashboard_folder_store.go @@ -17,7 +17,7 @@ type DashboardFolderStoreImpl struct { store db.DB } -func ProvideDashboardFolderStore(sqlStore db.DB) *DashboardFolderStoreImpl { +func newDashboardFolderStore(sqlStore db.DB) *DashboardFolderStoreImpl { return &DashboardFolderStoreImpl{store: sqlStore} } diff --git a/pkg/services/folder/folderimpl/dashboard_folder_store_test.go b/pkg/services/folder/folderimpl/dashboard_folder_store_test.go index e7bdaa6c5a3..3954c13d127 100644 --- a/pkg/services/folder/folderimpl/dashboard_folder_store_test.go +++ b/pkg/services/folder/folderimpl/dashboard_folder_store_test.go @@ -44,7 +44,7 @@ func TestIntegrationDashboardFolderStore(t *testing.T) { setup() var orgId int64 = 1 sqlStore := db.InitTestDB(t) - folderStore := ProvideDashboardFolderStore(sqlStore) + folderStore := newDashboardFolderStore(sqlStore) folder := insertTestFolder(t, dashboardStore, "TEST", orgId, "", "prod") dash := insertTestDashboard(t, dashboardStore, "Very Unique Name", orgId, folder.ID, folder.UID, "prod") @@ -69,7 +69,7 @@ func TestIntegrationDashboardFolderStore(t *testing.T) { setup() var orgId int64 = 1 sqlStore := db.InitTestDB(t) - folderStore := ProvideDashboardFolderStore(sqlStore) + folderStore := newDashboardFolderStore(sqlStore) folder := insertTestFolder(t, dashboardStore, "TEST", orgId, "", "prod") dash := insertTestDashboard(t, dashboardStore, "Very Unique Name", orgId, folder.ID, folder.UID, "prod") @@ -122,7 +122,7 @@ func TestIntegrationGetDashFolderStore(t *testing.T) { folderStore := ProvideStore(db) dashboardStore, err := database.ProvideDashboardStore(db, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(db)) require.NoError(t, err) - dashFolderStore := ProvideDashboardFolderStore(db) + dashFolderStore := newDashboardFolderStore(db) orgID := CreateOrg(t, db, cfg) diff --git a/pkg/services/folder/folderimpl/folder.go b/pkg/services/folder/folderimpl/folder.go index 73a0ec242cc..4a872f45eb8 100644 --- a/pkg/services/folder/folderimpl/folder.go +++ b/pkg/services/folder/folderimpl/folder.go @@ -17,7 +17,6 @@ import ( "golang.org/x/exp/slices" "github.com/grafana/dskit/concurrency" - dashboardv1 "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v1beta1" folderv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" "github.com/grafana/grafana/pkg/apimachinery/identity" @@ -50,13 +49,18 @@ import ( const FULLPATH_SEPARATOR = "/" +var ( + _ folder.LegacyService = (*Service)(nil) + _ folder.Service = (*Service)(nil) +) + type Service struct { store folder.Store unifiedStore folder.Store db db.DB log *slog.Logger - dashboardStore dashboards.Store - dashboardFolderStore folder.FolderStore + dashboardStore dashboards.Store // folders are saved in the dashboard table + dashboardFolderStore *DashboardFolderStoreImpl features featuremgmt.FeatureToggles accessControl accesscontrol.AccessControl k8sclient client.K8sHandler @@ -77,7 +81,6 @@ func ProvideService( ac accesscontrol.AccessControl, bus bus.Bus, dashboardStore dashboards.Store, - folderStore folder.FolderStore, userService user.Service, db db.DB, // DB for the (new) nested folder store features featuremgmt.FeatureToggles, @@ -94,7 +97,7 @@ func ProvideService( srv := &Service{ log: slog.Default().With("logger", "folder-service"), dashboardStore: dashboardStore, - dashboardFolderStore: folderStore, + dashboardFolderStore: newDashboardFolderStore(db), store: store, features: features, accessControl: ac, @@ -109,7 +112,7 @@ func ProvideService( supportBundles.RegisterSupportItemCollector(srv.supportBundleCollector()) - ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(folderStore, srv)) + ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(srv.getUIDFromLegacyID, srv)) ac.RegisterScopeAttributeResolver(dashboards.NewFolderUIDScopeResolver(srv)) k8sHandler := client.NewK8sHandler( @@ -194,6 +197,14 @@ func (s *Service) DBMigration(db db.DB) { s.log.Debug("syncing dashboard and folder tables finished") } +func (s *Service) getUIDFromLegacyID(ctx context.Context, orgID int64, id int64) (string, error) { + f, err := s.dashboardFolderStore.GetFolderByID(ctx, orgID, id) + if err != nil { + return "", err + } + return f.UID, nil +} + func (s *Service) CountFoldersInOrg(ctx context.Context, orgID int64) (int64, error) { ctx, span := s.tracer.Start(ctx, "folder.CountFoldersInOrg") defer span.End() @@ -315,7 +326,7 @@ func (s *Service) setFullpath(ctx context.Context, f *folder.Folder, forceLegacy var parents []*folder.Folder var err error if forceLegacy { - parents, err = s.GetParentsLegacy(ctx, folder.GetParentsQuery{ + parents, err = s.getParentsLegacy(ctx, folder.GetParentsQuery{ UID: f.UID, OrgID: f.OrgID, }) @@ -340,8 +351,8 @@ func (s *Service) GetChildren(ctx context.Context, q *folder.GetChildrenQuery) ( return s.getChildrenFromApiServer(ctx, q) } -func (s *Service) GetChildrenLegacy(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) { - ctx, span := s.tracer.Start(ctx, "folder.GetChildrenLegacy") +func (s *Service) getChildrenLegacy(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) { + ctx, span := s.tracer.Start(ctx, "folder.getChildrenLegacy") defer span.End() defer func(t time.Time) { parent := q.UID @@ -493,7 +504,7 @@ func (s *Service) GetSharedWithMe(ctx context.Context, q *folder.GetChildrenQuer } var rootFolders []*folder.FolderReference if forceLegacy { - rootFolders, err = s.GetChildrenLegacy(ctx, &folder.GetChildrenQuery{UID: "", OrgID: q.OrgID, SignedInUser: q.SignedInUser, Permission: q.Permission}) + rootFolders, err = s.getChildrenLegacy(ctx, &folder.GetChildrenQuery{UID: "", OrgID: q.OrgID, SignedInUser: q.SignedInUser, Permission: q.Permission}) } else { rootFolders, err = s.GetChildren(ctx, &folder.GetChildrenQuery{UID: "", OrgID: q.OrgID, SignedInUser: q.SignedInUser, Permission: q.Permission}) } @@ -620,8 +631,8 @@ func (s *Service) GetParents(ctx context.Context, q folder.GetParentsQuery) ([]* return s.getParentsFromApiServer(ctx, q) } -func (s *Service) GetParentsLegacy(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { - ctx, span := s.tracer.Start(ctx, "folder.GetParentsLegacy") +func (s *Service) getParentsLegacy(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { + ctx, span := s.tracer.Start(ctx, "folder.getParentsLegacy") defer span.End() if q.UID == accesscontrol.GeneralFolderUID { return nil, nil @@ -1250,42 +1261,6 @@ func (s *Service) GetDescendantCounts(ctx context.Context, q *folder.GetDescenda return s.getDescendantCountsFromApiServer(ctx, q) } -func (s *Service) GetDescendantCountsLegacy(ctx context.Context, q *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) { - ctx, span := s.tracer.Start(ctx, "folder.GetDescendantCountsLegacy") - defer span.End() - if q.SignedInUser == nil { - return nil, folder.ErrBadRequest.Errorf("missing signed-in user") - } - if q.UID == nil || *q.UID == "" { - return nil, folder.ErrBadRequest.Errorf("missing UID") - } - if q.OrgID < 1 { - return nil, folder.ErrBadRequest.Errorf("invalid orgID") - } - - folders := []string{*q.UID} - countsMap := make(folder.DescendantCounts, len(s.registry)+1) - descendantFolders, err := s.store.GetDescendants(ctx, q.OrgID, *q.UID) - if err != nil { - s.log.ErrorContext(ctx, "failed to get descendant folders", "error", err) - return nil, err - } - for _, f := range descendantFolders { - folders = append(folders, f.UID) - } - countsMap[entity.StandardKindFolder] = int64(len(descendantFolders)) - - for _, v := range s.registry { - c, err := v.CountInFolders(ctx, q.OrgID, folders, q.SignedInUser) - if err != nil { - s.log.ErrorContext(ctx, "failed to count folder descendants", "error", err) - return nil, err - } - countsMap[v.Kind()] = c - } - return countsMap, nil -} - // buildSaveDashboardCommand is a simplified version on DashboardServiceImpl.buildSaveDashboardCommand // keeping only the meaningful functionality for folders func (s *Service) buildSaveDashboardCommand(ctx context.Context, dto *dashboards.SaveDashboardDTO) (*dashboards.SaveDashboardCommand, error) { diff --git a/pkg/services/folder/folderimpl/unifiedstore.go b/pkg/services/folder/folderimpl/unifiedstore.go index 6e2554a739c..8f062d722f9 100644 --- a/pkg/services/folder/folderimpl/unifiedstore.go +++ b/pkg/services/folder/folderimpl/unifiedstore.go @@ -12,12 +12,8 @@ import ( "k8s.io/apimachinery/pkg/selection" claims "github.com/grafana/authlib/types" - - "github.com/grafana/grafana/pkg/apimachinery/utils" - "github.com/grafana/grafana/pkg/storage/unified/resource" - "github.com/grafana/grafana/pkg/storage/unified/resourcepb" - folderv1 "github.com/grafana/grafana/apps/folder/pkg/apis/folder/v1beta1" + "github.com/grafana/grafana/pkg/apimachinery/utils" "github.com/grafana/grafana/pkg/infra/log" internalfolders "github.com/grafana/grafana/pkg/registry/apis/folders" "github.com/grafana/grafana/pkg/services/accesscontrol" @@ -26,6 +22,8 @@ import ( dashboardsearch "github.com/grafana/grafana/pkg/services/dashboards/service/search" "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/user" + "github.com/grafana/grafana/pkg/storage/unified/resource" + "github.com/grafana/grafana/pkg/storage/unified/resourcepb" "github.com/grafana/grafana/pkg/util" ) diff --git a/pkg/services/folder/foldertest/folder_store_mock.go b/pkg/services/folder/foldertest/folder_store_mock.go deleted file mode 100644 index 1a88e59c4e0..00000000000 --- a/pkg/services/folder/foldertest/folder_store_mock.go +++ /dev/null @@ -1,149 +0,0 @@ -// Code generated by mockery v2.53.4. DO NOT EDIT. - -package foldertest - -import ( - context "context" - - folder "github.com/grafana/grafana/pkg/services/folder" - mock "github.com/stretchr/testify/mock" -) - -// FakeFolderStore is an autogenerated mock type for the FolderStore type -type FakeFolderStore struct { - mock.Mock -} - -// Get provides a mock function with given fields: ctx, q -func (_m *FakeFolderStore) Get(ctx context.Context, q folder.GetFolderQuery) (*folder.Folder, error) { - ret := _m.Called(ctx, q) - - if len(ret) == 0 { - panic("no return value specified for Get") - } - - var r0 *folder.Folder - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, folder.GetFolderQuery) (*folder.Folder, error)); ok { - return rf(ctx, q) - } - if rf, ok := ret.Get(0).(func(context.Context, folder.GetFolderQuery) *folder.Folder); ok { - r0 = rf(ctx, q) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*folder.Folder) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, folder.GetFolderQuery) error); ok { - r1 = rf(ctx, q) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetFolderByID provides a mock function with given fields: ctx, orgID, id -func (_m *FakeFolderStore) GetFolderByID(ctx context.Context, orgID int64, id int64) (*folder.Folder, error) { - ret := _m.Called(ctx, orgID, id) - - if len(ret) == 0 { - panic("no return value specified for GetFolderByID") - } - - var r0 *folder.Folder - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, int64) (*folder.Folder, error)); ok { - return rf(ctx, orgID, id) - } - if rf, ok := ret.Get(0).(func(context.Context, int64, int64) *folder.Folder); ok { - r0 = rf(ctx, orgID, id) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*folder.Folder) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, int64, int64) error); ok { - r1 = rf(ctx, orgID, id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetFolderByUID provides a mock function with given fields: ctx, orgID, uid -func (_m *FakeFolderStore) GetFolderByUID(ctx context.Context, orgID int64, uid string) (*folder.Folder, error) { - ret := _m.Called(ctx, orgID, uid) - - if len(ret) == 0 { - panic("no return value specified for GetFolderByUID") - } - - var r0 *folder.Folder - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, string) (*folder.Folder, error)); ok { - return rf(ctx, orgID, uid) - } - if rf, ok := ret.Get(0).(func(context.Context, int64, string) *folder.Folder); ok { - r0 = rf(ctx, orgID, uid) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*folder.Folder) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok { - r1 = rf(ctx, orgID, uid) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetFolders provides a mock function with given fields: ctx, orgID, uids -func (_m *FakeFolderStore) GetFolders(ctx context.Context, orgID int64, uids []string) (map[string]*folder.Folder, error) { - ret := _m.Called(ctx, orgID, uids) - - if len(ret) == 0 { - panic("no return value specified for GetFolders") - } - - var r0 map[string]*folder.Folder - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, []string) (map[string]*folder.Folder, error)); ok { - return rf(ctx, orgID, uids) - } - if rf, ok := ret.Get(0).(func(context.Context, int64, []string) map[string]*folder.Folder); ok { - r0 = rf(ctx, orgID, uids) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]*folder.Folder) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, int64, []string) error); ok { - r1 = rf(ctx, orgID, uids) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewFakeFolderStore creates a new instance of FakeFolderStore. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewFakeFolderStore(t interface { - mock.TestingT - Cleanup(func()) -}) *FakeFolderStore { - mock := &FakeFolderStore{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/services/folder/foldertest/foldertest.go b/pkg/services/folder/foldertest/foldertest.go index 35e55b26d0c..fff1237170a 100644 --- a/pkg/services/folder/foldertest/foldertest.go +++ b/pkg/services/folder/foldertest/foldertest.go @@ -59,17 +59,9 @@ func (s *FakeService) GetChildren(ctx context.Context, q *folder.GetChildrenQuer } return result, nil } -func (s *FakeService) GetChildrenLegacy(ctx context.Context, q *folder.GetChildrenQuery) ([]*folder.FolderReference, error) { - return s.ExpectedFoldersRef, s.ExpectedError -} - func (s *FakeService) GetParents(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { return s.ExpectedFolders, s.ExpectedError } -func (s *FakeService) GetParentsLegacy(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { - return s.ExpectedFolders, s.ExpectedError -} - func (s *FakeService) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) { return s.ExpectedFolder, s.ExpectedError } @@ -117,9 +109,6 @@ func (s *FakeService) RegisterService(service folder.RegistryService) error { func (s *FakeService) GetDescendantCounts(ctx context.Context, q *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) { return s.ExpectedDescendantCounts, s.ExpectedError } -func (s *FakeService) GetDescendantCountsLegacy(ctx context.Context, q *folder.GetDescendantCountsQuery) (folder.DescendantCounts, error) { - return s.ExpectedDescendantCounts, s.ExpectedError -} func (s *FakeService) GetFolders(ctx context.Context, q folder.GetFoldersQuery) ([]*folder.Folder, error) { if s.foldersByUID != nil && len(q.UIDs) > 0 { diff --git a/pkg/services/folder/service.go b/pkg/services/folder/service.go index f68416ea95b..b3184dc65ec 100644 --- a/pkg/services/folder/service.go +++ b/pkg/services/folder/service.go @@ -6,11 +6,20 @@ import ( "github.com/grafana/grafana/pkg/services/search/model" ) +type LegacyService interface { + CreateLegacy(ctx context.Context, cmd *CreateFolderCommand) (*Folder, error) + GetLegacy(ctx context.Context, q *GetFolderQuery) (*Folder, error) + UpdateLegacy(ctx context.Context, cmd *UpdateFolderCommand) (*Folder, error) + DeleteLegacy(ctx context.Context, cmd *DeleteFolderCommand) error + MoveLegacy(ctx context.Context, cmd *MoveFolderCommand) (*Folder, error) + GetFoldersLegacy(ctx context.Context, q GetFoldersQuery) ([]*Folder, error) +} + +// The folder.Service is backed by calls forwarding to an apiserver type Service interface { RegisterService(service RegistryService) error Create(ctx context.Context, cmd *CreateFolderCommand) (*Folder, error) - CreateLegacy(ctx context.Context, cmd *CreateFolderCommand) (*Folder, error) // GetFolder takes a GetFolderCommand and returns a folder matching the // request. One of UID, ID or Title must be included. If multiple values @@ -20,19 +29,15 @@ type Service interface { // If ParentUID is not set then the folder will be fetched from the root level. // If WithFullpath is true it computes also the full path of a folder. Get(ctx context.Context, q *GetFolderQuery) (*Folder, error) - GetLegacy(ctx context.Context, q *GetFolderQuery) (*Folder, error) // Update is used to update a folder's UID, Title and Description. To change // a folder's parent folder, use Move. Update(ctx context.Context, cmd *UpdateFolderCommand) (*Folder, error) - UpdateLegacy(ctx context.Context, cmd *UpdateFolderCommand) (*Folder, error) Delete(ctx context.Context, cmd *DeleteFolderCommand) error - DeleteLegacy(ctx context.Context, cmd *DeleteFolderCommand) error // Move changes a folder's parent folder to the requested new parent. Move(ctx context.Context, cmd *MoveFolderCommand) (*Folder, error) - MoveLegacy(ctx context.Context, cmd *MoveFolderCommand) (*Folder, error) // GetFolders returns org folders that are accessible by the signed in user by their UIDs. // If WithFullpath is true it computes also the full path of a folder. @@ -40,36 +45,18 @@ type Service interface { // If a folder contains a slash in its title, it is escaped with a backslash. // If FullpathUIDs is true it computes a string that contains the UIDs of all parent folders separated by slash. GetFolders(ctx context.Context, q GetFoldersQuery) ([]*Folder, error) - GetFoldersLegacy(ctx context.Context, q GetFoldersQuery) ([]*Folder, error) // SearchFolders returns a list of folders that match the query. SearchFolders(ctx context.Context, q SearchFoldersQuery) (model.HitList, error) // GetChildren returns an array containing all child folders. GetChildren(ctx context.Context, q *GetChildrenQuery) ([]*FolderReference, error) - GetChildrenLegacy(ctx context.Context, q *GetChildrenQuery) ([]*FolderReference, error) // GetParents returns an array containing add parent folders if nested folders are enabled // otherwise it returns an empty array GetParents(ctx context.Context, q GetParentsQuery) ([]*Folder, error) - GetParentsLegacy(ctx context.Context, q GetParentsQuery) ([]*Folder, error) GetDescendantCounts(ctx context.Context, q *GetDescendantCountsQuery) (DescendantCounts, error) - GetDescendantCountsLegacy(ctx context.Context, q *GetDescendantCountsQuery) (DescendantCounts, error) CountFoldersInOrg(ctx context.Context, orgID int64) (int64, error) } - -// FolderStore is a folder store. -// -//go:generate mockery --name FolderStore --structname FakeFolderStore --outpkg foldertest --output foldertest --filename folder_store_mock.go -type FolderStore interface { - // Get joins on the dashboard and folder table to return all information needed for a folder - Get(ctx context.Context, q GetFolderQuery) (*Folder, error) - // GetFolderByUID retrieves a folder by its UID - GetFolderByUID(ctx context.Context, orgID int64, uid string) (*Folder, error) - // GetFolderByID retrieves a folder by its ID - GetFolderByID(ctx context.Context, orgID int64, id int64) (*Folder, error) - // GetFolders returns all folders for the given orgID and UIDs. - GetFolders(ctx context.Context, orgID int64, uids []string) (map[string]*Folder, error) -} diff --git a/pkg/services/ngalert/store/alert_rule_test.go b/pkg/services/ngalert/store/alert_rule_test.go index 739803e2836..ea6b339c6c6 100644 --- a/pkg/services/ngalert/store/alert_rule_test.go +++ b/pkg/services/ngalert/store/alert_rule_test.go @@ -25,7 +25,6 @@ import ( "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/folder" - "github.com/grafana/grafana/pkg/services/folder/folderimpl" "github.com/grafana/grafana/pkg/services/ngalert/testutil" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/user" @@ -1612,10 +1611,9 @@ func createRule(tb testing.TB, store *DBstore, generator *models.AlertRuleGenera func setupFolderService(t testing.TB, sqlStore db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles) folder.Service { tracer := tracing.InitializeTracerForTest() inProcBus := bus.ProvideBus(tracer) - folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) - _, dashboardStore := testutil.SetupDashboardService(t, sqlStore, folderStore, cfg) + _, dashboardStore := testutil.SetupDashboardService(t, sqlStore, cfg) - return testutil.SetupFolderService(t, cfg, sqlStore, dashboardStore, folderStore, inProcBus, features, &actest.FakeAccessControl{ExpectedEvaluate: true}) + return testutil.SetupFolderService(t, cfg, sqlStore, dashboardStore, inProcBus, features, &actest.FakeAccessControl{ExpectedEvaluate: true}) } func TestIntegration_AlertRuleVersionsCleanup(t *testing.T) { diff --git a/pkg/services/ngalert/testutil/testutil.go b/pkg/services/ngalert/testutil/testutil.go index fb68085a83c..e7cca7c2bba 100644 --- a/pkg/services/ngalert/testutil/testutil.go +++ b/pkg/services/ngalert/testutil/testutil.go @@ -34,14 +34,14 @@ import ( "github.com/grafana/grafana/pkg/storage/legacysql/dualwrite" ) -func SetupFolderService(tb testing.TB, cfg *setting.Cfg, db db.DB, dashboardStore dashboards.Store, folderStore *folderimpl.DashboardFolderStoreImpl, bus *bus.InProcBus, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl) folder.Service { +func SetupFolderService(tb testing.TB, cfg *setting.Cfg, db db.DB, dashboardStore dashboards.Store, bus *bus.InProcBus, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl) folder.Service { tb.Helper() fStore := folderimpl.ProvideStore(db) - return folderimpl.ProvideService(fStore, ac, bus, dashboardStore, folderStore, nil, db, + return folderimpl.ProvideService(fStore, ac, bus, dashboardStore, nil, db, features, supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), sort.ProvideService(), apiserver.WithoutRestConfig) } -func SetupDashboardService(tb testing.TB, sqlStore db.DB, fs *folderimpl.DashboardFolderStoreImpl, cfg *setting.Cfg) (*dashboardservice.DashboardServiceImpl, dashboards.Store) { +func SetupDashboardService(tb testing.TB, sqlStore db.DB, cfg *setting.Cfg) (*dashboardservice.DashboardServiceImpl, dashboards.Store) { tb.Helper() ac := acmock.New() @@ -58,7 +58,6 @@ func SetupDashboardService(tb testing.TB, sqlStore db.DB, fs *folderimpl.Dashboa dashboardService, err := dashboardservice.ProvideDashboardServiceImpl( cfg, dashboardStore, - fs, features, folderPermissions, ac, diff --git a/pkg/services/provisioning/dashboards/file_reader_test.go b/pkg/services/provisioning/dashboards/file_reader_test.go index 44a880caf45..798d6e62d5a 100644 --- a/pkg/services/provisioning/dashboards/file_reader_test.go +++ b/pkg/services/provisioning/dashboards/file_reader_test.go @@ -134,9 +134,8 @@ func TestIntegrationDashboardFileReader(t *testing.T) { tagService := tagimpl.ProvideService(sql) dashStore, err := database.ProvideDashboardStore(sql, cfgT, features, tagService) require.NoError(t, err) - folderStore := folderimpl.ProvideDashboardFolderStore(sql) folderSvc := folderimpl.ProvideService(fStore, actest.FakeAccessControl{}, bus.ProvideBus(tracing.InitializeTracerForTest()), - dashStore, folderStore, nil, sql, featuremgmt.WithFeatures(), + dashStore, nil, sql, featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, cfgT, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), sort.ProvideService(), apiserver.WithoutRestConfig) t.Run("Reading dashboards from disk", func(t *testing.T) { diff --git a/pkg/services/provisioning/dashboards/validator_test.go b/pkg/services/provisioning/dashboards/validator_test.go index 91227110dda..e5346bed303 100644 --- a/pkg/services/provisioning/dashboards/validator_test.go +++ b/pkg/services/provisioning/dashboards/validator_test.go @@ -53,9 +53,8 @@ func TestIntegrationDuplicatesValidator(t *testing.T) { tagService := tagimpl.ProvideService(sql) dashStore, err := database.ProvideDashboardStore(sql, cfgT, features, tagService) require.NoError(t, err) - folderStore := folderimpl.ProvideDashboardFolderStore(sql) folderSvc := folderimpl.ProvideService(fStore, actest.FakeAccessControl{}, bus.ProvideBus(tracing.InitializeTracerForTest()), - dashStore, folderStore, nil, sql, featuremgmt.WithFeatures(), + dashStore, nil, sql, featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, cfgT, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), grafanasort.ProvideService(), apiserver.WithoutRestConfig) t.Run("Duplicates validator should collect info about duplicate UIDs and titles within folders", func(t *testing.T) { diff --git a/pkg/services/quota/quotaimpl/quota_test.go b/pkg/services/quota/quotaimpl/quota_test.go index 55f259be54b..0e7ebaaf142 100644 --- a/pkg/services/quota/quotaimpl/quota_test.go +++ b/pkg/services/quota/quotaimpl/quota_test.go @@ -502,20 +502,18 @@ func setupEnv(t *testing.T, sqlStore db.DB, cfg *setting.Cfg, b bus.Bus, quotaSe require.NoError(t, err) _, err = authimpl.ProvideUserAuthTokenService(sqlStore, nil, quotaService, fakes.NewFakeSecretsService(), cfg, tracing.InitializeTracerForTest(), featuremgmt.WithFeatures()) require.NoError(t, err) - folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) fStore := folderimpl.ProvideStore(sqlStore) dashStore, err := dashboardStore.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore)) require.NoError(t, err) ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures()) folderSvc := folderimpl.ProvideService( - fStore, acmock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore, + fStore, acmock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, nil, sqlStore, featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), sort.ProvideService(), apiserver.WithoutRestConfig) orgService, err := orgimpl.ProvideService(sqlStore, cfg, quotaService) require.NoError(t, err) dashService, err := dashService.ProvideDashboardServiceImpl( cfg, dashStore, - folderStore, featuremgmt.WithFeatures(), acmock.NewMockedPermissionsService(), ac, diff --git a/pkg/services/sqlstore/permissions/dashboards_bench_test.go b/pkg/services/sqlstore/permissions/dashboards_bench_test.go index 8f047d00a49..eb3dc8339c5 100644 --- a/pkg/services/sqlstore/permissions/dashboards_bench_test.go +++ b/pkg/services/sqlstore/permissions/dashboards_bench_test.go @@ -77,7 +77,7 @@ func setupBenchMark(b *testing.B, usr user.SignedInUser, features featuremgmt.Fe fStore := folderimpl.ProvideStore(store) folderSvc := folderimpl.ProvideService( - fStore, mock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(store), + fStore, mock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardWriteStore, nil, store, features, supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), sort.ProvideService(), apiserver.WithoutRestConfig) rootFolders := make([]*folder.Folder, 0, numFolders)