package dashboards import ( "context" "testing" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/dashboards" "github.com/grafana/grafana/pkg/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/grafana/grafana/pkg/services/guardian" ) func TestFolderService(t *testing.T) { t.Run("Folder service tests", func(t *testing.T) { service := dashboardServiceImpl{ orgId: 1, user: &models.SignedInUser{UserId: 1}, dashboardStore: &fakeDashboardStore{}, } t.Run("Given user has no permissions", func(t *testing.T) { origNewGuardian := guardian.New guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{}) bus.AddHandler("test", func(query *models.GetDashboardQuery) error { query.Result = models.NewDashboardFolder("Folder") return nil }) origStore := service.dashboardStore t.Cleanup(func() { service.dashboardStore = origStore }) service.dashboardStore = &fakeDashboardStore{ validationError: models.ErrDashboardUpdateAccessDenied, } t.Run("When get folder by id should return access denied error", func(t *testing.T) { _, err := service.GetFolderByID(context.Background(), 1) require.Equal(t, err, models.ErrFolderAccessDenied) }) t.Run("When get folder by id, with id = 0 should return default folder", func(t *testing.T) { folder, err := service.GetFolderByID(context.Background(), 0) require.NoError(t, err) require.Equal(t, folder, &models.Folder{Id: 0, Title: "General"}) }) t.Run("When get folder by uid should return access denied error", func(t *testing.T) { _, err := service.GetFolderByUID(context.Background(), "uid") require.Equal(t, err, models.ErrFolderAccessDenied) }) t.Run("When creating folder should return access denied error", func(t *testing.T) { _, err := service.CreateFolder(context.Background(), "Folder", "") require.Equal(t, err, models.ErrFolderAccessDenied) }) t.Run("When updating folder should return access denied error", func(t *testing.T) { err := service.UpdateFolder(context.Background(), "uid", &models.UpdateFolderCommand{ Uid: "uid", Title: "Folder", }) require.Equal(t, err, models.ErrFolderAccessDenied) }) t.Run("When deleting folder by uid should return access denied error", func(t *testing.T) { _, err := service.DeleteFolder(context.Background(), "uid", false) require.Error(t, err) require.Equal(t, err, models.ErrFolderAccessDenied) }) t.Cleanup(func() { guardian.New = origNewGuardian }) }) t.Run("Given user has permission to save", func(t *testing.T) { origNewGuardian := guardian.New guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanSaveValue: true}) dash := models.NewDashboardFolder("Folder") dash.Id = 1 bus.AddHandler("test", func(query *models.GetDashboardQuery) error { query.Result = dash return nil }) origUpdateAlerting := UpdateAlerting t.Cleanup(func() { UpdateAlerting = origUpdateAlerting }) UpdateAlerting = func(ctx context.Context, store dashboards.Store, orgID int64, dashboard *models.Dashboard, user *models.SignedInUser) error { return nil } bus.AddHandler("test", func(cmd *models.SaveDashboardCommand) error { cmd.Result = dash return nil }) bus.AddHandler("test", func(cmd *models.DeleteDashboardCommand) error { return nil }) t.Run("When creating folder should not return access denied error", func(t *testing.T) { _, err := service.CreateFolder(context.Background(), "Folder", "") require.NoError(t, err) }) t.Run("When updating folder should not return access denied error", func(t *testing.T) { err := service.UpdateFolder(context.Background(), "uid", &models.UpdateFolderCommand{ Uid: "uid", Title: "Folder", }) require.NoError(t, err) }) t.Run("When deleting folder by uid should not return access denied error", func(t *testing.T) { _, err := service.DeleteFolder(context.Background(), "uid", false) require.NoError(t, err) }) t.Cleanup(func() { guardian.New = origNewGuardian }) }) t.Run("Given user has permission to view", func(t *testing.T) { origNewGuardian := guardian.New guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{CanViewValue: true}) dashFolder := models.NewDashboardFolder("Folder") dashFolder.Id = 1 dashFolder.Uid = "uid-abc" bus.AddHandler("test", func(query *models.GetDashboardQuery) error { query.Result = dashFolder return nil }) t.Run("When get folder by id should return folder", func(t *testing.T) { f, _ := service.GetFolderByID(context.Background(), 1) require.Equal(t, f.Id, dashFolder.Id) require.Equal(t, f.Uid, dashFolder.Uid) require.Equal(t, f.Title, dashFolder.Title) }) t.Run("When get folder by uid should return folder", func(t *testing.T) { f, _ := service.GetFolderByUID(context.Background(), "uid") require.Equal(t, f.Id, dashFolder.Id) require.Equal(t, f.Uid, dashFolder.Uid) require.Equal(t, f.Title, dashFolder.Title) }) t.Cleanup(func() { guardian.New = origNewGuardian }) }) t.Run("Should map errors correct", func(t *testing.T) { testCases := []struct { ActualError error ExpectedError error }{ {ActualError: models.ErrDashboardTitleEmpty, ExpectedError: models.ErrFolderTitleEmpty}, {ActualError: models.ErrDashboardUpdateAccessDenied, ExpectedError: models.ErrFolderAccessDenied}, {ActualError: models.ErrDashboardWithSameNameInFolderExists, ExpectedError: models.ErrFolderSameNameExists}, {ActualError: models.ErrDashboardWithSameUIDExists, ExpectedError: models.ErrFolderWithSameUIDExists}, {ActualError: models.ErrDashboardVersionMismatch, ExpectedError: models.ErrFolderVersionMismatch}, {ActualError: models.ErrDashboardNotFound, ExpectedError: models.ErrFolderNotFound}, {ActualError: models.ErrDashboardFailedGenerateUniqueUid, ExpectedError: models.ErrFolderFailedGenerateUniqueUid}, {ActualError: models.ErrDashboardInvalidUid, ExpectedError: models.ErrDashboardInvalidUid}, } for _, tc := range testCases { actualError := toFolderError(tc.ActualError) assert.EqualErrorf(t, actualError, tc.ExpectedError.Error(), "For error '%s' expected error '%s', actual '%s'", tc.ActualError, tc.ExpectedError, actualError) } }) }) }