mirror of
https://github.com/grafana/grafana.git
synced 2025-08-06 18:15:25 +08:00
Chore: Drop dashboard service dependency from folder service (#61614)
* Chore: Drop dashboard dependency from folder service
This commit is contained in:

committed by
GitHub

parent
a1f2d0e205
commit
b80c9bb974
@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/events"
|
||||
@ -31,7 +32,6 @@ type Service struct {
|
||||
|
||||
log log.Logger
|
||||
cfg *setting.Cfg
|
||||
dashboardService dashboards.DashboardService
|
||||
dashboardStore dashboards.Store
|
||||
searchService *search.SearchService
|
||||
features featuremgmt.FeatureToggles
|
||||
@ -46,7 +46,6 @@ func ProvideService(
|
||||
ac accesscontrol.AccessControl,
|
||||
bus bus.Bus,
|
||||
cfg *setting.Cfg,
|
||||
dashboardService dashboards.DashboardService,
|
||||
dashboardStore dashboards.Store,
|
||||
db db.DB, // DB for the (new) nested folder store
|
||||
features featuremgmt.FeatureToggles,
|
||||
@ -59,7 +58,6 @@ func ProvideService(
|
||||
svr := &Service{
|
||||
cfg: cfg,
|
||||
log: log.New("folder-service"),
|
||||
dashboardService: dashboardService,
|
||||
dashboardStore: dashboardStore,
|
||||
store: store,
|
||||
searchService: searchService,
|
||||
@ -321,7 +319,7 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
|
||||
User: user,
|
||||
}
|
||||
|
||||
saveDashboardCmd, err := s.dashboardService.BuildSaveDashboardCommand(ctx, dto, false, false)
|
||||
saveDashboardCmd, err := s.BuildSaveDashboardCommand(ctx, dto)
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
@ -466,7 +464,7 @@ func (s *Service) legacyUpdate(ctx context.Context, cmd *folder.UpdateFolderComm
|
||||
Overwrite: cmd.Overwrite,
|
||||
}
|
||||
|
||||
saveDashboardCmd, err := s.dashboardService.BuildSaveDashboardCommand(ctx, dto, false, false)
|
||||
saveDashboardCmd, err := s.BuildSaveDashboardCommand(ctx, dto)
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
@ -648,8 +646,154 @@ func (s *Service) nestedFolderDelete(ctx context.Context, cmd *folder.DeleteFold
|
||||
return nil
|
||||
}
|
||||
|
||||
// MakeUserAdmin is copy of DashboardServiceImpl.MakeUserAdmin
|
||||
func (s *Service) MakeUserAdmin(ctx context.Context, orgID int64, userID, folderID int64, setViewAndEditPermissions bool) error {
|
||||
return s.dashboardService.MakeUserAdmin(ctx, orgID, userID, folderID, setViewAndEditPermissions)
|
||||
rtEditor := org.RoleEditor
|
||||
rtViewer := org.RoleViewer
|
||||
|
||||
items := []*models.DashboardACL{
|
||||
{
|
||||
OrgID: orgID,
|
||||
DashboardID: folderID,
|
||||
UserID: userID,
|
||||
Permission: models.PERMISSION_ADMIN,
|
||||
Created: time.Now(),
|
||||
Updated: time.Now(),
|
||||
},
|
||||
}
|
||||
|
||||
if setViewAndEditPermissions {
|
||||
items = append(items,
|
||||
&models.DashboardACL{
|
||||
OrgID: orgID,
|
||||
DashboardID: folderID,
|
||||
Role: &rtEditor,
|
||||
Permission: models.PERMISSION_EDIT,
|
||||
Created: time.Now(),
|
||||
Updated: time.Now(),
|
||||
},
|
||||
&models.DashboardACL{
|
||||
OrgID: orgID,
|
||||
DashboardID: folderID,
|
||||
Role: &rtViewer,
|
||||
Permission: models.PERMISSION_VIEW,
|
||||
Created: time.Now(),
|
||||
Updated: time.Now(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if err := s.dashboardStore.UpdateDashboardACL(ctx, folderID, items); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// BuildSaveDashboardCommand is a simplified version on DashboardServiceImpl.BuildSaveDashboardCommand
|
||||
// keeping only the meaningful functionality for folders
|
||||
func (s *Service) BuildSaveDashboardCommand(ctx context.Context, dto *dashboards.SaveDashboardDTO) (*dashboards.SaveDashboardCommand, error) {
|
||||
dash := dto.Dashboard
|
||||
|
||||
dash.OrgID = dto.OrgID
|
||||
dash.Title = strings.TrimSpace(dash.Title)
|
||||
dash.Data.Set("title", dash.Title)
|
||||
dash.SetUID(strings.TrimSpace(dash.UID))
|
||||
|
||||
if dash.Title == "" {
|
||||
return nil, dashboards.ErrDashboardTitleEmpty
|
||||
}
|
||||
|
||||
if dash.IsFolder && dash.FolderID > 0 {
|
||||
return nil, dashboards.ErrDashboardFolderCannotHaveParent
|
||||
}
|
||||
|
||||
if dash.IsFolder && strings.EqualFold(dash.Title, dashboards.RootFolderName) {
|
||||
return nil, dashboards.ErrDashboardFolderNameExists
|
||||
}
|
||||
|
||||
if !util.IsValidShortUID(dash.UID) {
|
||||
return nil, dashboards.ErrDashboardInvalidUid
|
||||
} else if util.IsShortUIDTooLong(dash.UID) {
|
||||
return nil, dashboards.ErrDashboardUidTooLong
|
||||
}
|
||||
|
||||
isParentFolderChanged, err := s.dashboardStore.ValidateDashboardBeforeSave(ctx, dash, dto.Overwrite)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isParentFolderChanged {
|
||||
// Check that the user is allowed to add a dashboard to the folder
|
||||
guardian, err := guardian.NewByDashboard(ctx, dash, dto.OrgID, dto.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if canSave, err := guardian.CanCreate(dash.FolderID, dash.IsFolder); err != nil || !canSave {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
}
|
||||
|
||||
guard, err := getGuardianForSavePermissionCheck(ctx, dash, dto.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if dash.ID == 0 {
|
||||
if canCreate, err := guard.CanCreate(dash.FolderID, dash.IsFolder); err != nil || !canCreate {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
} else {
|
||||
if canSave, err := guard.CanSave(); err != nil || !canSave {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, dashboards.ErrDashboardUpdateAccessDenied
|
||||
}
|
||||
}
|
||||
|
||||
cmd := &dashboards.SaveDashboardCommand{
|
||||
Dashboard: dash.Data,
|
||||
Message: dto.Message,
|
||||
OrgID: dto.OrgID,
|
||||
Overwrite: dto.Overwrite,
|
||||
UserID: dto.User.UserID,
|
||||
FolderID: dash.FolderID,
|
||||
IsFolder: dash.IsFolder,
|
||||
PluginID: dash.PluginID,
|
||||
}
|
||||
|
||||
if !dto.UpdatedAt.IsZero() {
|
||||
cmd.UpdatedAt = dto.UpdatedAt
|
||||
}
|
||||
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// getGuardianForSavePermissionCheck returns the guardian to be used for checking permission of dashboard
|
||||
// It replaces deleted Dashboard.GetDashboardIdForSavePermissionCheck()
|
||||
func getGuardianForSavePermissionCheck(ctx context.Context, d *dashboards.Dashboard, user *user.SignedInUser) (guardian.DashboardGuardian, error) {
|
||||
newDashboard := d.ID == 0
|
||||
|
||||
if newDashboard {
|
||||
// if it's a new dashboard/folder check the parent folder permissions
|
||||
guard, err := guardian.New(ctx, d.FolderID, d.OrgID, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return guard, nil
|
||||
}
|
||||
guard, err := guardian.NewByDashboard(ctx, d, d.OrgID, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return guard, nil
|
||||
}
|
||||
|
||||
func (s *Service) nestedFolderCreate(ctx context.Context, cmd *folder.CreateFolderCommand) (*folder.Folder, error) {
|
||||
|
@ -19,7 +19,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
dashboardsvc "github.com/grafana/grafana/pkg/services/dashboards/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
@ -39,7 +38,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, &featuremgmt.FeatureManager{}, nil, nil)
|
||||
ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, nil, nil, &featuremgmt.FeatureManager{}, nil, nil)
|
||||
|
||||
require.Len(t, ac.Calls.RegisterAttributeScopeResolver, 2)
|
||||
})
|
||||
@ -58,13 +57,10 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
cfg.RBACEnabled = false
|
||||
features := featuremgmt.WithFeatures()
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||
dashboardService := dashboardsvc.ProvideDashboardService(cfg, dashStore, nil, features, folderPermissions, dashboardPermissions, acmock.New())
|
||||
|
||||
service := &Service{
|
||||
cfg: cfg,
|
||||
log: log.New("test-folder-service"),
|
||||
dashboardService: dashboardService,
|
||||
dashboardStore: dashStore,
|
||||
store: store,
|
||||
searchService: nil,
|
||||
@ -320,13 +316,16 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
t.Cleanup(func() {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
dashboardsvc.On("BuildSaveDashboardCommand",
|
||||
mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"),
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&dashboards.SaveDashboardCommand{}, nil)
|
||||
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("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
cfg := setting.NewCfg()
|
||||
@ -335,13 +334,12 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
cfg: cfg,
|
||||
store: folderStore,
|
||||
dashboardStore: &dashStore,
|
||||
dashboardService: &dashboardsvc,
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||
log: log.New("test-folder-service"),
|
||||
}
|
||||
t.Run("create folder", func(t *testing.T) {
|
||||
folderStore.ExpectedFolder = &folder.Folder{ParentUID: util.GenerateShortUID()}
|
||||
res, err := folderService.Create(context.Background(), &folder.CreateFolderCommand{SignedInUser: usr})
|
||||
res, err := folderService.Create(context.Background(), &folder.CreateFolderCommand{SignedInUser: usr, Title: "my folder"})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res.UID)
|
||||
require.NotEmpty(t, res.ParentUID)
|
||||
@ -351,19 +349,21 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
func TestNestedFolderService(t *testing.T) {
|
||||
t.Run("with feature flag unset", func(t *testing.T) {
|
||||
t.Run("When create folder, no create in folder table done", func(t *testing.T) {
|
||||
// dashboard store & service commands that should be called.
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
dashboardsvc.On("BuildSaveDashboardCommand",
|
||||
mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"),
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&dashboards.SaveDashboardCommand{}, nil)
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
t.Cleanup(func() {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
// 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("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures(), nil, &dashboardsvc)
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures(), nil)
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
@ -376,8 +376,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("When delete folder, no delete in folder table done", func(t *testing.T) {
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
|
||||
var actualCmd *dashboards.DeleteDashboardCommand
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
@ -385,32 +383,28 @@ func TestNestedFolderService(t *testing.T) {
|
||||
}).Return(nil).Once()
|
||||
dashStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures(), nil, &dashboardsvc)
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures(), nil)
|
||||
err := folderSvc.Delete(context.Background(), &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
|
||||
t.Cleanup(func() {
|
||||
guardian.New = g
|
||||
})
|
||||
require.False(t, folderStore.DeleteCalled)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("with nested folder feature flag on", func(t *testing.T) {
|
||||
t.Run("create, no error", func(t *testing.T) {
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
// dashboard store & service commands that should be called.
|
||||
dashboardsvc.On("BuildSaveDashboardCommand",
|
||||
mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"),
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&dashboards.SaveDashboardCommand{}, nil)
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
t.Cleanup(func() {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
// 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("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
@ -418,7 +412,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
@ -431,13 +425,15 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("create without UID, no error", func(t *testing.T) {
|
||||
// dashboard store & service commands that should be called.
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
dashboardsvc.On("BuildSaveDashboardCommand",
|
||||
mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"),
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&dashboards.SaveDashboardCommand{}, nil)
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
t.Cleanup(func() {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
// 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{UID: "newUID"}, nil)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
@ -445,7 +441,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
f, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
@ -458,17 +454,18 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("create failed because of circular reference", func(t *testing.T) {
|
||||
// dashboard store & service commands that should be called.
|
||||
g := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
t.Cleanup(func() {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
dashboardFolder := dashboards.NewDashboardFolder("myFolder")
|
||||
dashboardFolder.ID = rand.Int63()
|
||||
dashboardFolder.UID = "myFolder"
|
||||
f := dashboards.FromDashboard(dashboardFolder)
|
||||
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
dashboardsvc.On("BuildSaveDashboardCommand",
|
||||
mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"),
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&dashboards.SaveDashboardCommand{}, nil)
|
||||
|
||||
// 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(dashboardFolder, nil)
|
||||
@ -496,7 +493,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
_, err := folderSvc.Create(context.Background(), &cmd)
|
||||
require.Error(t, err, folder.ErrCircularReference)
|
||||
// CreateFolder should not call the folder store's create method.
|
||||
@ -507,15 +504,14 @@ func TestNestedFolderService(t *testing.T) {
|
||||
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 := dashboards.FakeDashboardService{}
|
||||
dashboardsvc.On("BuildSaveDashboardCommand",
|
||||
mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"),
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&dashboards.SaveDashboardCommand{}, nil)
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true})
|
||||
t.Cleanup(func() {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
// 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("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
dashStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
@ -531,7 +527,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
// the service return success as long as the legacy create succeeds
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
@ -543,10 +539,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
// CreateFolder should also call the folder store's create method.
|
||||
require.True(t, folderStore.CreateCalled)
|
||||
require.NotNil(t, actualCmd)
|
||||
|
||||
t.Cleanup(func() {
|
||||
guardian.New = g
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("move, no view permission should fail", func(t *testing.T) {
|
||||
@ -557,7 +549,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
@ -565,7 +556,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
_, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.Error(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
@ -578,7 +569,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
@ -586,7 +576,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
_, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.Error(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
@ -599,7 +589,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
@ -612,7 +601,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
f, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, f)
|
||||
@ -625,7 +614,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
@ -634,7 +622,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
f, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.Error(t, err, folder.ErrCircularReference)
|
||||
require.Nil(t, f)
|
||||
@ -647,7 +635,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
@ -660,7 +647,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
f, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder2", OrgID: orgID, SignedInUser: usr})
|
||||
require.Error(t, err, folder.ErrMaximumDepthReached)
|
||||
require.Nil(t, f)
|
||||
@ -673,7 +660,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
@ -682,7 +668,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
f, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder2", OrgID: orgID, SignedInUser: usr})
|
||||
require.Error(t, err, folder.ErrCircularReference)
|
||||
require.Nil(t, f)
|
||||
@ -695,8 +681,6 @@ func TestNestedFolderService(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
var actualCmd *dashboards.DeleteDashboardCommand
|
||||
dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
@ -709,7 +693,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
err := folderSvc.Delete(context.Background(), &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
@ -725,13 +709,9 @@ func TestNestedFolderService(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
dashboardsvc := dashboards.FakeDashboardService{}
|
||||
|
||||
// dashboard store commands that should be called.
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
// dashboard store & service commands that should be called.
|
||||
dashboardsvc.On("BuildSaveDashboardCommand",
|
||||
mock.Anything, mock.AnythingOfType("*dashboards.SaveDashboardDTO"),
|
||||
mock.AnythingOfType("bool"), mock.AnythingOfType("bool")).Return(&dashboards.SaveDashboardCommand{}, nil)
|
||||
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)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
dashStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
@ -751,7 +731,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
}, &dashboardsvc)
|
||||
})
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
Title: "folder",
|
||||
OrgID: orgID,
|
||||
@ -765,7 +745,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func setup(t *testing.T, dashStore dashboards.Store, folderStore store, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl, dashboardService dashboards.DashboardService) folder.Service {
|
||||
func setup(t *testing.T, dashStore dashboards.Store, folderStore store, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl) folder.Service {
|
||||
t.Helper()
|
||||
|
||||
// nothing enabled yet
|
||||
@ -774,7 +754,6 @@ func setup(t *testing.T, dashStore dashboards.Store, folderStore store, features
|
||||
return &Service{
|
||||
cfg: cfg,
|
||||
log: log.New("test-folder-service"),
|
||||
dashboardService: dashboardService,
|
||||
dashboardStore: dashStore,
|
||||
store: folderStore,
|
||||
features: features,
|
||||
|
@ -310,16 +310,11 @@ func createFolderWithACL(t *testing.T, sqlStore db.DB, title string, user user.S
|
||||
cfg.IsFeatureToggleEnabled = features.IsEnabled
|
||||
ac := acmock.New()
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||
quotaService := quotatest.New(false, nil)
|
||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
|
||||
d := dashboardservice.ProvideDashboardService(
|
||||
cfg, dashboardStore, nil,
|
||||
features, folderPermissions, dashboardPermissions, ac,
|
||||
)
|
||||
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, d, dashboardStore, nil, features, folderPermissions, nil)
|
||||
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, nil, features, folderPermissions, nil)
|
||||
t.Logf("Creating folder with title and UID %q", title)
|
||||
ctx := appcontext.WithUser(context.Background(), &user)
|
||||
folder, err := s.Create(ctx, &folder.CreateFolderCommand{
|
||||
@ -447,7 +442,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, nil, features, folderPermissions, nil),
|
||||
folderService: folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), sqlStore.Cfg, dashboardStore, nil, features, folderPermissions, nil),
|
||||
}
|
||||
|
||||
// deliberate difference between signed in user and user in db to make it crystal clear
|
||||
|
@ -723,12 +723,10 @@ func createFolderWithACL(t *testing.T, sqlStore db.DB, title string, user *user.
|
||||
cfg.IsFeatureToggleEnabled = featuremgmt.WithFeatures().IsEnabled
|
||||
features := featuremgmt.WithFeatures()
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||
quotaService := quotatest.New(false, nil)
|
||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
d := dashboardservice.ProvideDashboardService(cfg, dashboardStore, nil, features, folderPermissions, dashboardPermissions, ac)
|
||||
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, d, dashboardStore, nil, features, folderPermissions, nil)
|
||||
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, nil, features, folderPermissions, nil)
|
||||
|
||||
t.Logf("Creating folder with title and UID %q", title)
|
||||
ctx := appcontext.WithUser(context.Background(), user)
|
||||
@ -836,13 +834,8 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
||||
features := featuremgmt.WithFeatures()
|
||||
ac := acmock.New()
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||
|
||||
dashboardService := dashboardservice.ProvideDashboardService(
|
||||
cfg, dashboardStore, &alerting.DashAlertExtractorService{},
|
||||
features, folderPermissions, dashboardPermissions, ac,
|
||||
)
|
||||
folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardService, dashboardStore, nil, features, folderPermissions, nil)
|
||||
folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, nil, features, folderPermissions, nil)
|
||||
|
||||
elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService)
|
||||
service := LibraryPanelService{
|
||||
|
@ -85,7 +85,7 @@ func SetupTestEnv(tb testing.TB, baseInterval time.Duration) (*ngalert.AlertNG,
|
||||
|
||||
tracer := tracing.InitializeTracerForTest()
|
||||
bus := bus.ProvideBus(tracer)
|
||||
folderService := folderimpl.ProvideService(ac, bus, cfg, dashboardService, dashboardStore, nil, features, folderPermissions, nil)
|
||||
folderService := folderimpl.ProvideService(ac, bus, cfg, dashboardStore, nil, features, folderPermissions, nil)
|
||||
|
||||
ng, err := ngalert.ProvideService(
|
||||
cfg, featuremgmt.WithFeatures(), nil, nil, routing.NewRouteRegister(), sqlStore, nil, nil, nil, quotatest.New(false, nil),
|
||||
|
Reference in New Issue
Block a user