From ed75aea21dbccec4775da18ddea38d8aee7fb348 Mon Sep 17 00:00:00 2001 From: "Arati R." <33031346+suntala@users.noreply.github.com> Date: Mon, 30 Sep 2024 10:28:47 +0200 Subject: [PATCH] Folders: Export folder store implementation (#93897) * Export folder store implementation * Rename folder store * Add folder store as a parameter to folder service * Add folder store to dash service implementation * Fix folder store comments --- pkg/api/dashboard_test.go | 12 ++-- pkg/api/folder_bench_test.go | 9 +-- pkg/server/wire.go | 2 + .../annotationsimpl/annotations_test.go | 4 +- .../database/database_folder_test.go | 3 +- .../dashboards/database/database_test.go | 12 ++-- .../dashboards/service/dashboard_service.go | 2 +- .../dashboard_service_integration_test.go | 6 ++ .../service/service_test.go | 3 +- pkg/services/folder/folderimpl/folder.go | 14 ++-- pkg/services/folder/folderimpl/folder_test.go | 57 ++++++++-------- pkg/services/folder/folderimpl/sqlstore.go | 36 +++++----- .../folder/folderimpl/sqlstore_test.go | 22 +++---- pkg/services/folder/folderimpl/store_fake.go | 66 ------------------- pkg/services/folder/{folderimpl => }/store.go | 34 +++++----- pkg/services/folder/store_fake.go | 64 ++++++++++++++++++ .../libraryelements/libraryelements_test.go | 14 ++-- .../librarypanels/librarypanels_test.go | 25 ++++--- .../ngalert/api/api_provisioning_test.go | 4 +- .../ngalert/provisioning/alert_rules_test.go | 7 +- pkg/services/ngalert/testutil/testutil.go | 6 +- .../publicdashboards/api/query_test.go | 3 +- .../sqlstore/permissions/dashboard_test.go | 4 +- .../permissions/dashboards_bench_test.go | 4 +- 24 files changed, 226 insertions(+), 187 deletions(-) delete mode 100644 pkg/services/folder/folderimpl/store_fake.go rename pkg/services/folder/{folderimpl => }/store.go (59%) create mode 100644 pkg/services/folder/store_fake.go diff --git a/pkg/api/dashboard_test.go b/pkg/api/dashboard_test.go index ad246fec912..42bd4a84956 100644 --- a/pkg/api/dashboard_test.go +++ b/pkg/api/dashboard_test.go @@ -833,20 +833,22 @@ func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, pr folderPermissions := accesscontrolmock.NewMockedPermissionsService() dashboardPermissions := accesscontrolmock.NewMockedPermissionsService() - folderSvc := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), - dashboardStore, folderStore, db.InitTestDB(t), features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) - + db := db.InitTestDB(t) + fStore := folderimpl.ProvideStore(db) + folderSvc := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), + dashboardStore, folderStore, db, features, + supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) if dashboardService == nil { dashboardService, err = service.ProvideDashboardServiceImpl( cfg, dashboardStore, folderStore, features, folderPermissions, dashboardPermissions, - ac, folderSvc, nil, + ac, folderSvc, fStore, nil, ) require.NoError(t, err) } dashboardProvisioningService, err := service.ProvideDashboardServiceImpl( cfg, dashboardStore, folderStore, features, folderPermissions, dashboardPermissions, - ac, folderSvc, nil, + ac, folderSvc, fStore, nil, ) require.NoError(t, err) diff --git a/pkg/api/folder_bench_test.go b/pkg/api/folder_bench_test.go index 58b4b7040d1..3d5113c715c 100644 --- a/pkg/api/folder_bench_test.go +++ b/pkg/api/folder_bench_test.go @@ -457,18 +457,19 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog folderStore := folderimpl.ProvideDashboardFolderStore(sc.db) ac := acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient()) - folderServiceWithFlagOn := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderStore, sc.db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) - cfg := setting.NewCfg() actionSets := resourcepermissions.NewActionSetService(features) acSvc := acimpl.ProvideOSSService( sc.cfg, acdb.ProvideService(sc.db), actionSets, localcache.ProvideService(), features, tracing.InitializeTracerForTest(), zanzana.NewNoopClient(), sc.db, permreg.ProvidePermissionRegistry(), ) - + fStore := folderimpl.ProvideStore(sc.db) + folderServiceWithFlagOn := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, + folderStore, sc.db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) folderPermissions, err := ossaccesscontrol.ProvideFolderPermissions( cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets) require.NoError(b, err) + dashboardPermissions, err := ossaccesscontrol.ProvideDashboardPermissions( cfg, features, routing.NewRouteRegister(), sc.db, ac, license, &dashboards.FakeDashboardStore{}, folderServiceWithFlagOn, acSvc, sc.teamSvc, sc.userSvc, actionSets) require.NoError(b, err) @@ -476,7 +477,7 @@ func setupServer(b testing.TB, sc benchScenario, features featuremgmt.FeatureTog dashboardSvc, err := dashboardservice.ProvideDashboardServiceImpl( sc.cfg, dashStore, folderStore, features, folderPermissions, dashboardPermissions, ac, - folderServiceWithFlagOn, nil, + folderServiceWithFlagOn, fStore, nil, ) require.NoError(b, err) diff --git a/pkg/server/wire.go b/pkg/server/wire.go index f23c64fbb54..5549a7d5966 100644 --- a/pkg/server/wire.go +++ b/pkg/server/wire.go @@ -295,6 +295,8 @@ var wireBasicSet = wire.NewSet( dashboardservice.ProvideDashboardPluginService, dashboardstore.ProvideDashboardStore, folderimpl.ProvideService, + folderimpl.ProvideStore, + wire.Bind(new(folder.Store), new(*folderimpl.FolderStoreImpl)), folderimpl.ProvideDashboardFolderStore, wire.Bind(new(folder.FolderStore), new(*folderimpl.DashboardFolderStoreImpl)), dashboardimportservice.ProvideService, diff --git a/pkg/services/annotations/annotationsimpl/annotations_test.go b/pkg/services/annotations/annotationsimpl/annotations_test.go index 7a1223bfb64..4263acc340c 100644 --- a/pkg/services/annotations/annotationsimpl/annotations_test.go +++ b/pkg/services/annotations/annotationsimpl/annotations_test.go @@ -227,7 +227,9 @@ func TestIntegrationAnnotationListingWithInheritedRBAC(t *testing.T) { }) ac := acimpl.ProvideAccessControl(features, zanzana.NewNoopClient()) - folderSvc := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderimpl.ProvideDashboardFolderStore(sql), sql, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + fStore := folderimpl.ProvideStore(sql) + folderSvc := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, + folderimpl.ProvideDashboardFolderStore(sql), sql, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) cfg.AnnotationMaximumTagsLength = 60 diff --git a/pkg/services/dashboards/database/database_folder_test.go b/pkg/services/dashboards/database/database_folder_test.go index f654bc428e1..177f0ba3e52 100644 --- a/pkg/services/dashboards/database/database_folder_test.go +++ b/pkg/services/dashboards/database/database_folder_test.go @@ -303,7 +303,8 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) { guardian.New = origNewGuardian }) - folderSvc := folderimpl.ProvideService(mock.New(), bus.ProvideBus(tracer), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(sqlStore), sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + folderStore := folderimpl.ProvideStore(sqlStore) + folderSvc := folderimpl.ProvideService(folderStore, mock.New(), bus.ProvideBus(tracer), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(sqlStore), sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) parentUID := "" for i := 0; ; i++ { diff --git a/pkg/services/dashboards/database/database_test.go b/pkg/services/dashboards/database/database_test.go index 83c118d6047..73d85983569 100644 --- a/pkg/services/dashboards/database/database_test.go +++ b/pkg/services/dashboards/database/database_test.go @@ -830,7 +830,9 @@ func TestIntegrationFindDashboardsByTitle(t *testing.T) { ac := acimpl.ProvideAccessControl(features, zanzana.NewNoopClient()) folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) - folderServiceWithFlagOn := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + fStore := folderimpl.ProvideStore(sqlStore) + folderServiceWithFlagOn := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, + folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) user := &user.SignedInUser{ OrgID: 1, @@ -936,8 +938,7 @@ func TestIntegrationFindDashboardsByFolder(t *testing.T) { t.Skip("skipping integration test") } - sqlStore := db.InitTestDB(t) - cfg := setting.NewCfg() + sqlStore, cfg := db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPanelTitleSearch) dashboardStore, err := ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) @@ -948,7 +949,10 @@ func TestIntegrationFindDashboardsByFolder(t *testing.T) { ac := acimpl.ProvideAccessControl(features, zanzana.NewNoopClient()) folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) - folderServiceWithFlagOn := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + fStore := folderimpl.ProvideStore(sqlStore) + + folderServiceWithFlagOn := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, + folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) user := &user.SignedInUser{ OrgID: 1, diff --git a/pkg/services/dashboards/service/dashboard_service.go b/pkg/services/dashboards/service/dashboard_service.go index 34c400461c4..02a1934103a 100644 --- a/pkg/services/dashboards/service/dashboard_service.go +++ b/pkg/services/dashboards/service/dashboard_service.go @@ -66,7 +66,7 @@ func ProvideDashboardServiceImpl( cfg *setting.Cfg, dashboardStore dashboards.Store, folderStore folder.FolderStore, features featuremgmt.FeatureToggles, folderPermissionsService accesscontrol.FolderPermissionsService, dashboardPermissionsService accesscontrol.DashboardPermissionsService, ac accesscontrol.AccessControl, - folderSvc folder.Service, r prometheus.Registerer, + folderSvc folder.Service, fStore folder.Store, r prometheus.Registerer, ) (*DashboardServiceImpl, error) { dashSvc := &DashboardServiceImpl{ cfg: cfg, diff --git a/pkg/services/dashboards/service/dashboard_service_integration_test.go b/pkg/services/dashboards/service/dashboard_service_integration_test.go index c1fb4f426a0..775ae923aef 100644 --- a/pkg/services/dashboards/service/dashboard_service_integration_test.go +++ b/pkg/services/dashboards/service/dashboard_service_integration_test.go @@ -17,6 +17,7 @@ import ( "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/dashboards/database" "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/folder/foldertest" "github.com/grafana/grafana/pkg/services/guardian" @@ -874,6 +875,7 @@ func permissionScenario(t *testing.T, desc string, canSave bool, fn permissionSc dashboardPermissions, ac, foldertest.NewFakeService(), + folder.NewFakeStore(), nil, ) require.NoError(t, err) @@ -939,6 +941,7 @@ func callSaveWithResult(t *testing.T, cmd dashboards.SaveDashboardCommand, sqlSt dashboardPermissions, actest.FakeAccessControl{}, foldertest.NewFakeService(), + folder.NewFakeStore(), nil, ) require.NoError(t, err) @@ -963,6 +966,7 @@ func callSaveWithError(t *testing.T, cmd dashboards.SaveDashboardCommand, sqlSto accesscontrolmock.NewMockedPermissionsService(), actest.FakeAccessControl{}, foldertest.NewFakeService(), + folder.NewFakeStore(), nil, ) require.NoError(t, err) @@ -1006,6 +1010,7 @@ func saveTestDashboard(t *testing.T, title string, orgID int64, folderUID string dashboardPermissions, actest.FakeAccessControl{}, foldertest.NewFakeService(), + folder.NewFakeStore(), nil, ) require.NoError(t, err) @@ -1056,6 +1061,7 @@ func saveTestFolder(t *testing.T, title string, orgID int64, sqlStore db.DB) *da accesscontrolmock.NewMockedPermissionsService(), actest.FakeAccessControl{}, foldertest.NewFakeService(), + folder.NewFakeStore(), nil, ) require.NoError(t, err) diff --git a/pkg/services/dashboardsnapshots/service/service_test.go b/pkg/services/dashboardsnapshots/service/service_test.go index c2cdf73efad..c8fad1ad7d6 100644 --- a/pkg/services/dashboardsnapshots/service/service_test.go +++ b/pkg/services/dashboardsnapshots/service/service_test.go @@ -18,6 +18,7 @@ import ( "github.com/grafana/grafana/pkg/services/dashboardsnapshots" dashsnapdb "github.com/grafana/grafana/pkg/services/dashboardsnapshots/database" "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/folder/foldertest" "github.com/grafana/grafana/pkg/services/quota/quotatest" @@ -98,7 +99,7 @@ func TestValidateDashboardExists(t *testing.T) { secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(sqlStore)) dashboardStore, err := dashdb.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil)) require.NoError(t, err) - dashSvc, err := dashsvc.ProvideDashboardServiceImpl(cfg, dashboardStore, folderimpl.ProvideDashboardFolderStore(sqlStore), nil, nil, nil, acmock.New(), foldertest.NewFakeService(), nil) + dashSvc, err := dashsvc.ProvideDashboardServiceImpl(cfg, dashboardStore, folderimpl.ProvideDashboardFolderStore(sqlStore), nil, nil, nil, acmock.New(), foldertest.NewFakeService(), folder.NewFakeStore(), nil) require.NoError(t, err) s := ProvideService(dsStore, secretsService, dashSvc) ctx := context.Background() diff --git a/pkg/services/folder/folderimpl/folder.go b/pkg/services/folder/folderimpl/folder.go index 48cc32b7b76..c87c7505c73 100644 --- a/pkg/services/folder/folderimpl/folder.go +++ b/pkg/services/folder/folderimpl/folder.go @@ -40,7 +40,7 @@ import ( const FULLPATH_SEPARATOR = "/" type Service struct { - store store + store folder.Store db db.DB log *slog.Logger dashboardStore dashboards.Store @@ -58,6 +58,7 @@ type Service struct { } func ProvideService( + store *FolderStoreImpl, ac accesscontrol.AccessControl, bus bus.Bus, dashboardStore dashboards.Store, @@ -68,7 +69,6 @@ func ProvideService( r prometheus.Registerer, tracer tracing.Tracer, ) folder.Service { - store := ProvideStore(db) srv := &Service{ log: slog.Default().With("logger", "folder-service"), dashboardStore: dashboardStore, @@ -143,10 +143,10 @@ func (s *Service) GetFolders(ctx context.Context, q folder.GetFoldersQuery) ([]* return nil, folder.ErrBadRequest.Errorf("missing signed in user") } - qry := NewGetFoldersQuery(q) + qry := folder.NewGetFoldersQuery(q) permissions := q.SignedInUser.GetPermissions() folderPermissions := permissions[dashboards.ActionFoldersRead] - qry.ancestorUIDs = make([]string, 0, len(folderPermissions)) + qry.AncestorUIDs = make([]string, 0, len(folderPermissions)) if len(folderPermissions) == 0 && !q.SignedInUser.GetIsGrafanaAdmin() { return nil, nil } @@ -154,12 +154,12 @@ func (s *Service) GetFolders(ctx context.Context, q folder.GetFoldersQuery) ([]* if p == dashboards.ScopeFoldersAll { // no need to query for folders with permissions // the user has permission to access all folders - qry.ancestorUIDs = nil + qry.AncestorUIDs = nil break } if folderUid, found := strings.CutPrefix(p, dashboards.ScopeFoldersPrefix); found { - if !slices.Contains(qry.ancestorUIDs, folderUid) { - qry.ancestorUIDs = append(qry.ancestorUIDs, folderUid) + if !slices.Contains(qry.AncestorUIDs, folderUid) { + qry.AncestorUIDs = append(qry.AncestorUIDs, folderUid) } } } diff --git a/pkg/services/folder/folderimpl/folder_test.go b/pkg/services/folder/folderimpl/folder_test.go index 7ad8b4b8235..2e5260fc594 100644 --- a/pkg/services/folder/folderimpl/folder_test.go +++ b/pkg/services/folder/folderimpl/folder_test.go @@ -62,8 +62,10 @@ func TestIntegrationProvideFolderService(t *testing.T) { } t.Run("should register scope resolvers", func(t *testing.T) { ac := acmock.New() - db := db.InitTestDB(t) - ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), nil, nil, db, featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + db, _ := db.InitTestDBWithCfg(t) + store := ProvideStore(db) + ProvideService(store, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), nil, nil, db, + featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) require.Len(t, ac.Calls.RegisterAttributeScopeResolver, 3) }) @@ -486,7 +488,7 @@ func TestIntegrationNestedFolderService(t *testing.T) { CanEditValue: true, }) - dashSrv, err := dashboardservice.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, featuresFlagOn, folderPermissions, dashboardPermissions, ac, serviceWithFlagOn, nil) + dashSrv, err := dashboardservice.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, featuresFlagOn, folderPermissions, dashboardPermissions, ac, serviceWithFlagOn, nestedFolderStore, nil) require.NoError(t, err) alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOn, db, serviceWithFlagOn, dashSrv, ac) @@ -568,7 +570,7 @@ func TestIntegrationNestedFolderService(t *testing.T) { }) dashSrv, err := dashboardservice.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, featuresFlagOff, - folderPermissions, dashboardPermissions, ac, serviceWithFlagOff, nil) + folderPermissions, dashboardPermissions, ac, serviceWithFlagOff, nestedFolderStore, nil) require.NoError(t, err) alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOff, db, serviceWithFlagOff, dashSrv, ac) @@ -713,7 +715,7 @@ func TestIntegrationNestedFolderService(t *testing.T) { tc.service.dashboardStore = dashStore tc.service.store = nestedFolderStore - dashSrv, err := dashboardservice.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, tc.featuresFlag, folderPermissions, dashboardPermissions, ac, tc.service, nil) + dashSrv, err := dashboardservice.ProvideDashboardServiceImpl(cfg, dashStore, folderStore, tc.featuresFlag, folderPermissions, dashboardPermissions, ac, tc.service, tc.service.store, nil) require.NoError(t, err) alertStore, err := ngstore.ProvideDBStore(cfg, tc.featuresFlag, db, tc.service, dashSrv, ac) require.NoError(t, err) @@ -792,7 +794,7 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) { guardian.New = g }) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() dashStore := dashboards.FakeDashboardStore{} dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*dashboards.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil) @@ -906,7 +908,7 @@ func TestNestedFolderService(t *testing.T) { dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() features := featuremgmt.WithFeatures() db, _ := sqlstore.InitTestDB(t) @@ -944,7 +946,7 @@ func TestNestedFolderService(t *testing.T) { dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(dash, nil) dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() features := featuremgmt.WithFeatures("nestedFolders") tempUser := &user.SignedInUser{UserID: 1, OrgID: orgID, Permissions: map[int64]map[string][]string{}} @@ -974,7 +976,7 @@ func TestNestedFolderService(t *testing.T) { dashStore := &dashboards.FakeDashboardStore{} dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() features := featuremgmt.WithFeatures("nestedFolders") tempUser := &user.SignedInUser{UserID: 1, OrgID: orgID, Permissions: map[int64]map[string][]string{}} @@ -1044,7 +1046,7 @@ func TestNestedFolderService(t *testing.T) { nestedFolderUser := &user.SignedInUser{UserID: 1, OrgID: orgID, Permissions: map[int64]map[string][]string{}} nestedFolderUser.Permissions[orgID] = map[string][]string{dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("some_parent")}} - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() db, _ := sqlstore.InitTestDB(t) features := featuremgmt.WithFeatures("nestedFolders") folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, features, acimpl.ProvideAccessControl(features, zanzana.NewNoopClient()), db) @@ -1085,7 +1087,7 @@ func TestNestedFolderService(t *testing.T) { dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(&dashboards.Dashboard{UID: "newUID"}, nil) dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() db, _ := sqlstore.InitTestDB(t) folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{ @@ -1122,7 +1124,7 @@ func TestNestedFolderService(t *testing.T) { dashboardFolderStore := foldertest.NewFakeFolderStore(t) dashboardFolderStore.On("GetFolderByUID", mock.Anything, orgID, dashboardFolder.UID).Return(f, nil) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedParentFolders = []*folder.Folder{ {UID: "newFolder", ParentUID: "newFolder"}, {UID: "newFolder2", ParentUID: "newFolder2"}, @@ -1164,7 +1166,7 @@ func TestNestedFolderService(t *testing.T) { dashboardFolderStore := foldertest.NewFakeFolderStore(t) // return an error from the folder store - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedError = errors.New("FAILED") // the service return success as long as the legacy create succeeds @@ -1189,7 +1191,7 @@ func TestNestedFolderService(t *testing.T) { dashboardFolderStore := foldertest.NewFakeFolderStore(t) //dashboardFolderStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"} nestedFolderUser := &user.SignedInUser{UserID: 1, OrgID: orgID, Permissions: map[int64]map[string][]string{}} @@ -1205,7 +1207,7 @@ func TestNestedFolderService(t *testing.T) { dashStore := &dashboards.FakeDashboardStore{} dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"} nestedFolderStore.ExpectedParentFolders = []*folder.Folder{ {UID: "newFolder", ParentUID: "newFolder"}, @@ -1236,7 +1238,7 @@ func TestNestedFolderService(t *testing.T) { nestedFolderUser.Permissions[orgID] = map[string][]string{dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceAllScope()}} features := featuremgmt.WithFeatures("nestedFolders") - folderSvc := setup(t, &dashboards.FakeDashboardStore{}, foldertest.NewFakeFolderStore(t), NewFakeStore(), features, acimpl.ProvideAccessControl(features, zanzana.NewNoopClient()), dbtest.NewFakeDB()) + folderSvc := setup(t, &dashboards.FakeDashboardStore{}, foldertest.NewFakeFolderStore(t), folder.NewFakeStore(), features, acimpl.ProvideAccessControl(features, zanzana.NewNoopClient()), dbtest.NewFakeDB()) _, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: accesscontrol.K6FolderUID, NewParentUID: "newFolder", OrgID: orgID, SignedInUser: nestedFolderUser}) require.Error(t, err, folder.ErrBadRequest) }) @@ -1246,7 +1248,7 @@ func TestNestedFolderService(t *testing.T) { nestedFolderUser.Permissions[orgID] = map[string][]string{dashboards.ActionFoldersWrite: {dashboards.ScopeFoldersProvider.GetResourceAllScope()}} childUID := "k6-app-child" - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedFolder = &folder.Folder{ OrgID: orgID, UID: childUID, @@ -1263,7 +1265,7 @@ func TestNestedFolderService(t *testing.T) { dashStore := &dashboards.FakeDashboardStore{} dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"} nestedFolderUser := &user.SignedInUser{UserID: 1, OrgID: orgID, Permissions: map[int64]map[string][]string{}} @@ -1279,7 +1281,7 @@ func TestNestedFolderService(t *testing.T) { dashStore := &dashboards.FakeDashboardStore{} dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"} nestedFolderStore.ExpectedParentFolders = []*folder.Folder{ {UID: "newFolder", ParentUID: "newFolder"}, @@ -1307,7 +1309,7 @@ func TestNestedFolderService(t *testing.T) { dashStore := &dashboards.FakeDashboardStore{} dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderUser := &user.SignedInUser{UserID: 1, OrgID: orgID, Permissions: map[int64]map[string][]string{}} nestedFolderUser.Permissions[orgID] = map[string][]string{dashboards.ActionFoldersCreate: {dashboards.ScopeFoldersProvider.GetResourceScopeUID("some_subfolder")}} @@ -1328,7 +1330,7 @@ func TestNestedFolderService(t *testing.T) { dashStore := &dashboards.FakeDashboardStore{} dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"} nestedFolderStore.ExpectedError = folder.ErrCircularReference @@ -1350,7 +1352,7 @@ func TestNestedFolderService(t *testing.T) { dashStore := &dashboards.FakeDashboardStore{} dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"} nestedFolderStore.ExpectedParentFolders = []*folder.Folder{ {UID: "newFolder", ParentUID: "newFolder"}, @@ -1376,7 +1378,7 @@ func TestNestedFolderService(t *testing.T) { dashStore := &dashboards.FakeDashboardStore{} dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"} nestedFolderStore.ExpectedParentFolders = []*folder.Folder{{UID: "myFolder", ParentUID: "12345"}, {UID: "12345", ParentUID: ""}} @@ -1409,7 +1411,7 @@ func TestNestedFolderService(t *testing.T) { parents = append(parents, &folder.Folder{UID: fmt.Sprintf("folder%d", i)}) } - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() //nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"} nestedFolderStore.ExpectedParentFolders = parents @@ -1439,7 +1441,7 @@ func TestNestedFolderService(t *testing.T) { dashboardFolderStore := foldertest.NewFakeFolderStore(t) - nestedFolderStore := NewFakeStore() + nestedFolderStore := folder.NewFakeStore() nestedFolderStore.ExpectedError = folder.ErrFolderNotFound folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{ @@ -1493,6 +1495,7 @@ func TestIntegrationNestedFolderSharedWithMe(t *testing.T) { dashboardPermissions, actest.FakeAccessControl{}, serviceWithFlagOn, + nestedFolderStore, nil, ) require.NoError(t, err) @@ -2496,7 +2499,7 @@ func TestSupportBundle(t *testing.T) { } } -func CreateSubtreeInStore(t *testing.T, store store, service *Service, depth int, prefix string, cmd folder.CreateFolderCommand) []*folder.Folder { +func CreateSubtreeInStore(t *testing.T, store folder.Store, service *Service, depth int, prefix string, cmd folder.CreateFolderCommand) []*folder.Folder { t.Helper() folders := make([]*folder.Folder, 0, depth) @@ -2520,7 +2523,7 @@ func CreateSubtreeInStore(t *testing.T, store store, service *Service, depth int return folders } -func setup(t *testing.T, dashStore dashboards.Store, dashboardFolderStore folder.FolderStore, nestedFolderStore store, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl, db db.DB) folder.Service { +func setup(t *testing.T, dashStore dashboards.Store, dashboardFolderStore folder.FolderStore, nestedFolderStore folder.Store, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl, db db.DB) folder.Service { t.Helper() // nothing enabled yet diff --git a/pkg/services/folder/folderimpl/sqlstore.go b/pkg/services/folder/folderimpl/sqlstore.go index c4464087840..2e085fddccd 100644 --- a/pkg/services/folder/folderimpl/sqlstore.go +++ b/pkg/services/folder/folderimpl/sqlstore.go @@ -22,19 +22,19 @@ import ( const DEFAULT_BATCH_SIZE = 999 -type sqlStore struct { +type FolderStoreImpl struct { db db.DB log log.Logger } // sqlStore implements the store interface. -var _ store = (*sqlStore)(nil) +var _ folder.Store = (*FolderStoreImpl)(nil) -func ProvideStore(db db.DB) *sqlStore { - return &sqlStore{db: db, log: log.New("folder-store")} +func ProvideStore(db db.DB) *FolderStoreImpl { + return &FolderStoreImpl{db: db, log: log.New("folder-store")} } -func (ss *sqlStore) Create(ctx context.Context, cmd folder.CreateFolderCommand) (*folder.Folder, error) { +func (ss *FolderStoreImpl) Create(ctx context.Context, cmd folder.CreateFolderCommand) (*folder.Folder, error) { if cmd.UID == "" { return nil, folder.ErrBadRequest.Errorf("missing UID") } @@ -83,7 +83,7 @@ func (ss *sqlStore) Create(ctx context.Context, cmd folder.CreateFolderCommand) return foldr.WithURL(), err } -func (ss *sqlStore) Delete(ctx context.Context, UIDs []string, orgID int64) error { +func (ss *FolderStoreImpl) Delete(ctx context.Context, UIDs []string, orgID int64) error { if len(UIDs) == 0 { return nil } @@ -103,7 +103,7 @@ func (ss *sqlStore) Delete(ctx context.Context, UIDs []string, orgID int64) erro }) } -func (ss *sqlStore) Update(ctx context.Context, cmd folder.UpdateFolderCommand) (*folder.Folder, error) { +func (ss *FolderStoreImpl) Update(ctx context.Context, cmd folder.UpdateFolderCommand) (*folder.Folder, error) { updated := time.Now() uid := cmd.UID @@ -191,7 +191,7 @@ func (ss *sqlStore) Update(ctx context.Context, cmd folder.UpdateFolderCommand) // └── B/C // // The full path of C is "A/B\/C". -func (ss *sqlStore) Get(ctx context.Context, q folder.GetFolderQuery) (*folder.Folder, error) { +func (ss *FolderStoreImpl) Get(ctx context.Context, q folder.GetFolderQuery) (*folder.Folder, error) { foldr := &folder.Folder{} err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { exists := false @@ -244,7 +244,7 @@ func (ss *sqlStore) Get(ctx context.Context, q folder.GetFolderQuery) (*folder.F return foldr.WithURL(), err } -func (ss *sqlStore) GetParents(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { +func (ss *FolderStoreImpl) GetParents(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { if q.UID == "" { return []*folder.Folder{}, nil } @@ -295,7 +295,7 @@ func (ss *sqlStore) GetParents(ctx context.Context, q folder.GetParentsQuery) ([ return util.Reverse(folders[1:]), nil } -func (ss *sqlStore) GetChildren(ctx context.Context, q folder.GetChildrenQuery) ([]*folder.Folder, error) { +func (ss *FolderStoreImpl) GetChildren(ctx context.Context, q folder.GetChildrenQuery) ([]*folder.Folder, error) { var folders []*folder.Folder err := ss.db.WithDbSession(ctx, func(sess *db.Session) error { @@ -353,7 +353,7 @@ func (ss *sqlStore) GetChildren(ctx context.Context, q folder.GetChildrenQuery) return folders, err } -func (ss *sqlStore) getParentsMySQL(ctx context.Context, q folder.GetParentsQuery) (folders []*folder.Folder, err error) { +func (ss *FolderStoreImpl) getParentsMySQL(ctx context.Context, q folder.GetParentsQuery) (folders []*folder.Folder, err error) { err = ss.db.WithDbSession(ctx, func(sess *db.Session) error { uid := "" // covered by UQE_folder_org_id_uid @@ -387,7 +387,7 @@ func (ss *sqlStore) getParentsMySQL(ctx context.Context, q folder.GetParentsQuer } // TODO use a single query to get the height of a folder -func (ss *sqlStore) GetHeight(ctx context.Context, foldrUID string, orgID int64, parentUID *string) (int, error) { +func (ss *FolderStoreImpl) GetHeight(ctx context.Context, foldrUID string, orgID int64, parentUID *string) (int, error) { height := -1 queue := []string{foldrUID} for len(queue) > 0 && height <= folder.MaxNestedFolderDepth { @@ -445,7 +445,7 @@ func (ss *sqlStore) GetHeight(ctx context.Context, foldrUID string, orgID int64, // The full path UIDs of C is "uid1/uid2/uid3". // The full path UIDs of B is "uid1/uid2". // The full path UIDs of A is "uid1". -func (ss *sqlStore) GetFolders(ctx context.Context, q getFoldersQuery) ([]*folder.Folder, error) { +func (ss *FolderStoreImpl) GetFolders(ctx context.Context, q folder.GetFoldersFromStoreQuery) ([]*folder.Folder, error) { if q.BatchSize == 0 { q.BatchSize = DEFAULT_BATCH_SIZE } @@ -467,7 +467,7 @@ func (ss *sqlStore) GetFolders(ctx context.Context, q getFoldersQuery) ([]*folde } s.WriteString(` FROM folder f0`) // join the same table multiple times to compute the full path of a folder - if q.WithFullpath || q.WithFullpathUIDs || len(q.ancestorUIDs) > 0 { + if q.WithFullpath || q.WithFullpathUIDs || len(q.AncestorUIDs) > 0 { s.WriteString(getFullpathJoinsSQL()) } // covered by UQE_folder_org_id_uid @@ -489,7 +489,7 @@ func (ss *sqlStore) GetFolders(ctx context.Context, q getFoldersQuery) ([]*folde args = append(args, accesscontrol.K6FolderUID, accesscontrol.K6FolderUID) } - if len(q.ancestorUIDs) == 0 { + if len(q.AncestorUIDs) == 0 { if q.OrderByTitle { s.WriteString(` ORDER BY f0.title ASC`) } @@ -503,8 +503,8 @@ func (ss *sqlStore) GetFolders(ctx context.Context, q getFoldersQuery) ([]*folde } // filter out folders if they are not in the subtree of the given ancestor folders - if err := batch(len(q.ancestorUIDs), int(q.BatchSize), func(start2, end2 int) error { - s2, args2 := getAncestorsSQL(ss.db.GetDialect(), q.ancestorUIDs, start2, end2, s.String(), args) + if err := batch(len(q.AncestorUIDs), int(q.BatchSize), func(start2, end2 int) error { + s2, args2 := getAncestorsSQL(ss.db.GetDialect(), q.AncestorUIDs, start2, end2, s.String(), args) if q.OrderByTitle { s2 += " ORDER BY f0.title ASC" } @@ -533,7 +533,7 @@ func (ss *sqlStore) GetFolders(ctx context.Context, q getFoldersQuery) ([]*folde return folders, nil } -func (ss *sqlStore) GetDescendants(ctx context.Context, orgID int64, ancestor_uid string) ([]*folder.Folder, error) { +func (ss *FolderStoreImpl) GetDescendants(ctx context.Context, orgID int64, ancestor_uid string) ([]*folder.Folder, error) { var folders []*folder.Folder recursiveQueriesAreSupported, err := ss.db.RecursiveQueriesAreSupported() diff --git a/pkg/services/folder/folderimpl/sqlstore_test.go b/pkg/services/folder/folderimpl/sqlstore_test.go index c966bbf679b..dc60826d618 100644 --- a/pkg/services/folder/folderimpl/sqlstore_test.go +++ b/pkg/services/folder/folderimpl/sqlstore_test.go @@ -865,7 +865,7 @@ func TestIntegrationGetFolders(t *testing.T) { }) t.Run("get folders by UIDs should succeed", func(t *testing.T) { - actualFolders, err := folderStore.GetFolders(context.Background(), NewGetFoldersQuery(folder.GetFoldersQuery{OrgID: orgID, UIDs: uids[1:]})) + actualFolders, err := folderStore.GetFolders(context.Background(), folder.NewGetFoldersQuery(folder.GetFoldersQuery{OrgID: orgID, UIDs: uids[1:]})) require.NoError(t, err) assert.Equal(t, len(uids[1:]), len(actualFolders)) for _, f := range folders[1:] { @@ -885,7 +885,7 @@ func TestIntegrationGetFolders(t *testing.T) { }) t.Run("get folders by UIDs batching should work as expected", func(t *testing.T) { - q := NewGetFoldersQuery(folder.GetFoldersQuery{OrgID: orgID, UIDs: uids[1:], BatchSize: 3}) + q := folder.NewGetFoldersQuery(folder.GetFoldersQuery{OrgID: orgID, UIDs: uids[1:], BatchSize: 3}) actualFolders, err := folderStore.GetFolders(context.Background(), q) require.NoError(t, err) assert.Equal(t, len(uids[1:]), len(actualFolders)) @@ -906,7 +906,7 @@ func TestIntegrationGetFolders(t *testing.T) { }) t.Run("get folders by UIDs with fullpath should succeed", func(t *testing.T) { - q := NewGetFoldersQuery(folder.GetFoldersQuery{OrgID: orgID, UIDs: uids[1:], WithFullpath: true}) + q := folder.NewGetFoldersQuery(folder.GetFoldersQuery{OrgID: orgID, UIDs: uids[1:], WithFullpath: true}) q.BatchSize = 3 actualFolders, err := folderStore.GetFolders(context.Background(), q) require.NoError(t, err) @@ -929,12 +929,12 @@ func TestIntegrationGetFolders(t *testing.T) { }) t.Run("get folders by UIDs and ancestor UIDs should work as expected", func(t *testing.T) { - q := NewGetFoldersQuery(folder.GetFoldersQuery{OrgID: orgID, UIDs: uids[1:], BatchSize: 3}) - q.ancestorUIDs = make([]string, 0, int(q.BatchSize)+1) + q := folder.NewGetFoldersQuery(folder.GetFoldersQuery{OrgID: orgID, UIDs: uids[1:], BatchSize: 3}) + q.AncestorUIDs = make([]string, 0, int(q.BatchSize)+1) for i := 0; i < int(q.BatchSize); i++ { - q.ancestorUIDs = append(q.ancestorUIDs, uuid.New().String()) + q.AncestorUIDs = append(q.AncestorUIDs, uuid.New().String()) } - q.ancestorUIDs = append(q.ancestorUIDs, folders[len(folders)-1].UID) + q.AncestorUIDs = append(q.AncestorUIDs, folders[len(folders)-1].UID) actualFolders, err := folderStore.GetFolders(context.Background(), q) require.NoError(t, err) @@ -967,7 +967,7 @@ func CreateOrg(t *testing.T, db db.DB, cfg *setting.Cfg) int64 { return orgID } -func CreateSubtree(t *testing.T, store *sqlStore, orgID int64, parentUID string, depth int, prefix string) []string { +func CreateSubtree(t *testing.T, store *FolderStoreImpl, orgID int64, parentUID string, depth int, prefix string) []string { t.Helper() ancestorUIDs := []string{} @@ -1006,7 +1006,7 @@ func CreateSubtree(t *testing.T, store *sqlStore, orgID int64, parentUID string, return ancestorUIDs } -func CreateLeaves(t *testing.T, store *sqlStore, parent *folder.Folder, num int) []string { +func CreateLeaves(t *testing.T, store *FolderStoreImpl, parent *folder.Folder, num int) []string { t.Helper() leaves := make([]string, 0) @@ -1024,7 +1024,7 @@ func CreateLeaves(t *testing.T, store *sqlStore, parent *folder.Folder, num int) return leaves } -func assertAncestorUIDs(t *testing.T, store *sqlStore, f *folder.Folder, expected []string) { +func assertAncestorUIDs(t *testing.T, store *FolderStoreImpl, f *folder.Folder, expected []string) { t.Helper() ancestors, err := store.GetParents(context.Background(), folder.GetParentsQuery{ @@ -1039,7 +1039,7 @@ func assertAncestorUIDs(t *testing.T, store *sqlStore, f *folder.Folder, expecte assert.Equal(t, expected, actualAncestorsUIDs) } -func assertChildrenUIDs(t *testing.T, store *sqlStore, f *folder.Folder, expected []string) { +func assertChildrenUIDs(t *testing.T, store *FolderStoreImpl, f *folder.Folder, expected []string) { t.Helper() ancestors, err := store.GetChildren(context.Background(), folder.GetChildrenQuery{ diff --git a/pkg/services/folder/folderimpl/store_fake.go b/pkg/services/folder/folderimpl/store_fake.go deleted file mode 100644 index 33af4ebed09..00000000000 --- a/pkg/services/folder/folderimpl/store_fake.go +++ /dev/null @@ -1,66 +0,0 @@ -package folderimpl - -import ( - "context" - - "github.com/grafana/grafana/pkg/services/folder" -) - -type fakeStore struct { - ExpectedChildFolders []*folder.Folder - ExpectedParentFolders []*folder.Folder - ExpectedFolders []*folder.Folder - ExpectedFolder *folder.Folder - ExpectedError error - ExpectedFolderHeight int - CreateCalled bool - DeleteCalled bool -} - -func NewFakeStore() *fakeStore { - return &fakeStore{} -} - -var _ store = (*fakeStore)(nil) - -func (f *fakeStore) Create(ctx context.Context, cmd folder.CreateFolderCommand) (*folder.Folder, error) { - f.CreateCalled = true - return f.ExpectedFolder, f.ExpectedError -} - -func (f *fakeStore) Delete(ctx context.Context, UIDs []string, orgID int64) error { - f.DeleteCalled = true - return f.ExpectedError -} - -func (f *fakeStore) Update(ctx context.Context, cmd folder.UpdateFolderCommand) (*folder.Folder, error) { - return f.ExpectedFolder, f.ExpectedError -} - -func (f *fakeStore) Move(ctx context.Context, cmd folder.MoveFolderCommand) error { - return f.ExpectedError -} - -func (f *fakeStore) Get(ctx context.Context, cmd folder.GetFolderQuery) (*folder.Folder, error) { - return f.ExpectedFolder, f.ExpectedError -} - -func (f *fakeStore) GetParents(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) { - return f.ExpectedParentFolders, f.ExpectedError -} - -func (f *fakeStore) GetChildren(ctx context.Context, cmd folder.GetChildrenQuery) ([]*folder.Folder, error) { - return f.ExpectedChildFolders, f.ExpectedError -} - -func (f *fakeStore) GetHeight(ctx context.Context, folderUID string, orgID int64, parentUID *string) (int, error) { - return f.ExpectedFolderHeight, f.ExpectedError -} - -func (f *fakeStore) GetFolders(ctx context.Context, q getFoldersQuery) ([]*folder.Folder, error) { - return f.ExpectedFolders, f.ExpectedError -} - -func (f *fakeStore) GetDescendants(ctx context.Context, orgID int64, ancestor_uid string) ([]*folder.Folder, error) { - return f.ExpectedFolders, f.ExpectedError -} diff --git a/pkg/services/folder/folderimpl/store.go b/pkg/services/folder/store.go similarity index 59% rename from pkg/services/folder/folderimpl/store.go rename to pkg/services/folder/store.go index d2177ae4bfb..e2f17986221 100644 --- a/pkg/services/folder/folderimpl/store.go +++ b/pkg/services/folder/store.go @@ -1,27 +1,25 @@ -package folderimpl +package folder import ( "context" - - "github.com/grafana/grafana/pkg/services/folder" ) -type getFoldersQuery struct { - folder.GetFoldersQuery - ancestorUIDs []string +type GetFoldersFromStoreQuery struct { + GetFoldersQuery + AncestorUIDs []string } -func NewGetFoldersQuery(q folder.GetFoldersQuery) getFoldersQuery { - return getFoldersQuery{ +func NewGetFoldersQuery(q GetFoldersQuery) GetFoldersFromStoreQuery { + return GetFoldersFromStoreQuery{ GetFoldersQuery: q, - ancestorUIDs: []string{}, + AncestorUIDs: []string{}, } } -// store is the interface which a folder store must implement. -type store interface { +// Store is the interface which a folder Store must implement. +type Store interface { // Create creates a folder and returns the newly-created folder. - Create(ctx context.Context, cmd folder.CreateFolderCommand) (*folder.Folder, error) + Create(ctx context.Context, cmd CreateFolderCommand) (*Folder, error) // Delete folders with the specified UIDs and orgID from the folder store. Delete(ctx context.Context, UIDs []string, orgID int64) error @@ -30,24 +28,24 @@ type store interface { // If the NewParentUID field is not nil, it updates also the parent UID (move mode). // If it's a non empty string, it moves the folder under the folder with the specific UID // otherwise, it moves the folder under the root folder (parent_uid column is set to NULL). - Update(ctx context.Context, cmd folder.UpdateFolderCommand) (*folder.Folder, error) + Update(ctx context.Context, cmd UpdateFolderCommand) (*Folder, error) // Get returns a folder. - Get(ctx context.Context, q folder.GetFolderQuery) (*folder.Folder, error) + Get(ctx context.Context, q GetFolderQuery) (*Folder, error) // GetParents returns an ordered list of parent folder of the given folder. - GetParents(ctx context.Context, q folder.GetParentsQuery) ([]*folder.Folder, error) + GetParents(ctx context.Context, q GetParentsQuery) ([]*Folder, error) // GetChildren returns the set of immediate children folders (depth=1) of the // given folder. - GetChildren(ctx context.Context, q folder.GetChildrenQuery) ([]*folder.Folder, error) + GetChildren(ctx context.Context, q GetChildrenQuery) ([]*Folder, error) // GetHeight returns the height of the folder tree. When parentUID is set, the function would // verify in the meanwhile that parentUID is not present in the subtree of the folder with the given UID. GetHeight(ctx context.Context, foldrUID string, orgID int64, parentUID *string) (int, error) // GetFolders returns folders with given uids - GetFolders(ctx context.Context, q getFoldersQuery) ([]*folder.Folder, error) + GetFolders(ctx context.Context, q GetFoldersFromStoreQuery) ([]*Folder, error) // GetDescendants returns all descendants of a folder - GetDescendants(ctx context.Context, orgID int64, anchestor_uid string) ([]*folder.Folder, error) + GetDescendants(ctx context.Context, orgID int64, anchestor_uid string) ([]*Folder, error) } diff --git a/pkg/services/folder/store_fake.go b/pkg/services/folder/store_fake.go new file mode 100644 index 00000000000..79f1a1d6863 --- /dev/null +++ b/pkg/services/folder/store_fake.go @@ -0,0 +1,64 @@ +package folder + +import ( + "context" +) + +type fakeStore struct { + ExpectedChildFolders []*Folder + ExpectedParentFolders []*Folder + ExpectedFolders []*Folder + ExpectedFolder *Folder + ExpectedError error + ExpectedFolderHeight int + CreateCalled bool + DeleteCalled bool +} + +func NewFakeStore() *fakeStore { + return &fakeStore{} +} + +var _ Store = (*fakeStore)(nil) + +func (f *fakeStore) Create(ctx context.Context, cmd CreateFolderCommand) (*Folder, error) { + f.CreateCalled = true + return f.ExpectedFolder, f.ExpectedError +} + +func (f *fakeStore) Delete(ctx context.Context, UIDs []string, orgID int64) error { + f.DeleteCalled = true + return f.ExpectedError +} + +func (f *fakeStore) Update(ctx context.Context, cmd UpdateFolderCommand) (*Folder, error) { + return f.ExpectedFolder, f.ExpectedError +} + +func (f *fakeStore) Move(ctx context.Context, cmd MoveFolderCommand) error { + return f.ExpectedError +} + +func (f *fakeStore) Get(ctx context.Context, cmd GetFolderQuery) (*Folder, error) { + return f.ExpectedFolder, f.ExpectedError +} + +func (f *fakeStore) GetParents(ctx context.Context, q GetParentsQuery) ([]*Folder, error) { + return f.ExpectedParentFolders, f.ExpectedError +} + +func (f *fakeStore) GetChildren(ctx context.Context, cmd GetChildrenQuery) ([]*Folder, error) { + return f.ExpectedChildFolders, f.ExpectedError +} + +func (f *fakeStore) GetHeight(ctx context.Context, folderUID string, orgID int64, parentUID *string) (int, error) { + return f.ExpectedFolderHeight, f.ExpectedError +} + +func (f *fakeStore) GetFolders(ctx context.Context, q GetFoldersFromStoreQuery) ([]*Folder, error) { + return f.ExpectedFolders, f.ExpectedError +} + +func (f *fakeStore) GetDescendants(ctx context.Context, orgID int64, ancestor_uid string) ([]*Folder, error) { + return f.ExpectedFolders, f.ExpectedError +} diff --git a/pkg/services/libraryelements/libraryelements_test.go b/pkg/services/libraryelements/libraryelements_test.go index 1f5c22168ff..36bdf451541 100644 --- a/pkg/services/libraryelements/libraryelements_test.go +++ b/pkg/services/libraryelements/libraryelements_test.go @@ -308,6 +308,7 @@ func createDashboard(t *testing.T, sqlStore db.DB, user user.SignedInUser, dash cfg, dashboardStore, folderStore, features, folderPermissions, dashboardPermissions, ac, foldertest.NewFakeService(), + folder.NewFakeStore(), nil, ) require.NoError(t, err) @@ -328,7 +329,9 @@ func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder require.NoError(t, err) folderStore := folderimpl.ProvideDashboardFolderStore(sc.sqlStore) - s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sc.sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + store := folderimpl.ProvideStore(sc.sqlStore) + s := folderimpl.ProvideService(store, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sc.sqlStore, + features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) t.Logf("Creating folder with title and UID %q", title) ctx := identity.WithRequester(context.Background(), &sc.user) folder, err := s.Create(ctx, &folder.CreateFolderCommand{ @@ -391,7 +394,7 @@ func scenarioWithPanel(t *testing.T, desc string, fn func(t *testing.T, sc scena dashboardService, svcErr := dashboardservice.ProvideDashboardServiceImpl( cfg, dashboardStore, folderStore, features, folderPermissions, dashboardPermissions, ac, - foldertest.NewFakeService(), + foldertest.NewFakeService(), folder.NewFakeStore(), nil, ) require.NoError(t, svcErr) @@ -453,16 +456,19 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo dashService, dashSvcErr := dashboardservice.ProvideDashboardServiceImpl( cfg, dashboardStore, folderStore, features, folderPermissions, dashboardPermissions, ac, - foldertest.NewFakeService(), + foldertest.NewFakeService(), folder.NewFakeStore(), nil, ) require.NoError(t, dashSvcErr) guardian.InitAccessControlGuardian(cfg, ac, dashService) + fStore := folderimpl.ProvideStore(sqlStore) + folderSrv := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracer), dashboardStore, folderStore, sqlStore, + features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) service := LibraryElementService{ Cfg: cfg, features: featuremgmt.WithFeatures(), SQLStore: sqlStore, - folderService: folderimpl.ProvideService(ac, bus.ProvideBus(tracer), dashboardStore, folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()), + folderService: folderSrv, } // deliberate difference between signed in user and user in db to make it crystal clear diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index 89bcb12b3cb..8e571be20e2 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -732,7 +732,7 @@ func createDashboard(t *testing.T, sqlStore db.DB, user *user.SignedInUser, dash service, err := dashboardservice.ProvideDashboardServiceImpl( cfg, dashboardStore, folderStore, featuremgmt.WithFeatures(), acmock.NewMockedPermissionsService(), dashPermissionService, ac, - foldertest.NewFakeService(), + foldertest.NewFakeService(), folder.NewFakeStore(), nil, ) require.NoError(t, err) @@ -752,7 +752,9 @@ func createFolder(t *testing.T, sc scenarioContext, title string) *folder.Folder dashboardStore, err := database.ProvideDashboardStore(sc.sqlStore, cfg, features, tagimpl.ProvideService(sc.sqlStore), quotaService) require.NoError(t, err) folderStore := folderimpl.ProvideDashboardFolderStore(sc.sqlStore) - s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sc.sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + fStore := folderimpl.ProvideStore(sc.sqlStore) + s := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sc.sqlStore, + features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) t.Logf("Creating folder with title and UID %q", title) ctx := identity.WithRequester(context.Background(), sc.user) @@ -816,6 +818,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo role := org.RoleAdmin sqlStore, cfg := db.InitTestDBWithCfg(t) quotaService := quotatest.New(false, nil) + features := featuremgmt.WithFeatures() ac := actest.FakeAccessControl{ExpectedEvaluate: true} dashStore := &dashboards.FakeDashboardStore{} @@ -823,20 +826,22 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) dashPermissionService := acmock.NewMockedPermissionsService() dashService, err := dashboardservice.ProvideDashboardServiceImpl( - setting.NewCfg(), dashStore, folderStore, - featuremgmt.WithFeatures(), acmock.NewMockedPermissionsService(), dashPermissionService, ac, - foldertest.NewFakeService(), + cfg, dashStore, folderStore, + features, acmock.NewMockedPermissionsService(), dashPermissionService, ac, + foldertest.NewFakeService(), folder.NewFakeStore(), nil, ) require.NoError(t, err) - guardian.InitAccessControlGuardian(setting.NewCfg(), ac, dashService) + guardian.InitAccessControlGuardian(cfg, ac, dashService) - dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotaService) + dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore), quotaService) require.NoError(t, err) - features := featuremgmt.WithFeatures() - folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + fStore := folderimpl.ProvideStore(sqlStore) - elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService, featuremgmt.WithFeatures(), ac) + folderService := folderimpl.ProvideService(fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sqlStore, + features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + + elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService, features, ac) service := LibraryPanelService{ Cfg: cfg, SQLStore: sqlStore, diff --git a/pkg/services/ngalert/api/api_provisioning_test.go b/pkg/services/ngalert/api/api_provisioning_test.go index 32fa6c7d460..ba50444f8c8 100644 --- a/pkg/services/ngalert/api/api_provisioning_test.go +++ b/pkg/services/ngalert/api/api_provisioning_test.go @@ -1821,7 +1821,9 @@ func createTestEnv(t *testing.T, testConfig string) testEnvironment { require.NoError(t, err) folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) - folderService := folderimpl.ProvideService(actest.FakeAccessControl{ExpectedEvaluate: true}, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sqlStore, featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + fStore := folderimpl.ProvideStore(sqlStore) + folderService := folderimpl.ProvideService(fStore, actest.FakeAccessControl{ExpectedEvaluate: true}, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, sqlStore, + featuremgmt.WithFeatures(), supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) store := store.DBstore{ Logger: log, SQLStore: sqlStore, diff --git a/pkg/services/ngalert/provisioning/alert_rules_test.go b/pkg/services/ngalert/provisioning/alert_rules_test.go index e5e819ef45f..d6d49bca373 100644 --- a/pkg/services/ngalert/provisioning/alert_rules_test.go +++ b/pkg/services/ngalert/provisioning/alert_rules_test.go @@ -1542,13 +1542,14 @@ func TestDeleteRuleGroup(t *testing.T) { func TestProvisiongWithFullpath(t *testing.T) { tracer := tracing.InitializeTracerForTest() inProcBus := bus.ProvideBus(tracer) - sqlStore := db.InitTestDB(t) - cfg := setting.NewCfg() + sqlStore, cfg := db.InitTestDBWithCfg(t) folderStore := folderimpl.ProvideDashboardFolderStore(sqlStore) _, dashboardStore := testutil.SetupDashboardService(t, sqlStore, folderStore, cfg) ac := acmock.New() features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders) - folderService := folderimpl.ProvideService(ac, inProcBus, dashboardStore, folderStore, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + fStore := folderimpl.ProvideStore(sqlStore) + folderService := folderimpl.ProvideService(fStore, ac, inProcBus, dashboardStore, folderStore, sqlStore, + features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) ruleService := createAlertRuleService(t, folderService) var orgID int64 = 1 diff --git a/pkg/services/ngalert/testutil/testutil.go b/pkg/services/ngalert/testutil/testutil.go index 6311a9ffdbb..b9885c7bd53 100644 --- a/pkg/services/ngalert/testutil/testutil.go +++ b/pkg/services/ngalert/testutil/testutil.go @@ -27,7 +27,9 @@ import ( 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 { tb.Helper() - return folderimpl.ProvideService(ac, bus, dashboardStore, folderStore, db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + fStore := folderimpl.ProvideStore(db) + return folderimpl.ProvideService(fStore, ac, bus, dashboardStore, folderStore, db, + features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) } func SetupDashboardService(tb testing.TB, sqlStore db.DB, fs *folderimpl.DashboardFolderStoreImpl, cfg *setting.Cfg) (*dashboardservice.DashboardServiceImpl, dashboards.Store) { @@ -57,7 +59,7 @@ func SetupDashboardService(tb testing.TB, sqlStore db.DB, fs *folderimpl.Dashboa dashboardService, err := dashboardservice.ProvideDashboardServiceImpl( cfg, dashboardStore, fs, features, folderPermissions, dashboardPermissions, ac, - foldertest.NewFakeService(), + foldertest.NewFakeService(), folder.NewFakeStore(), nil, ) require.NoError(tb, err) diff --git a/pkg/services/publicdashboards/api/query_test.go b/pkg/services/publicdashboards/api/query_test.go index 6146c36de2f..e12350ddba4 100644 --- a/pkg/services/publicdashboards/api/query_test.go +++ b/pkg/services/publicdashboards/api/query_test.go @@ -31,6 +31,7 @@ import ( "github.com/grafana/grafana/pkg/services/datasources/guardian" datasourcesService "github.com/grafana/grafana/pkg/services/datasources/service" "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/folder/foldertest" "github.com/grafana/grafana/pkg/services/licensing/licensingtest" @@ -323,7 +324,7 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T) dashService, err := service.ProvideDashboardServiceImpl( cfg, dashboardStoreService, folderStore, featuremgmt.WithFeatures(), acmock.NewMockedPermissionsService(), dashPermissionService, ac, - foldertest.NewFakeService(), nil, + foldertest.NewFakeService(), folder.NewFakeStore(), nil, ) require.NoError(t, err) diff --git a/pkg/services/sqlstore/permissions/dashboard_test.go b/pkg/services/sqlstore/permissions/dashboard_test.go index 4c184e56e17..57040ee9f1d 100644 --- a/pkg/services/sqlstore/permissions/dashboard_test.go +++ b/pkg/services/sqlstore/permissions/dashboard_test.go @@ -822,7 +822,9 @@ func setupNestedTest(t *testing.T, usr *user.SignedInUser, perms []accesscontrol dashStore, err := database.ProvideDashboardStore(db, cfg, features, tagimpl.ProvideService(db), quotatest.New(false, nil)) require.NoError(t, err) - folderSvc := folderimpl.ProvideService(actest.FakeAccessControl{ExpectedEvaluate: true}, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, folderimpl.ProvideDashboardFolderStore(db), db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + fStore := folderimpl.ProvideStore(db) + folderSvc := folderimpl.ProvideService(fStore, actest.FakeAccessControl{ExpectedEvaluate: true}, bus.ProvideBus(tracing.InitializeTracerForTest()), dashStore, + folderimpl.ProvideDashboardFolderStore(db), db, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) // create parent folder parent, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{ diff --git a/pkg/services/sqlstore/permissions/dashboards_bench_test.go b/pkg/services/sqlstore/permissions/dashboards_bench_test.go index 4dc62cadd3a..594b41dcfb2 100644 --- a/pkg/services/sqlstore/permissions/dashboards_bench_test.go +++ b/pkg/services/sqlstore/permissions/dashboards_bench_test.go @@ -81,7 +81,9 @@ func setupBenchMark(b *testing.B, usr user.SignedInUser, features featuremgmt.Fe dashboardWriteStore, err := database.ProvideDashboardStore(store, cfg, features, tagimpl.ProvideService(store), quotaService) require.NoError(b, err) - folderSvc := folderimpl.ProvideService(mock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(store), store, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) + fStore := folderimpl.ProvideStore(store) + folderSvc := folderimpl.ProvideService(fStore, mock.New(), bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(store), + store, features, supportbundlestest.NewFakeBundleService(), nil, tracing.InitializeTracerForTest()) origNewGuardian := guardian.New guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true, CanSaveValue: true})