Chore: Move folder service into a separate package (#56591)
* Chore: move folder service interface into a separate package * copy implementation into a standalone package * move implementation and tests to the new folder package * remove leftovers from wire * add test doubles for folder service * fix tests in library panels/elements * fix provideservice in ngalert
This commit is contained in:
@@ -0,0 +1,320 @@
|
||||
package folderimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/events"
|
||||
"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"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
log log.Logger
|
||||
cfg *setting.Cfg
|
||||
dashboardService dashboards.DashboardService
|
||||
dashboardStore dashboards.Store
|
||||
searchService *search.SearchService
|
||||
features featuremgmt.FeatureToggles
|
||||
permissions accesscontrol.FolderPermissionsService
|
||||
|
||||
// bus is currently used to publish events that cause scheduler to update rules.
|
||||
bus bus.Bus
|
||||
}
|
||||
|
||||
func ProvideService(
|
||||
ac accesscontrol.AccessControl,
|
||||
bus bus.Bus,
|
||||
cfg *setting.Cfg,
|
||||
dashboardService dashboards.DashboardService,
|
||||
dashboardStore dashboards.Store,
|
||||
features featuremgmt.FeatureToggles,
|
||||
folderPermissionsService accesscontrol.FolderPermissionsService,
|
||||
searchService *search.SearchService,
|
||||
) folder.Service {
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderNameScopeResolver(dashboardStore))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(dashboardStore))
|
||||
return &Service{
|
||||
cfg: cfg,
|
||||
log: log.New("folder-service"),
|
||||
dashboardService: dashboardService,
|
||||
dashboardStore: dashboardStore,
|
||||
searchService: searchService,
|
||||
features: features,
|
||||
permissions: folderPermissionsService,
|
||||
bus: bus,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) GetFolders(ctx context.Context, user *user.SignedInUser, orgID int64, limit int64, page int64) ([]*models.Folder, error) {
|
||||
searchQuery := search.Query{
|
||||
SignedInUser: user,
|
||||
DashboardIds: make([]int64, 0),
|
||||
FolderIds: make([]int64, 0),
|
||||
Limit: limit,
|
||||
OrgId: orgID,
|
||||
Type: "dash-folder",
|
||||
Permission: models.PERMISSION_VIEW,
|
||||
Page: page,
|
||||
}
|
||||
|
||||
if err := s.searchService.SearchHandler(ctx, &searchQuery); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
folders := make([]*models.Folder, 0)
|
||||
|
||||
for _, hit := range searchQuery.Result {
|
||||
folders = append(folders, &models.Folder{
|
||||
Id: hit.ID,
|
||||
Uid: hit.UID,
|
||||
Title: hit.Title,
|
||||
})
|
||||
}
|
||||
|
||||
return folders, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetFolderByID(ctx context.Context, user *user.SignedInUser, id int64, orgID int64) (*models.Folder, error) {
|
||||
if id == 0 {
|
||||
return &models.Folder{Id: id, Title: "General"}, nil
|
||||
}
|
||||
dashFolder, err := s.dashboardStore.GetFolderByID(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g := guardian.New(ctx, dashFolder.Id, orgID, user)
|
||||
if canView, err := g.CanView(); err != nil || !canView {
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
return nil, dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
return dashFolder, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetFolderByUID(ctx context.Context, user *user.SignedInUser, orgID int64, uid string) (*models.Folder, error) {
|
||||
dashFolder, err := s.dashboardStore.GetFolderByUID(ctx, orgID, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g := guardian.New(ctx, dashFolder.Id, orgID, user)
|
||||
if canView, err := g.CanView(); err != nil || !canView {
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
return nil, dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
return dashFolder, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetFolderByTitle(ctx context.Context, user *user.SignedInUser, orgID int64, title string) (*models.Folder, error) {
|
||||
dashFolder, err := s.dashboardStore.GetFolderByTitle(ctx, orgID, title)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g := guardian.New(ctx, dashFolder.Id, orgID, user)
|
||||
if canView, err := g.CanView(); err != nil || !canView {
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
return nil, dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
return dashFolder, nil
|
||||
}
|
||||
|
||||
func (s *Service) CreateFolder(ctx context.Context, user *user.SignedInUser, orgID int64, title, uid string) (*models.Folder, error) {
|
||||
dashFolder := models.NewDashboardFolder(title)
|
||||
dashFolder.OrgId = orgID
|
||||
|
||||
trimmedUID := strings.TrimSpace(uid)
|
||||
if trimmedUID == accesscontrol.GeneralFolderUID {
|
||||
return nil, dashboards.ErrFolderInvalidUID
|
||||
}
|
||||
|
||||
dashFolder.SetUid(trimmedUID)
|
||||
userID := user.UserID
|
||||
if userID == 0 {
|
||||
userID = -1
|
||||
}
|
||||
dashFolder.CreatedBy = userID
|
||||
dashFolder.UpdatedBy = userID
|
||||
dashFolder.UpdateSlug()
|
||||
|
||||
dto := &dashboards.SaveDashboardDTO{
|
||||
Dashboard: dashFolder,
|
||||
OrgId: orgID,
|
||||
User: user,
|
||||
}
|
||||
|
||||
saveDashboardCmd, err := s.dashboardService.BuildSaveDashboardCommand(ctx, dto, false, false)
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
|
||||
dash, err := s.dashboardStore.SaveDashboard(ctx, *saveDashboardCmd)
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
|
||||
var folder *models.Folder
|
||||
folder, err = s.dashboardStore.GetFolderByID(ctx, orgID, dash.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var permissionErr error
|
||||
if !accesscontrol.IsDisabled(s.cfg) {
|
||||
var permissions []accesscontrol.SetResourcePermissionCommand
|
||||
if user.IsRealUser() && !user.IsAnonymous {
|
||||
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
|
||||
UserID: userID, Permission: models.PERMISSION_ADMIN.String(),
|
||||
})
|
||||
}
|
||||
|
||||
permissions = append(permissions, []accesscontrol.SetResourcePermissionCommand{
|
||||
{BuiltinRole: string(org.RoleEditor), Permission: models.PERMISSION_EDIT.String()},
|
||||
{BuiltinRole: string(org.RoleViewer), Permission: models.PERMISSION_VIEW.String()},
|
||||
}...)
|
||||
|
||||
_, permissionErr = s.permissions.SetPermissions(ctx, orgID, folder.Uid, permissions...)
|
||||
} else if s.cfg.EditorsCanAdmin && user.IsRealUser() && !user.IsAnonymous {
|
||||
permissionErr = s.MakeUserAdmin(ctx, orgID, userID, folder.Id, true)
|
||||
}
|
||||
|
||||
if permissionErr != nil {
|
||||
s.log.Error("Could not make user admin", "folder", folder.Title, "user", userID, "error", permissionErr)
|
||||
}
|
||||
|
||||
return folder, nil
|
||||
}
|
||||
|
||||
func (s *Service) UpdateFolder(ctx context.Context, user *user.SignedInUser, orgID int64, existingUid string, cmd *models.UpdateFolderCommand) error {
|
||||
query := models.GetDashboardQuery{OrgId: orgID, Uid: existingUid}
|
||||
if _, err := s.dashboardStore.GetDashboard(ctx, &query); err != nil {
|
||||
return toFolderError(err)
|
||||
}
|
||||
|
||||
dashFolder := query.Result
|
||||
currentTitle := dashFolder.Title
|
||||
|
||||
if !dashFolder.IsFolder {
|
||||
return dashboards.ErrFolderNotFound
|
||||
}
|
||||
|
||||
cmd.UpdateDashboardModel(dashFolder, orgID, user.UserID)
|
||||
|
||||
dto := &dashboards.SaveDashboardDTO{
|
||||
Dashboard: dashFolder,
|
||||
OrgId: orgID,
|
||||
User: user,
|
||||
Overwrite: cmd.Overwrite,
|
||||
}
|
||||
|
||||
saveDashboardCmd, err := s.dashboardService.BuildSaveDashboardCommand(ctx, dto, false, false)
|
||||
if err != nil {
|
||||
return toFolderError(err)
|
||||
}
|
||||
|
||||
dash, err := s.dashboardStore.SaveDashboard(ctx, *saveDashboardCmd)
|
||||
if err != nil {
|
||||
return toFolderError(err)
|
||||
}
|
||||
|
||||
var folder *models.Folder
|
||||
folder, err = s.dashboardStore.GetFolderByID(ctx, orgID, dash.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.Result = folder
|
||||
|
||||
if currentTitle != folder.Title {
|
||||
if err := s.bus.Publish(ctx, &events.FolderTitleUpdated{
|
||||
Timestamp: folder.Updated,
|
||||
Title: folder.Title,
|
||||
ID: dash.Id,
|
||||
UID: dash.Uid,
|
||||
OrgID: orgID,
|
||||
}); err != nil {
|
||||
s.log.Error("failed to publish FolderTitleUpdated event", "folder", folder.Title, "user", user.UserID, "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) DeleteFolder(ctx context.Context, user *user.SignedInUser, orgID int64, uid string, forceDeleteRules bool) (*models.Folder, error) {
|
||||
dashFolder, err := s.dashboardStore.GetFolderByUID(ctx, orgID, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
guard := guardian.New(ctx, dashFolder.Id, orgID, user)
|
||||
if canSave, err := guard.CanDelete(); err != nil || !canSave {
|
||||
if err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
return nil, dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
deleteCmd := models.DeleteDashboardCommand{OrgId: orgID, Id: dashFolder.Id, ForceDeleteFolderRules: forceDeleteRules}
|
||||
|
||||
if err := s.dashboardStore.DeleteDashboard(ctx, &deleteCmd); err != nil {
|
||||
return nil, toFolderError(err)
|
||||
}
|
||||
|
||||
return dashFolder, nil
|
||||
}
|
||||
|
||||
func (s *Service) MakeUserAdmin(ctx context.Context, orgID int64, userID, folderID int64, setViewAndEditPermissions bool) error {
|
||||
return s.dashboardService.MakeUserAdmin(ctx, orgID, userID, folderID, setViewAndEditPermissions)
|
||||
}
|
||||
|
||||
func toFolderError(err error) error {
|
||||
if errors.Is(err, dashboards.ErrDashboardTitleEmpty) {
|
||||
return dashboards.ErrFolderTitleEmpty
|
||||
}
|
||||
|
||||
if errors.Is(err, dashboards.ErrDashboardUpdateAccessDenied) {
|
||||
return dashboards.ErrFolderAccessDenied
|
||||
}
|
||||
|
||||
if errors.Is(err, dashboards.ErrDashboardWithSameNameInFolderExists) {
|
||||
return dashboards.ErrFolderSameNameExists
|
||||
}
|
||||
|
||||
if errors.Is(err, dashboards.ErrDashboardWithSameUIDExists) {
|
||||
return dashboards.ErrFolderWithSameUIDExists
|
||||
}
|
||||
|
||||
if errors.Is(err, dashboards.ErrDashboardVersionMismatch) {
|
||||
return dashboards.ErrFolderVersionMismatch
|
||||
}
|
||||
|
||||
if errors.Is(err, dashboards.ErrDashboardNotFound) {
|
||||
return dashboards.ErrFolderNotFound
|
||||
}
|
||||
|
||||
if errors.Is(err, dashboards.ErrDashboardFailedGenerateUniqueUid) {
|
||||
err = dashboards.ErrFolderFailedGenerateUniqueUid
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
package folderimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
busmock "github.com/grafana/grafana/pkg/bus/mock"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
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/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
var orgID = int64(1)
|
||||
var usr = &user.SignedInUser{UserID: 1}
|
||||
|
||||
func TestIntegrationProvideFolderService(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
t.Run("should register scope resolvers", func(t *testing.T) {
|
||||
cfg := setting.NewCfg()
|
||||
ac := acmock.New()
|
||||
|
||||
ProvideService(ac, busmock.New(), cfg, nil, nil, nil, nil, nil)
|
||||
|
||||
require.Len(t, ac.Calls.RegisterAttributeScopeResolver, 2)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntegrationFolderService(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
t.Run("Folder service tests", func(t *testing.T) {
|
||||
store := &dashboards.FakeDashboardStore{}
|
||||
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())
|
||||
|
||||
service := &Service{
|
||||
cfg: cfg,
|
||||
log: log.New("test-folder-service"),
|
||||
dashboardService: dashboardService,
|
||||
dashboardStore: store,
|
||||
searchService: nil,
|
||||
features: features,
|
||||
permissions: folderPermissions,
|
||||
bus: busmock.New(),
|
||||
}
|
||||
|
||||
t.Run("Given user has no permissions", func(t *testing.T) {
|
||||
origNewGuardian := guardian.New
|
||||
guardian.MockDashboardGuardian(&guardian.FakeDashboardGuardian{})
|
||||
|
||||
folderId := rand.Int63()
|
||||
folderUID := util.GenerateShortUID()
|
||||
|
||||
folder := models.NewFolder("Folder")
|
||||
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)
|
||||
|
||||
t.Run("When get folder by id should return access denied error", func(t *testing.T) {
|
||||
_, err := service.GetFolderByID(context.Background(), usr, folderId, orgID)
|
||||
require.Equal(t, err, dashboards.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(), usr, 0, orgID)
|
||||
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(), usr, orgID, folderUID)
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
t.Run("When creating folder should return access denied error", func(t *testing.T) {
|
||||
store.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).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) {
|
||||
folder := args.Get(1).(*models.GetDashboardQuery)
|
||||
folder.Result = models.NewDashboard("dashboard-test")
|
||||
folder.Result.IsFolder = true
|
||||
}).Return(&models.Dashboard{}, nil)
|
||||
err := service.UpdateFolder(context.Background(), usr, orgID, folderUID, &models.UpdateFolderCommand{
|
||||
Uid: folderUID,
|
||||
Title: "Folder-TEST",
|
||||
})
|
||||
require.Equal(t, err, dashboards.ErrFolderAccessDenied)
|
||||
})
|
||||
|
||||
t.Run("When deleting folder by uid should return access denied error", func(t *testing.T) {
|
||||
_, err := service.DeleteFolder(context.Background(), usr, orgID, folderUID, false)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, err, dashboards.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})
|
||||
|
||||
t.Run("When creating folder should not return access denied error", func(t *testing.T) {
|
||||
dash := models.NewDashboardFolder("Test-Folder")
|
||||
dash.Id = rand.Int63()
|
||||
f := models.DashboardToFolder(dash)
|
||||
|
||||
store.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil)
|
||||
store.On("SaveDashboard", mock.Anything).Return(dash, nil).Once()
|
||||
store.On("GetFolderByID", mock.Anything, orgID, dash.Id).Return(f, nil)
|
||||
|
||||
actualFolder, err := service.CreateFolder(context.Background(), usr, orgID, dash.Title, "")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, f, actualFolder)
|
||||
})
|
||||
|
||||
t.Run("When creating folder should return error if uid is general", func(t *testing.T) {
|
||||
dash := models.NewDashboardFolder("Test-Folder")
|
||||
dash.Id = rand.Int63()
|
||||
|
||||
_, err := service.CreateFolder(context.Background(), usr, orgID, dash.Title, "general")
|
||||
require.ErrorIs(t, err, dashboards.ErrFolderInvalidUID)
|
||||
})
|
||||
|
||||
t.Run("When updating folder should not return access denied error", func(t *testing.T) {
|
||||
dashboardFolder := models.NewDashboardFolder("Folder")
|
||||
dashboardFolder.Id = rand.Int63()
|
||||
dashboardFolder.Uid = util.GenerateShortUID()
|
||||
f := models.DashboardToFolder(dashboardFolder)
|
||||
|
||||
store.On("ValidateDashboardBeforeSave", mock.Anything, mock.Anything).Return(true, nil)
|
||||
store.On("SaveDashboard", mock.Anything).Return(dashboardFolder, nil)
|
||||
store.On("GetFolderByID", mock.Anything, orgID, dashboardFolder.Id).Return(f, nil)
|
||||
|
||||
req := &models.UpdateFolderCommand{
|
||||
Uid: dashboardFolder.Uid,
|
||||
Title: "TEST-Folder",
|
||||
}
|
||||
|
||||
err := service.UpdateFolder(context.Background(), usr, orgID, dashboardFolder.Uid, req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, f, req.Result)
|
||||
})
|
||||
|
||||
t.Run("When deleting folder by uid should not return access denied error", func(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)
|
||||
|
||||
var actualCmd *models.DeleteDashboardCommand
|
||||
store.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
actualCmd = args.Get(1).(*models.DeleteDashboardCommand)
|
||||
}).Return(nil).Once()
|
||||
|
||||
expectedForceDeleteRules := rand.Int63()%2 == 0
|
||||
_, err := service.DeleteFolder(context.Background(), usr, orgID, f.Uid, expectedForceDeleteRules)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
require.Equal(t, f.Id, actualCmd.Id)
|
||||
require.Equal(t, orgID, actualCmd.OrgId)
|
||||
require.Equal(t, expectedForceDeleteRules, actualCmd.ForceDeleteFolderRules)
|
||||
})
|
||||
|
||||
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})
|
||||
|
||||
t.Run("When get folder by id should return folder", func(t *testing.T) {
|
||||
expected := models.NewFolder(util.GenerateShortUID())
|
||||
expected.Id = rand.Int63()
|
||||
|
||||
store.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)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("When get folder by uid should return folder", func(t *testing.T) {
|
||||
expected := models.NewFolder(util.GenerateShortUID())
|
||||
expected.Uid = util.GenerateShortUID()
|
||||
|
||||
store.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)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
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)
|
||||
|
||||
actual, err := service.GetFolderByTitle(context.Background(), usr, orgID, expected.Title)
|
||||
require.Equal(t, expected, actual)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Cleanup(func() {
|
||||
guardian.New = origNewGuardian
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Should map errors correct", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ActualError error
|
||||
ExpectedError error
|
||||
}{
|
||||
{ActualError: dashboards.ErrDashboardTitleEmpty, ExpectedError: dashboards.ErrFolderTitleEmpty},
|
||||
{ActualError: dashboards.ErrDashboardUpdateAccessDenied, ExpectedError: dashboards.ErrFolderAccessDenied},
|
||||
{ActualError: dashboards.ErrDashboardWithSameNameInFolderExists, ExpectedError: dashboards.ErrFolderSameNameExists},
|
||||
{ActualError: dashboards.ErrDashboardWithSameUIDExists, ExpectedError: dashboards.ErrFolderWithSameUIDExists},
|
||||
{ActualError: dashboards.ErrDashboardVersionMismatch, ExpectedError: dashboards.ErrFolderVersionMismatch},
|
||||
{ActualError: dashboards.ErrDashboardNotFound, ExpectedError: dashboards.ErrFolderNotFound},
|
||||
{ActualError: dashboards.ErrDashboardFailedGenerateUniqueUid, ExpectedError: dashboards.ErrFolderFailedGenerateUniqueUid},
|
||||
{ActualError: dashboards.ErrDashboardInvalidUid, ExpectedError: dashboards.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)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user