diff --git a/pkg/services/folder/folderimpl/folder.go b/pkg/services/folder/folderimpl/folder.go index 019164504a4..f779dc7dba4 100644 --- a/pkg/services/folder/folderimpl/folder.go +++ b/pkg/services/folder/folderimpl/folder.go @@ -7,12 +7,14 @@ import ( "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/events" + "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/accesscontrol" "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/guardian" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/search" @@ -29,7 +31,7 @@ type Service struct { dashboardService dashboards.DashboardService dashboardStore dashboards.Store searchService *search.SearchService - features featuremgmt.FeatureToggles + features *featuremgmt.FeatureManager permissions accesscontrol.FolderPermissionsService // bus is currently used to publish events that cause scheduler to update rules. @@ -42,17 +44,20 @@ func ProvideService( cfg *setting.Cfg, dashboardService dashboards.DashboardService, dashboardStore dashboards.Store, - features featuremgmt.FeatureToggles, + db db.DB, // DB for the (new) nested folder store + features *featuremgmt.FeatureManager, folderPermissionsService accesscontrol.FolderPermissionsService, searchService *search.SearchService, ) folder.Service { ac.RegisterScopeAttributeResolver(dashboards.NewFolderNameScopeResolver(dashboardStore)) ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(dashboardStore)) + store := ProvideStore(db, cfg, features) return &Service{ cfg: cfg, log: log.New("folder-service"), dashboardService: dashboardService, dashboardStore: dashboardStore, + store: store, searchService: searchService, features: features, permissions: folderPermissionsService, @@ -178,8 +183,8 @@ func (s *Service) CreateFolder(ctx context.Context, user *user.SignedInUser, org return nil, toFolderError(err) } - var folder *models.Folder - folder, err = s.dashboardStore.GetFolderByID(ctx, orgID, dash.Id) + var createdFolder *models.Folder + createdFolder, err = s.dashboardStore.GetFolderByID(ctx, orgID, dash.Id) if err != nil { return nil, err } @@ -198,16 +203,45 @@ func (s *Service) CreateFolder(ctx context.Context, user *user.SignedInUser, org {BuiltinRole: string(org.RoleViewer), Permission: models.PERMISSION_VIEW.String()}, }...) - _, permissionErr = s.permissions.SetPermissions(ctx, orgID, folder.Uid, permissions...) + _, permissionErr = s.permissions.SetPermissions(ctx, orgID, createdFolder.Uid, permissions...) } else if s.cfg.EditorsCanAdmin && user.IsRealUser() && !user.IsAnonymous { - permissionErr = s.MakeUserAdmin(ctx, orgID, userID, folder.Id, true) + permissionErr = s.MakeUserAdmin(ctx, orgID, userID, createdFolder.Id, true) } if permissionErr != nil { - s.log.Error("Could not make user admin", "folder", folder.Title, "user", userID, "error", permissionErr) + s.log.Error("Could not make user admin", "folder", createdFolder.Title, "user", userID, "error", permissionErr) } - return folder, nil + if s.features.IsEnabled(featuremgmt.FlagNestedFolders) { + var description string + if dash.Data != nil { + description = dash.Data.Get("description").MustString() + } + + _, err := s.store.Create(ctx, folder.CreateFolderCommand{ + // TODO: Today, if a UID isn't specified, the dashboard store + // generates a new UID. The new folder store will need to do this as + // well, but for now we take the UID from the newly created folder. + UID: dash.Uid, + OrgID: orgID, + Title: title, + Description: description, + ParentUID: folder.RootFolderUID, + }) + if err != nil { + // We'll log the error and also roll back the previously-created + // (legacy) folder. + s.log.Error("error saving folder to nested folder store", err) + _, err = s.DeleteFolder(ctx, user, orgID, createdFolder.Uid, true) + if err != nil { + s.log.Error("error deleting folder after failed save to nested folder store", err) + } + return createdFolder, err + } + // The folder UID is specified (or generated) during creation, so we'll + // stop here and return the created model.Folder. + } + return createdFolder, nil } func (s *Service) UpdateFolder(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) error { diff --git a/pkg/services/folder/folderimpl/folder_test.go b/pkg/services/folder/folderimpl/folder_test.go index 07a36ca9a7a..f1b3d01db34 100644 --- a/pkg/services/folder/folderimpl/folder_test.go +++ b/pkg/services/folder/folderimpl/folder_test.go @@ -2,6 +2,7 @@ package folderimpl import ( "context" + "errors" "math/rand" "testing" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/infra/appcontext" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/tracing" "github.com/grafana/grafana/pkg/models" @@ -19,6 +21,7 @@ import ( "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/guardian" + "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/user" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" @@ -34,7 +37,7 @@ func TestIntegrationProvideFolderService(t *testing.T) { t.Run("should register scope resolvers", func(t *testing.T) { cfg := setting.NewCfg() ac := acmock.New() - ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, nil, nil, nil, nil, nil) + ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, nil, nil, nil, &featuremgmt.FeatureManager{}, nil, nil) require.Len(t, ac.Calls.RegisterAttributeScopeResolver, 2) }) @@ -45,20 +48,24 @@ func TestIntegrationFolderService(t *testing.T) { t.Skip("skipping integration test") } t.Run("Folder service tests", func(t *testing.T) { - store := &dashboards.FakeDashboardStore{} + dashStore := &dashboards.FakeDashboardStore{} + db := sqlstore.InitTestDB(t) + store := ProvideStore(db, db.Cfg, featuremgmt.WithFeatures([]interface{}{"nestedFolders"})) + cfg := setting.NewCfg() cfg.RBACEnabled = false features := featuremgmt.WithFeatures() cfg.IsFeatureToggleEnabled = features.IsEnabled folderPermissions := acmock.NewMockedPermissionsService() dashboardPermissions := acmock.NewMockedPermissionsService() - dashboardService := dashboardsvc.ProvideDashboardService(cfg, store, nil, features, folderPermissions, dashboardPermissions, acmock.New()) + dashboardService := dashboardsvc.ProvideDashboardService(cfg, dashStore, nil, features, folderPermissions, dashboardPermissions, acmock.New()) service := &Service{ cfg: cfg, log: log.New("test-folder-service"), dashboardService: dashboardService, - dashboardStore: store, + dashboardStore: dashStore, + store: store, searchService: nil, features: features, permissions: folderPermissions, @@ -76,8 +83,8 @@ func TestIntegrationFolderService(t *testing.T) { folder.Id = folderId folder.Uid = folderUID - store.On("GetFolderByID", mock.Anything, orgID, folderId).Return(folder, nil) - store.On("GetFolderByUID", mock.Anything, orgID, folderUID).Return(folder, nil) + dashStore.On("GetFolderByID", mock.Anything, orgID, folderId).Return(folder, nil) + dashStore.On("GetFolderByUID", mock.Anything, orgID, folderUID).Return(folder, nil) t.Run("When get folder by id should return access denied error", func(t *testing.T) { _, err := service.GetFolderByID(context.Background(), usr, folderId, orgID) @@ -96,13 +103,13 @@ func TestIntegrationFolderService(t *testing.T) { }) t.Run("When creating folder should return access denied error", func(t *testing.T) { - store.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil).Times(2) + dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil).Times(2) _, err := service.CreateFolder(context.Background(), usr, orgID, folder.Title, folderUID) require.Equal(t, err, dashboards.ErrFolderAccessDenied) }) t.Run("When updating folder should return access denied error", func(t *testing.T) { - store.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) { + dashStore.On("GetDashboard", mock.Anything, mock.AnythingOfType("*models.GetDashboardQuery")).Run(func(args mock.Arguments) { folder := args.Get(1).(*models.GetDashboardQuery) folder.Result = models.NewDashboard("dashboard-test") folder.Result.IsFolder = true @@ -134,11 +141,11 @@ func TestIntegrationFolderService(t *testing.T) { dash.Id = rand.Int63() f := models.DashboardToFolder(dash) - store.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil) - store.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(dash, nil).Once() - store.On("GetFolderByID", mock.Anything, orgID, dash.Id).Return(f, nil) + dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil) + dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(dash, nil).Once() + dashStore.On("GetFolderByID", mock.Anything, orgID, dash.Id).Return(f, nil) - actualFolder, err := service.CreateFolder(context.Background(), usr, orgID, dash.Title, "") + actualFolder, err := service.CreateFolder(context.Background(), usr, orgID, dash.Title, "someuid") require.NoError(t, err) require.Equal(t, f, actualFolder) }) @@ -157,9 +164,9 @@ func TestIntegrationFolderService(t *testing.T) { dashboardFolder.Uid = util.GenerateShortUID() f := models.DashboardToFolder(dashboardFolder) - store.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil) - store.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(dashboardFolder, nil) - store.On("GetFolderByID", mock.Anything, orgID, dashboardFolder.Id).Return(f, nil) + dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*models.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil) + dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(dashboardFolder, nil) + dashStore.On("GetFolderByID", mock.Anything, orgID, dashboardFolder.Id).Return(f, nil) req := &models.UpdateFolderCommand{ Uid: dashboardFolder.Uid, @@ -175,10 +182,10 @@ func TestIntegrationFolderService(t *testing.T) { f := models.NewFolder(util.GenerateShortUID()) f.Id = rand.Int63() f.Uid = util.GenerateShortUID() - store.On("GetFolderByUID", mock.Anything, orgID, f.Uid).Return(f, nil) + dashStore.On("GetFolderByUID", mock.Anything, orgID, f.Uid).Return(f, nil) var actualCmd *models.DeleteDashboardCommand - store.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { actualCmd = args.Get(1).(*models.DeleteDashboardCommand) }).Return(nil).Once() @@ -204,7 +211,7 @@ func TestIntegrationFolderService(t *testing.T) { expected := models.NewFolder(util.GenerateShortUID()) expected.Id = rand.Int63() - store.On("GetFolderByID", mock.Anything, orgID, expected.Id).Return(expected, nil) + dashStore.On("GetFolderByID", mock.Anything, orgID, expected.Id).Return(expected, nil) actual, err := service.GetFolderByID(context.Background(), usr, expected.Id, orgID) require.Equal(t, expected, actual) @@ -215,7 +222,7 @@ func TestIntegrationFolderService(t *testing.T) { expected := models.NewFolder(util.GenerateShortUID()) expected.Uid = util.GenerateShortUID() - store.On("GetFolderByUID", mock.Anything, orgID, expected.Uid).Return(expected, nil) + dashStore.On("GetFolderByUID", mock.Anything, orgID, expected.Uid).Return(expected, nil) actual, err := service.GetFolderByUID(context.Background(), usr, orgID, expected.Uid) require.Equal(t, expected, actual) @@ -225,7 +232,7 @@ func TestIntegrationFolderService(t *testing.T) { t.Run("When get folder by title should return folder", func(t *testing.T) { expected := models.NewFolder("TEST-" + util.GenerateShortUID()) - store.On("GetFolderByTitle", mock.Anything, orgID, expected.Title).Return(expected, nil) + dashStore.On("GetFolderByTitle", mock.Anything, orgID, expected.Title).Return(expected, nil) actual, err := service.GetFolderByTitle(context.Background(), usr, orgID, expected.Title) require.Equal(t, expected, actual) @@ -326,3 +333,98 @@ func TestFolderService(t *testing.T) { require.NoError(t, err) }) } + +func TestCreate_NestedFolders(t *testing.T) { + t.Run("with feature flag unset", func(t *testing.T) { + ctx := appcontext.WithUser(context.Background(), usr) + store := &FakeStore{} + dashStore := dashboards.FakeDashboardStore{} + dashboardsvc := dashboards.FakeDashboardService{} + // nothing enabled yet + cfg := setting.NewCfg() + cfg.RBACEnabled = false + features := featuremgmt.WithFeatures() + cfg.IsFeatureToggleEnabled = features.IsEnabled + foldersvc := &Service{ + cfg: cfg, + log: log.New("test-folder-service"), + dashboardService: &dashboardsvc, + dashboardStore: &dashStore, + store: store, + features: features, + } + + // dashboard store & service commands that should be called. + dashboardsvc.On("BuildSaveDashboardCommand", + mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"), + mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&models.SaveDashboardCommand{}, nil) + dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(&models.Dashboard{}, nil) + dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&models.Folder{}, nil) + + _, err := foldersvc.CreateFolder(ctx, usr, orgID, "myFolder", "myFolder") + require.NoError(t, err) + // CreateFolder should not call the folder store create if the feature toggle is not enabled. + require.False(t, store.CreateCalled) + }) + + t.Run("with nested folder feature flag on", func(t *testing.T) { + ctx := appcontext.WithUser(context.Background(), usr) + store := &FakeStore{} + dashStore := &dashboards.FakeDashboardStore{} + dashboardsvc := &dashboards.FakeDashboardService{} + // nothing enabled yet + cfg := setting.NewCfg() + cfg.RBACEnabled = false + features := featuremgmt.WithFeatures("nestedFolders") + cfg.IsFeatureToggleEnabled = features.IsEnabled + foldersvc := &Service{ + cfg: cfg, + log: log.New("test-folder-service"), + dashboardService: dashboardsvc, + dashboardStore: dashStore, + store: store, + features: features, + } + + t.Run("create, no error", func(t *testing.T) { + // dashboard store & service commands that should be called. + dashboardsvc.On("BuildSaveDashboardCommand", + mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"), + mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&models.SaveDashboardCommand{}, nil) + dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(&models.Dashboard{}, nil) + dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&models.Folder{}, nil) + _, err := foldersvc.CreateFolder(ctx, usr, orgID, "myFolder", "myFolder") + require.NoError(t, err) + // CreateFolder should also call the folder store's create method. + require.True(t, store.CreateCalled) + }) + + t.Run("create returns error from nested folder service", func(t *testing.T) { + // This test creates and deletes the dashboard, so needs some extra setup. + g := guardian.New + guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{}) + + // dashboard store & service commands that should be called. + dashboardsvc.On("BuildSaveDashboardCommand", + mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"), + mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&models.SaveDashboardCommand{}, nil) + dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("models.SaveDashboardCommand")).Return(&models.Dashboard{}, nil) + dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&models.Folder{}, nil) + dashStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&models.Folder{}, nil) + + // return an error from the folder store + store.ExpectedError = errors.New("FAILED") + + // the service return success as long as the legacy create succeeds + _, err := foldersvc.CreateFolder(ctx, usr, orgID, "myFolder", "myFolder") + require.Error(t, err, "FAILED") + + // CreateFolder should also call the folder store's create method. + require.True(t, store.CreateCalled) + + t.Cleanup(func() { + guardian.New = g + }) + }) + }) +} diff --git a/pkg/services/folder/folderimpl/sqlstore.go b/pkg/services/folder/folderimpl/sqlstore.go index 5840bbba91c..4c82a7a2dd9 100644 --- a/pkg/services/folder/folderimpl/sqlstore.go +++ b/pkg/services/folder/folderimpl/sqlstore.go @@ -18,13 +18,13 @@ type sqlStore struct { db db.DB log log.Logger cfg *setting.Cfg - fm featuremgmt.FeatureManager + fm featuremgmt.FeatureToggles } // sqlStore implements the store interface. var _ store = (*sqlStore)(nil) -func ProvideStore(db db.DB, cfg *setting.Cfg, features featuremgmt.FeatureManager) *sqlStore { +func ProvideStore(db db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles) *sqlStore { return &sqlStore{db: db, log: log.New("folder-store"), cfg: cfg, fm: features} } diff --git a/pkg/services/folder/folderimpl/sqlstore_test.go b/pkg/services/folder/folderimpl/sqlstore_test.go index 85c1dfaf04e..63f9587d122 100644 --- a/pkg/services/folder/folderimpl/sqlstore_test.go +++ b/pkg/services/folder/folderimpl/sqlstore_test.go @@ -6,6 +6,9 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/folder" @@ -13,8 +16,6 @@ import ( "github.com/grafana/grafana/pkg/services/org/orgimpl" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/util" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestIntegrationCreate(t *testing.T) { @@ -24,7 +25,7 @@ func TestIntegrationCreate(t *testing.T) { t.Skip("skipping until folder migration is merged") db := sqlstore.InitTestDB(t) - folderStore := ProvideStore(db, db.Cfg, *featuremgmt.WithFeatures()) + folderStore := ProvideStore(db, db.Cfg, &featuremgmt.FeatureManager{}) orgID := CreateOrg(t, db) @@ -162,7 +163,7 @@ func TestIntegrationDelete(t *testing.T) { t.Skip("skipping until folder migration is merged") db := sqlstore.InitTestDB(t) - folderStore := ProvideStore(db, db.Cfg, *featuremgmt.WithFeatures()) + folderStore := ProvideStore(db, db.Cfg, &featuremgmt.FeatureManager{}) orgID := CreateOrg(t, db) @@ -210,7 +211,7 @@ func TestIntegrationUpdate(t *testing.T) { t.Skip("skipping until folder migration is merged") db := sqlstore.InitTestDB(t) - folderStore := ProvideStore(db, db.Cfg, *featuremgmt.WithFeatures()) + folderStore := ProvideStore(db, db.Cfg, &featuremgmt.FeatureManager{}) orgID := CreateOrg(t, db) @@ -315,7 +316,7 @@ func TestIntegrationGet(t *testing.T) { t.Skip("skipping until folder migration is merged") db := sqlstore.InitTestDB(t) - folderStore := ProvideStore(db, db.Cfg, *featuremgmt.WithFeatures()) + folderStore := ProvideStore(db, db.Cfg, &featuremgmt.FeatureManager{}) orgID := CreateOrg(t, db) @@ -396,7 +397,7 @@ func TestIntegrationGetParents(t *testing.T) { t.Skip("skipping until folder migration is merged") db := sqlstore.InitTestDB(t) - folderStore := ProvideStore(db, db.Cfg, *featuremgmt.WithFeatures()) + folderStore := ProvideStore(db, db.Cfg, &featuremgmt.FeatureManager{}) orgID := CreateOrg(t, db) @@ -460,7 +461,7 @@ func TestIntegrationGetChildren(t *testing.T) { t.Skip("skipping until folder migration is merged") db := sqlstore.InitTestDB(t) - folderStore := ProvideStore(db, db.Cfg, *featuremgmt.WithFeatures()) + folderStore := ProvideStore(db, db.Cfg, &featuremgmt.FeatureManager{}) orgID := CreateOrg(t, db) diff --git a/pkg/services/folder/folderimpl/store_fake.go b/pkg/services/folder/folderimpl/store_fake.go index 302acda3e24..d18351437a6 100644 --- a/pkg/services/folder/folderimpl/store_fake.go +++ b/pkg/services/folder/folderimpl/store_fake.go @@ -10,6 +10,8 @@ type FakeStore struct { ExpectedFolders []*folder.Folder ExpectedFolder *folder.Folder ExpectedError error + + CreateCalled bool } func NewFakeStore() *FakeStore { @@ -19,6 +21,7 @@ func NewFakeStore() *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 } diff --git a/pkg/services/folder/model.go b/pkg/services/folder/model.go index 3886b8471f4..ee5392db273 100644 --- a/pkg/services/folder/model.go +++ b/pkg/services/folder/model.go @@ -13,6 +13,7 @@ var ErrInternal = errutil.NewBase(errutil.StatusInternal, "folder.internal") const ( GeneralFolderUID = "general" + RootFolderUID = "" MaxNestedFolderDepth = 8 ) diff --git a/pkg/services/libraryelements/libraryelements_test.go b/pkg/services/libraryelements/libraryelements_test.go index 3b6a3975ed5..d1f7f307b24 100644 --- a/pkg/services/libraryelements/libraryelements_test.go +++ b/pkg/services/libraryelements/libraryelements_test.go @@ -310,7 +310,7 @@ func createFolderWithACL(t *testing.T, sqlStore db.DB, title string, user user.S cfg, dashboardStore, nil, features, folderPermissions, dashboardPermissions, ac, ) - s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, d, dashboardStore, features, folderPermissions, nil) + s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, d, dashboardStore, nil, features, folderPermissions, nil) t.Logf("Creating folder with title and UID %q", title) folder, err := s.CreateFolder(context.Background(), &user, user.OrgID, title, title) require.NoError(t, err) @@ -420,7 +420,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo service := LibraryElementService{ Cfg: sqlStore.Cfg, SQLStore: sqlStore, - folderService: folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), sqlStore.Cfg, dashboardService, dashboardStore, features, folderPermissions, nil), + folderService: folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), sqlStore.Cfg, dashboardService, dashboardStore, nil, features, folderPermissions, nil), } usr := user.SignedInUser{ diff --git a/pkg/services/librarypanels/librarypanels_test.go b/pkg/services/librarypanels/librarypanels_test.go index a422dc729a2..02b18692e85 100644 --- a/pkg/services/librarypanels/librarypanels_test.go +++ b/pkg/services/librarypanels/librarypanels_test.go @@ -717,7 +717,7 @@ func createFolderWithACL(t *testing.T, sqlStore db.DB, title string, user *user. dashboardPermissions := acmock.NewMockedPermissionsService() dashboardStore := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg)) d := dashboardservice.ProvideDashboardService(cfg, dashboardStore, nil, features, folderPermissions, dashboardPermissions, ac) - s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, d, dashboardStore, features, folderPermissions, nil) + s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, d, dashboardStore, nil, features, folderPermissions, nil) t.Logf("Creating folder with title and UID %q", title) folder, err := s.CreateFolder(context.Background(), user, user.OrgID, title, title) @@ -819,7 +819,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo cfg, dashboardStore, &alerting.DashAlertExtractorService{}, features, folderPermissions, dashboardPermissions, ac, ) - folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardService, dashboardStore, features, folderPermissions, nil) + folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardService, dashboardStore, nil, features, folderPermissions, nil) elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService) service := LibraryPanelService{ diff --git a/pkg/services/ngalert/tests/util.go b/pkg/services/ngalert/tests/util.go index 6862ed83361..3daf391381b 100644 --- a/pkg/services/ngalert/tests/util.go +++ b/pkg/services/ngalert/tests/util.go @@ -89,7 +89,7 @@ func SetupTestEnv(tb testing.TB, baseInterval time.Duration) (*ngalert.AlertNG, ) bus := bus.ProvideBus(tracing.InitializeTracerForTest()) - folderService := folderimpl.ProvideService(ac, bus, cfg, dashboardService, dashboardStore, features, folderPermissions, nil) + folderService := folderimpl.ProvideService(ac, bus, cfg, dashboardService, dashboardStore, nil, features, folderPermissions, nil) ng, err := ngalert.ProvideService( cfg, &FakeFeatures{}, nil, nil, routing.NewRouteRegister(), sqlStore, nil, nil, nil, nil,