Nested Folders: Wrap create/update operations with transactions (#78000)
* Nested Folders: Add transaction to create and update methods * Update tests * Make IncreaseVersionForAllRulesInNamespace synchronous * Resolve merge conflicts
This commit is contained in:
@@ -191,7 +191,6 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*dashboards.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(dash, nil).Once()
|
||||
folderStore.On("GetFolderByID", mock.Anything, orgID, dash.ID).Return(f, nil)
|
||||
|
||||
actualFolder, err := service.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
@@ -220,10 +219,21 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
dashboardFolder := dashboards.NewDashboardFolder("Folder")
|
||||
dashboardFolder.ID = rand.Int63()
|
||||
dashboardFolder.UID = util.GenerateShortUID()
|
||||
dashboardFolder.OrgID = orgID
|
||||
f := dashboards.FromDashboard(dashboardFolder)
|
||||
|
||||
_, err := service.store.Create(context.Background(), folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: dashboardFolder.Title,
|
||||
UID: dashboardFolder.UID,
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*dashboards.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(dashboardFolder, nil)
|
||||
dashStore.On("GetDashboard", mock.Anything, mock.AnythingOfType("*dashboards.GetDashboardQuery")).Return(dashboardFolder, nil)
|
||||
|
||||
folderStore.On("GetFolderByID", mock.Anything, orgID, dashboardFolder.ID).Return(f, nil)
|
||||
|
||||
title := "TEST-Folder"
|
||||
@@ -714,12 +724,12 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(&dashboards.Dashboard{}, nil)
|
||||
|
||||
dashboardFolderStore := foldertest.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
folderService := &Service{
|
||||
cfg: cfg,
|
||||
store: nestedFolderStore,
|
||||
db: sqlstore.InitTestDB(t),
|
||||
dashboardStore: &dashStore,
|
||||
dashboardFolderStore: dashboardFolderStore,
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||
@@ -744,21 +754,25 @@ func TestNestedFolderService(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
// dash is needed here because folderSvc.Create expects SaveDashboard to return it
|
||||
dash := dashboards.NewDashboardFolder("myFolder")
|
||||
dash.ID = rand.Int63()
|
||||
dash.UID = "some_uid"
|
||||
|
||||
// dashboard store & service commands that should be called.
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*dashboards.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(&dashboards.Dashboard{}, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(dash, nil)
|
||||
|
||||
dashboardFolderStore := foldertest.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
nestedFolderStore := NewFakeStore()
|
||||
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures(), acimpl.ProvideAccessControl(setting.NewCfg()), dbtest.NewFakeDB())
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures(), acimpl.ProvideAccessControl(setting.NewCfg()), sqlstore.InitTestDB(t))
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
UID: "myFolder",
|
||||
Title: dash.Title,
|
||||
UID: dash.UID,
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -774,21 +788,23 @@ func TestNestedFolderService(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
dash := dashboards.NewDashboardFolder("myFolder")
|
||||
dash.ID = rand.Int63()
|
||||
dash.UID = "some_uid"
|
||||
|
||||
// dashboard store commands that should be called.
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*dashboards.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(&dashboards.Dashboard{}, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(dash, nil)
|
||||
|
||||
dashboardFolderStore := foldertest.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
nestedFolderStore := NewFakeStore()
|
||||
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), acimpl.ProvideAccessControl(setting.NewCfg()), dbtest.NewFakeDB())
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), acimpl.ProvideAccessControl(setting.NewCfg()), sqlstore.InitTestDB(t))
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
UID: "myFolder",
|
||||
Title: dash.Title,
|
||||
UID: dash.UID,
|
||||
SignedInUser: usr,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
@@ -840,17 +856,16 @@ func TestNestedFolderService(t *testing.T) {
|
||||
// dashboard store commands that should be called.
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*dashboards.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(&dashboards.Dashboard{}, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(dash, nil)
|
||||
|
||||
dashboardFolderStore := foldertest.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
dashboardFolderStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
|
||||
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()
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), acimpl.ProvideAccessControl(setting.NewCfg()), dbtest.NewFakeDB())
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), acimpl.ProvideAccessControl(setting.NewCfg()), sqlstore.InitTestDB(t))
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: dash.Title,
|
||||
@@ -875,13 +890,11 @@ func TestNestedFolderService(t *testing.T) {
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(&dashboards.Dashboard{UID: "newUID"}, nil)
|
||||
|
||||
dashboardFolderStore := foldertest.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
nestedFolderStore := NewFakeStore()
|
||||
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, dbtest.NewFakeDB())
|
||||
}, sqlstore.InitTestDB(t))
|
||||
f, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
@@ -909,13 +922,8 @@ func TestNestedFolderService(t *testing.T) {
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*dashboards.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(dashboardFolder, nil)
|
||||
var actualCmd *dashboards.DeleteDashboardCommand
|
||||
dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
actualCmd = args.Get(1).(*dashboards.DeleteDashboardCommand)
|
||||
}).Return(nil).Once()
|
||||
|
||||
dashboardFolderStore := foldertest.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, orgID, dashboardFolder.ID).Return(f, nil)
|
||||
dashboardFolderStore.On("GetFolderByUID", mock.Anything, orgID, dashboardFolder.UID).Return(f, nil)
|
||||
|
||||
nestedFolderStore := NewFakeStore()
|
||||
@@ -936,12 +944,11 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, dbtest.NewFakeDB())
|
||||
}, sqlstore.InitTestDB(t))
|
||||
_, err := folderSvc.Create(context.Background(), &cmd)
|
||||
require.Error(t, err, folder.ErrCircularReference)
|
||||
// CreateFolder should not call the folder store's create method.
|
||||
require.False(t, nestedFolderStore.CreateCalled)
|
||||
require.NotNil(t, actualCmd)
|
||||
})
|
||||
|
||||
t.Run("create returns error from nested folder service", func(t *testing.T) {
|
||||
@@ -956,13 +963,8 @@ func TestNestedFolderService(t *testing.T) {
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*dashboards.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(&dashboards.Dashboard{}, nil)
|
||||
var actualCmd *dashboards.DeleteDashboardCommand
|
||||
dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
actualCmd = args.Get(1).(*dashboards.DeleteDashboardCommand)
|
||||
}).Return(nil).Once()
|
||||
|
||||
dashboardFolderStore := foldertest.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
// return an error from the folder store
|
||||
nestedFolderStore := NewFakeStore()
|
||||
@@ -971,7 +973,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
// the service return success as long as the legacy create succeeds
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, dbtest.NewFakeDB())
|
||||
}, sqlstore.InitTestDB(t))
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
@@ -982,7 +984,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
// CreateFolder should also call the folder store's create method.
|
||||
require.True(t, nestedFolderStore.CreateCalled)
|
||||
require.NotNil(t, actualCmd)
|
||||
})
|
||||
|
||||
t.Run("move without the right permissions should fail", func(t *testing.T) {
|
||||
@@ -1141,13 +1142,8 @@ func TestNestedFolderService(t *testing.T) {
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashStore.On("ValidateDashboardBeforeSave", mock.Anything, mock.AnythingOfType("*dashboards.Dashboard"), mock.AnythingOfType("bool")).Return(true, nil).Times(2)
|
||||
dashStore.On("SaveDashboard", mock.Anything, mock.AnythingOfType("dashboards.SaveDashboardCommand")).Return(&dashboards.Dashboard{}, nil)
|
||||
var actualCmd *dashboards.DeleteDashboardCommand
|
||||
dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
actualCmd = args.Get(1).(*dashboards.DeleteDashboardCommand)
|
||||
}).Return(nil).Once()
|
||||
|
||||
dashboardFolderStore := foldertest.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
dashboardFolderStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
|
||||
parents := make([]*folder.Folder, 0, folder.MaxNestedFolderDepth)
|
||||
@@ -1161,7 +1157,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, dbtest.NewFakeDB())
|
||||
}, sqlstore.InitTestDB(t))
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
Title: "folder",
|
||||
OrgID: orgID,
|
||||
@@ -1170,7 +1166,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
SignedInUser: usr,
|
||||
})
|
||||
assert.ErrorIs(t, err, folder.ErrMaximumDepthReached)
|
||||
require.NotNil(t, actualCmd)
|
||||
})
|
||||
|
||||
t.Run("get default folder, no error", func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user