mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Split folder store and dashboard store interfaces (#61655)
* update folder store mock * Split folder store and dashboard store interfaces
This commit is contained in:
parent
a6102105af
commit
c104cc7020
@ -432,7 +432,7 @@ func setupHTTPServerWithCfgDb(
|
||||
teamPermissionsService: teamPermissionService,
|
||||
searchUsersService: searchusers.ProvideUsersService(filters.ProvideOSSSearchUserFilter(), usertest.NewUserServiceFake()),
|
||||
DashboardService: dashboardservice.ProvideDashboardService(
|
||||
cfg, dashboardsStore, nil, features,
|
||||
cfg, dashboardsStore, dashboardsStore, nil, features,
|
||||
folderPermissionsService, dashboardPermissionsService, ac,
|
||||
),
|
||||
preferenceService: preftest.NewPreferenceServiceFake(),
|
||||
|
@ -47,7 +47,7 @@ func TestDashboardPermissionAPIEndpoint(t *testing.T) {
|
||||
SQLStore: mockSQLStore,
|
||||
Features: features,
|
||||
DashboardService: dashboardservice.ProvideDashboardService(
|
||||
settings, dashboardStore, nil, features, folderPermissions, dashboardPermissions, ac,
|
||||
settings, dashboardStore, dashboards.NewFakeFolderStore(t), nil, features, folderPermissions, dashboardPermissions, ac,
|
||||
),
|
||||
AccessControl: accesscontrolmock.New().WithDisabled(),
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
"/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
||||
setUp()
|
||||
sc.sqlStore = mockSQLStore
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService)
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService, nil)
|
||||
|
||||
assert.False(t, dash.Meta.CanEdit)
|
||||
assert.False(t, dash.Meta.CanSave)
|
||||
@ -209,7 +209,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
"/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
||||
setUp()
|
||||
sc.sqlStore = mockSQLStore
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService)
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService, nil)
|
||||
|
||||
assert.True(t, dash.Meta.CanEdit)
|
||||
assert.True(t, dash.Meta.CanSave)
|
||||
@ -393,7 +393,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
"/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
||||
setUpInner()
|
||||
sc.sqlStore = mockSQLStore
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService)
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService, nil)
|
||||
|
||||
assert.True(t, dash.Meta.CanEdit)
|
||||
assert.True(t, dash.Meta.CanSave)
|
||||
@ -456,7 +456,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
|
||||
require.True(t, setting.ViewersCanEdit)
|
||||
sc.sqlStore = mockSQLStore
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService)
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService, nil)
|
||||
|
||||
assert.True(t, dash.Meta.CanEdit)
|
||||
assert.False(t, dash.Meta.CanSave)
|
||||
@ -494,7 +494,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/abcdefghi", "/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
||||
setUpInner()
|
||||
sc.sqlStore = mockSQLStore
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService)
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService, nil)
|
||||
|
||||
assert.True(t, dash.Meta.CanEdit)
|
||||
assert.True(t, dash.Meta.CanSave)
|
||||
@ -547,7 +547,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
loggedInUserScenarioWithRole(t, "When calling GET on", "GET", "/api/dashboards/uid/abcdefghi", "/api/dashboards/uid/:uid", role, func(sc *scenarioContext) {
|
||||
setUpInner()
|
||||
sc.sqlStore = mockSQLStore
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService)
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, nil, nil, dashboardService, nil)
|
||||
|
||||
assert.False(t, dash.Meta.CanEdit)
|
||||
assert.False(t, dash.Meta.CanSave)
|
||||
@ -952,7 +952,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
return "/tmp/grafana/dashboards"
|
||||
}
|
||||
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, fakeProvisioningService, dashboardStore, dashboardService)
|
||||
dash := getDashboardShouldReturn200WithConfig(t, sc, fakeProvisioningService, dashboardStore, dashboardService, nil)
|
||||
|
||||
assert.Equal(t, "../../../dashboard1.json", dash.Meta.ProvisionedExternalId, mockSQLStore)
|
||||
}, mockSQLStore)
|
||||
@ -992,7 +992,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, provisioningService provisioning.ProvisioningService, dashboardStore dashboards.Store, dashboardService dashboards.DashboardService) dtos.DashboardFullWithMeta {
|
||||
func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, provisioningService provisioning.ProvisioningService, dashboardStore dashboards.Store, dashboardService dashboards.DashboardService, folderStore dashboards.FolderStore) dtos.DashboardFullWithMeta {
|
||||
t.Helper()
|
||||
|
||||
if provisioningService == nil {
|
||||
@ -1017,7 +1017,7 @@ func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, pr
|
||||
|
||||
if dashboardService == nil {
|
||||
dashboardService = service.ProvideDashboardService(
|
||||
cfg, dashboardStore, nil, features,
|
||||
cfg, dashboardStore, folderStore, nil, features,
|
||||
folderPermissions, dashboardPermissions, ac,
|
||||
)
|
||||
}
|
||||
@ -1030,7 +1030,7 @@ func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, pr
|
||||
ProvisioningService: provisioningService,
|
||||
AccessControl: accesscontrolmock.New(),
|
||||
dashboardProvisioningService: service.ProvideDashboardService(
|
||||
cfg, dashboardStore, nil, features,
|
||||
cfg, dashboardStore, folderStore, nil, features,
|
||||
folderPermissions, dashboardPermissions, ac,
|
||||
),
|
||||
DashboardService: dashboardService,
|
||||
|
@ -45,7 +45,7 @@ func TestFolderPermissionAPIEndpoint(t *testing.T) {
|
||||
folderPermissionsService: folderPermissions,
|
||||
dashboardPermissionsService: dashboardPermissions,
|
||||
DashboardService: service.ProvideDashboardService(
|
||||
settings, dashboardStore, nil, features, folderPermissions, dashboardPermissions, ac,
|
||||
settings, dashboardStore, dashboards.NewFakeFolderStore(t), nil, features, folderPermissions, dashboardPermissions, ac,
|
||||
),
|
||||
AccessControl: accesscontrolmock.New().WithDisabled(),
|
||||
}
|
||||
|
@ -257,6 +257,7 @@ var wireSet = wire.NewSet(
|
||||
wire.Bind(new(dashboards.DashboardProvisioningService), new(*dashboardservice.DashboardServiceImpl)),
|
||||
wire.Bind(new(dashboards.PluginService), new(*dashboardservice.DashboardServiceImpl)),
|
||||
wire.Bind(new(dashboards.Store), new(*dashboardstore.DashboardStore)),
|
||||
wire.Bind(new(dashboards.FolderStore), new(*dashboardstore.DashboardStore)),
|
||||
dashboardimportservice.ProvideService,
|
||||
wire.Bind(new(dashboardimport.Service), new(*dashboardimportservice.ImportDashboardService)),
|
||||
plugindashboardsservice.ProvideService,
|
||||
|
@ -293,6 +293,7 @@ var wireBasicSet = wire.NewSet(
|
||||
wire.Bind(new(dashboards.DashboardProvisioningService), new(*dashboardservice.DashboardServiceImpl)),
|
||||
wire.Bind(new(dashboards.PluginService), new(*dashboardservice.DashboardServiceImpl)),
|
||||
wire.Bind(new(dashboards.Store), new(*dashboardstore.DashboardStore)),
|
||||
wire.Bind(new(dashboards.FolderStore), new(*dashboardstore.DashboardStore)),
|
||||
dashboardimportservice.ProvideService,
|
||||
wire.Bind(new(dashboardimport.Service), new(*dashboardimportservice.ImportDashboardService)),
|
||||
plugindashboardsservice.ProvideService,
|
||||
|
@ -38,7 +38,7 @@ var (
|
||||
)
|
||||
|
||||
// NewFolderNameScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "folders:name:" into an uid based scope.
|
||||
func NewFolderNameScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
func NewFolderNameScopeResolver(db Store, folderDB FolderStore) (string, ac.ScopeAttributeResolver) {
|
||||
prefix := ScopeFoldersProvider.GetResourceScopeName("")
|
||||
return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) {
|
||||
if !strings.HasPrefix(scope, prefix) {
|
||||
@ -48,7 +48,7 @@ func NewFolderNameScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
if len(nsName) == 0 {
|
||||
return nil, ac.ErrInvalidScope
|
||||
}
|
||||
folder, err := db.GetFolderByTitle(ctx, orgID, nsName)
|
||||
folder, err := folderDB.GetFolderByTitle(ctx, orgID, nsName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -57,7 +57,7 @@ func NewFolderNameScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
}
|
||||
|
||||
// NewFolderIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "folders:id:" into an uid based scope.
|
||||
func NewFolderIDScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
func NewFolderIDScopeResolver(db Store, folderDB FolderStore) (string, ac.ScopeAttributeResolver) {
|
||||
prefix := ScopeFoldersProvider.GetResourceScope("")
|
||||
return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) {
|
||||
if !strings.HasPrefix(scope, prefix) {
|
||||
@ -73,7 +73,7 @@ func NewFolderIDScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
return []string{ScopeFoldersProvider.GetResourceScopeUID(ac.GeneralFolderUID)}, nil
|
||||
}
|
||||
|
||||
folder, err := db.GetFolderByID(ctx, orgID, id)
|
||||
folder, err := folderDB.GetFolderByID(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -84,7 +84,7 @@ func NewFolderIDScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
|
||||
// NewDashboardIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "dashboards:id:"
|
||||
// into uid based scopes for both dashboard and folder
|
||||
func NewDashboardIDScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
func NewDashboardIDScopeResolver(db Store, folderDB FolderStore) (string, ac.ScopeAttributeResolver) {
|
||||
prefix := ScopeDashboardsProvider.GetResourceScope("")
|
||||
return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) {
|
||||
if !strings.HasPrefix(scope, prefix) {
|
||||
@ -101,13 +101,13 @@ func NewDashboardIDScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resolveDashboardScope(ctx, db, orgID, dashboard)
|
||||
return resolveDashboardScope(ctx, db, folderDB, orgID, dashboard)
|
||||
})
|
||||
}
|
||||
|
||||
// NewDashboardUIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "dashboards:uid:"
|
||||
// into uid based scopes for both dashboard and folder
|
||||
func NewDashboardUIDScopeResolver(db Store) (string, ac.ScopeAttributeResolver) {
|
||||
func NewDashboardUIDScopeResolver(db Store, folderDB FolderStore) (string, ac.ScopeAttributeResolver) {
|
||||
prefix := ScopeDashboardsProvider.GetResourceScopeUID("")
|
||||
return prefix, ac.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, scope string) ([]string, error) {
|
||||
if !strings.HasPrefix(scope, prefix) {
|
||||
@ -124,11 +124,11 @@ func NewDashboardUIDScopeResolver(db Store) (string, ac.ScopeAttributeResolver)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resolveDashboardScope(ctx, db, orgID, dashboard)
|
||||
return resolveDashboardScope(ctx, db, folderDB, orgID, dashboard)
|
||||
})
|
||||
}
|
||||
|
||||
func resolveDashboardScope(ctx context.Context, db Store, orgID int64, dashboard *Dashboard) ([]string, error) {
|
||||
func resolveDashboardScope(ctx context.Context, db Store, folderDB FolderStore, orgID int64, dashboard *Dashboard) ([]string, error) {
|
||||
var folderUID string
|
||||
if dashboard.FolderID < 0 {
|
||||
return []string{ScopeDashboardsProvider.GetResourceScopeUID(dashboard.UID)}, nil
|
||||
@ -137,7 +137,7 @@ func resolveDashboardScope(ctx context.Context, db Store, orgID int64, dashboard
|
||||
if dashboard.FolderID == 0 {
|
||||
folderUID = ac.GeneralFolderUID
|
||||
} else {
|
||||
folder, err := db.GetFolderByID(ctx, orgID, dashboard.FolderID)
|
||||
folder, err := folderDB.GetFolderByID(ctx, orgID, dashboard.FolderID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -17,41 +17,42 @@ import (
|
||||
|
||||
func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
t.Run("prefix should be expected", func(t *testing.T) {
|
||||
prefix, _ := NewFolderNameScopeResolver(&FakeDashboardStore{})
|
||||
prefix, _ := NewFolderNameScopeResolver(&FakeDashboardStore{}, NewFakeFolderStore(t))
|
||||
require.Equal(t, "folders:name:", prefix)
|
||||
})
|
||||
|
||||
t.Run("resolver should convert to uid scope", func(t *testing.T) {
|
||||
dashboardStore := &FakeDashboardStore{}
|
||||
|
||||
_, resolver := NewFolderNameScopeResolver(dashboardStore)
|
||||
|
||||
orgId := rand.Int63()
|
||||
title := "Very complex :title with: and /" + util.GenerateShortUID()
|
||||
|
||||
db := &folder.Folder{Title: title, ID: rand.Int63(), UID: util.GenerateShortUID()}
|
||||
dashboardStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything).Return(db, nil).Once()
|
||||
|
||||
folderStore := NewFakeFolderStore(t)
|
||||
folderStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything).Return(db, nil).Once()
|
||||
|
||||
scope := "folders:name:" + title
|
||||
|
||||
_, resolver := NewFolderNameScopeResolver(dashboardStore, folderStore)
|
||||
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, resolvedScopes, 1)
|
||||
|
||||
require.Equal(t, fmt.Sprintf("folders:uid:%v", db.UID), resolvedScopes[0])
|
||||
|
||||
dashboardStore.AssertCalled(t, "GetFolderByTitle", mock.Anything, orgId, title)
|
||||
folderStore.AssertCalled(t, "GetFolderByTitle", mock.Anything, orgId, title)
|
||||
})
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
dashboardStore := &FakeDashboardStore{}
|
||||
_, resolver := NewFolderNameScopeResolver(dashboardStore)
|
||||
_, resolver := NewFolderNameScopeResolver(dashboardStore, NewFakeFolderStore(t))
|
||||
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:id:123")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
})
|
||||
t.Run("resolver should fail if resource of input scope is empty", func(t *testing.T) {
|
||||
dashboardStore := &FakeDashboardStore{}
|
||||
_, resolver := NewFolderNameScopeResolver(dashboardStore)
|
||||
_, resolver := NewFolderNameScopeResolver(dashboardStore, NewFakeFolderStore(t))
|
||||
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:name:")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
@ -59,10 +60,11 @@ func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
t.Run("returns 'not found' if folder does not exist", func(t *testing.T) {
|
||||
dashboardStore := &FakeDashboardStore{}
|
||||
|
||||
_, resolver := NewFolderNameScopeResolver(dashboardStore)
|
||||
folderStore := NewFakeFolderStore(t)
|
||||
_, resolver := NewFolderNameScopeResolver(dashboardStore, folderStore)
|
||||
|
||||
orgId := rand.Int63()
|
||||
dashboardStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once()
|
||||
folderStore.On("GetFolderByTitle", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once()
|
||||
|
||||
scope := "folders:name:" + util.GenerateShortUID()
|
||||
|
||||
@ -74,20 +76,21 @@ func TestNewFolderNameScopeResolver(t *testing.T) {
|
||||
|
||||
func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
t.Run("prefix should be expected", func(t *testing.T) {
|
||||
prefix, _ := NewFolderIDScopeResolver(&FakeDashboardStore{})
|
||||
prefix, _ := NewFolderIDScopeResolver(&FakeDashboardStore{}, NewFakeFolderStore(t))
|
||||
require.Equal(t, "folders:id:", prefix)
|
||||
})
|
||||
|
||||
t.Run("resolver should convert to uid scope", func(t *testing.T) {
|
||||
dashboardStore := &FakeDashboardStore{}
|
||||
folderStore := NewFakeFolderStore(t)
|
||||
|
||||
_, resolver := NewFolderIDScopeResolver(dashboardStore)
|
||||
_, resolver := NewFolderIDScopeResolver(dashboardStore, folderStore)
|
||||
|
||||
orgId := rand.Int63()
|
||||
uid := util.GenerateShortUID()
|
||||
|
||||
db := &folder.Folder{ID: rand.Int63(), UID: uid}
|
||||
dashboardStore.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(db, nil).Once()
|
||||
folderStore.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(db, nil).Once()
|
||||
|
||||
scope := "folders:id:" + strconv.FormatInt(db.ID, 10)
|
||||
|
||||
@ -96,11 +99,11 @@ func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
require.Len(t, resolvedScopes, 1)
|
||||
require.Equal(t, fmt.Sprintf("folders:uid:%v", db.UID), resolvedScopes[0])
|
||||
|
||||
dashboardStore.AssertCalled(t, "GetFolderByID", mock.Anything, orgId, db.ID)
|
||||
folderStore.AssertCalled(t, "GetFolderByID", mock.Anything, orgId, db.ID)
|
||||
})
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
dashboardStore := &FakeDashboardStore{}
|
||||
_, resolver := NewFolderIDScopeResolver(dashboardStore)
|
||||
_, resolver := NewFolderIDScopeResolver(dashboardStore, NewFakeFolderStore(t))
|
||||
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:uid:123")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
@ -111,7 +114,7 @@ func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
dashboardStore = &FakeDashboardStore{}
|
||||
orgId = rand.Int63()
|
||||
scope = "folders:id:0"
|
||||
_, resolver = NewFolderIDScopeResolver(dashboardStore)
|
||||
_, resolver = NewFolderIDScopeResolver(dashboardStore, NewFakeFolderStore(t))
|
||||
)
|
||||
|
||||
resolved, err := resolver.Resolve(context.Background(), orgId, scope)
|
||||
@ -123,18 +126,19 @@ func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
|
||||
t.Run("resolver should fail if resource of input scope is empty", func(t *testing.T) {
|
||||
dashboardStore := &FakeDashboardStore{}
|
||||
_, resolver := NewFolderIDScopeResolver(dashboardStore)
|
||||
_, resolver := NewFolderIDScopeResolver(dashboardStore, NewFakeFolderStore(t))
|
||||
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "folders:id:")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
})
|
||||
t.Run("returns 'not found' if folder does not exist", func(t *testing.T) {
|
||||
dashboardStore := &FakeDashboardStore{}
|
||||
folderStore := NewFakeFolderStore(t)
|
||||
|
||||
_, resolver := NewFolderIDScopeResolver(dashboardStore)
|
||||
_, resolver := NewFolderIDScopeResolver(dashboardStore, folderStore)
|
||||
|
||||
orgId := rand.Int63()
|
||||
dashboardStore.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once()
|
||||
folderStore.On("GetFolderByID", mock.Anything, mock.Anything, mock.Anything).Return(nil, ErrDashboardNotFound).Once()
|
||||
|
||||
scope := "folders:id:10"
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgId, scope)
|
||||
@ -145,21 +149,22 @@ func TestNewFolderIDScopeResolver(t *testing.T) {
|
||||
|
||||
func TestNewDashboardIDScopeResolver(t *testing.T) {
|
||||
t.Run("prefix should be expected", func(t *testing.T) {
|
||||
prefix, _ := NewDashboardIDScopeResolver(&FakeDashboardStore{})
|
||||
prefix, _ := NewDashboardIDScopeResolver(&FakeDashboardStore{}, NewFakeFolderStore(t))
|
||||
require.Equal(t, "dashboards:id:", prefix)
|
||||
})
|
||||
|
||||
t.Run("resolver should convert to uid dashboard and folder scope", func(t *testing.T) {
|
||||
store := &FakeDashboardStore{}
|
||||
folderStore := NewFakeFolderStore(t)
|
||||
|
||||
_, resolver := NewDashboardIDScopeResolver(store)
|
||||
_, resolver := NewDashboardIDScopeResolver(store, folderStore)
|
||||
|
||||
orgID := rand.Int63()
|
||||
folder := &folder.Folder{ID: 2, UID: "2"}
|
||||
dashboard := &Dashboard{ID: 1, FolderID: folder.ID, UID: "1"}
|
||||
|
||||
store.On("GetDashboard", mock.Anything, mock.Anything).Return(dashboard, nil).Once()
|
||||
store.On("GetFolderByID", mock.Anything, orgID, folder.ID).Return(folder, nil).Once()
|
||||
folderStore.On("GetFolderByID", mock.Anything, orgID, folder.ID).Return(folder, nil).Once()
|
||||
|
||||
scope := ac.Scope("dashboards", "id", strconv.FormatInt(dashboard.ID, 10))
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgID, scope)
|
||||
@ -170,14 +175,14 @@ func TestNewDashboardIDScopeResolver(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
_, resolver := NewDashboardIDScopeResolver(&FakeDashboardStore{})
|
||||
_, resolver := NewDashboardIDScopeResolver(&FakeDashboardStore{}, NewFakeFolderStore(t))
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "dashboards:uid:123")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
})
|
||||
|
||||
t.Run("resolver should convert folderID 0 to general uid scope for the folder scope", func(t *testing.T) {
|
||||
store := &FakeDashboardStore{}
|
||||
_, resolver := NewDashboardIDScopeResolver(store)
|
||||
_, resolver := NewDashboardIDScopeResolver(store, NewFakeFolderStore(t))
|
||||
|
||||
dashboard := &Dashboard{ID: 1, FolderID: 0, UID: "1"}
|
||||
store.On("GetDashboard", mock.Anything, mock.Anything).Return(dashboard, nil)
|
||||
@ -192,20 +197,21 @@ func TestNewDashboardIDScopeResolver(t *testing.T) {
|
||||
|
||||
func TestNewDashboardUIDScopeResolver(t *testing.T) {
|
||||
t.Run("prefix should be expected", func(t *testing.T) {
|
||||
prefix, _ := NewDashboardUIDScopeResolver(&FakeDashboardStore{})
|
||||
prefix, _ := NewDashboardUIDScopeResolver(&FakeDashboardStore{}, NewFakeFolderStore(t))
|
||||
require.Equal(t, "dashboards:uid:", prefix)
|
||||
})
|
||||
|
||||
t.Run("resolver should convert to uid dashboard and folder scope", func(t *testing.T) {
|
||||
store := &FakeDashboardStore{}
|
||||
_, resolver := NewDashboardUIDScopeResolver(store)
|
||||
folderStore := NewFakeFolderStore(t)
|
||||
_, resolver := NewDashboardUIDScopeResolver(store, folderStore)
|
||||
|
||||
orgID := rand.Int63()
|
||||
folder := &folder.Folder{ID: 2, UID: "2"}
|
||||
dashboard := &Dashboard{ID: 1, FolderID: folder.ID, UID: "1"}
|
||||
|
||||
store.On("GetDashboard", mock.Anything, mock.Anything).Return(dashboard, nil).Once()
|
||||
store.On("GetFolderByID", mock.Anything, orgID, folder.ID).Return(folder, nil).Once()
|
||||
folderStore.On("GetFolderByID", mock.Anything, orgID, folder.ID).Return(folder, nil).Once()
|
||||
|
||||
scope := ac.Scope("dashboards", "uid", dashboard.UID)
|
||||
resolvedScopes, err := resolver.Resolve(context.Background(), orgID, scope)
|
||||
@ -216,14 +222,14 @@ func TestNewDashboardUIDScopeResolver(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("resolver should fail if input scope is not expected", func(t *testing.T) {
|
||||
_, resolver := NewDashboardUIDScopeResolver(&FakeDashboardStore{})
|
||||
_, resolver := NewDashboardUIDScopeResolver(&FakeDashboardStore{}, NewFakeFolderStore(t))
|
||||
_, err := resolver.Resolve(context.Background(), rand.Int63(), "dashboards:id:123")
|
||||
require.ErrorIs(t, err, ac.ErrInvalidScope)
|
||||
})
|
||||
|
||||
t.Run("resolver should convert folderID 0 to general uid scope for the folder scope", func(t *testing.T) {
|
||||
store := &FakeDashboardStore{}
|
||||
_, resolver := NewDashboardUIDScopeResolver(store)
|
||||
_, resolver := NewDashboardUIDScopeResolver(store, NewFakeFolderStore(t))
|
||||
|
||||
dashboard := &Dashboard{ID: 1, FolderID: 0, UID: "1"}
|
||||
store.On("GetDashboard", mock.Anything, mock.Anything).Return(dashboard, nil)
|
||||
|
@ -83,8 +83,6 @@ type Store interface {
|
||||
// CountDashboardsInFolder returns the number of dashboards associated with
|
||||
// the given parent folder ID.
|
||||
CountDashboardsInFolder(ctx context.Context, request *CountDashboardsInFolderRequest) (int64, error)
|
||||
|
||||
FolderStore
|
||||
}
|
||||
|
||||
// FolderStore is a folder store.
|
||||
|
@ -37,6 +37,7 @@ type DashboardServiceImpl struct {
|
||||
cfg *setting.Cfg
|
||||
log log.Logger
|
||||
dashboardStore dashboards.Store
|
||||
folderStore dashboards.FolderStore
|
||||
dashAlertExtractor alerting.DashAlertExtractor
|
||||
features featuremgmt.FeatureToggles
|
||||
folderPermissions accesscontrol.FolderPermissionsService
|
||||
@ -45,17 +46,17 @@ type DashboardServiceImpl struct {
|
||||
}
|
||||
|
||||
func ProvideDashboardService(
|
||||
cfg *setting.Cfg, store dashboards.Store, dashAlertExtractor alerting.DashAlertExtractor,
|
||||
cfg *setting.Cfg, dashboardStore dashboards.Store, folderStore dashboards.FolderStore, dashAlertExtractor alerting.DashAlertExtractor,
|
||||
features featuremgmt.FeatureToggles, folderPermissionsService accesscontrol.FolderPermissionsService,
|
||||
dashboardPermissionsService accesscontrol.DashboardPermissionsService, ac accesscontrol.AccessControl,
|
||||
) *DashboardServiceImpl {
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardIDScopeResolver(store))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardUIDScopeResolver(store))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardIDScopeResolver(dashboardStore, folderStore))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardUIDScopeResolver(dashboardStore, folderStore))
|
||||
|
||||
return &DashboardServiceImpl{
|
||||
cfg: cfg,
|
||||
log: log.New("dashboard-service"),
|
||||
dashboardStore: store,
|
||||
dashboardStore: dashboardStore,
|
||||
dashAlertExtractor: dashAlertExtractor,
|
||||
features: features,
|
||||
folderPermissions: folderPermissionsService,
|
||||
@ -623,7 +624,7 @@ func (dr DashboardServiceImpl) CountDashboardsInFolder(ctx context.Context, quer
|
||||
return 0, err
|
||||
}
|
||||
|
||||
folder, err := dr.dashboardStore.GetFolderByUID(ctx, u.OrgID, query.FolderUID)
|
||||
folder, err := dr.folderStore.GetFolderByUID(ctx, u.OrgID, query.FolderUID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -826,7 +826,7 @@ func permissionScenario(t *testing.T, desc string, canSave bool, fn permissionSc
|
||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
service := ProvideDashboardService(
|
||||
cfg, dashboardStore, &dummyDashAlertExtractor{},
|
||||
cfg, dashboardStore, dashboardStore, &dummyDashAlertExtractor{},
|
||||
featuremgmt.WithFeatures(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
@ -885,7 +885,7 @@ func callSaveWithResult(t *testing.T, cmd dashboards.SaveDashboardCommand, sqlSt
|
||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
service := ProvideDashboardService(
|
||||
cfg, dashboardStore, &dummyDashAlertExtractor{},
|
||||
cfg, dashboardStore, dashboardStore, &dummyDashAlertExtractor{},
|
||||
featuremgmt.WithFeatures(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
@ -906,7 +906,7 @@ func callSaveWithError(t *testing.T, cmd dashboards.SaveDashboardCommand, sqlSto
|
||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
service := ProvideDashboardService(
|
||||
cfg, dashboardStore, &dummyDashAlertExtractor{},
|
||||
cfg, dashboardStore, dashboardStore, &dummyDashAlertExtractor{},
|
||||
featuremgmt.WithFeatures(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
@ -945,7 +945,7 @@ func saveTestDashboard(t *testing.T, title string, orgID, folderID int64, sqlSto
|
||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
service := ProvideDashboardService(
|
||||
cfg, dashboardStore, &dummyDashAlertExtractor{},
|
||||
cfg, dashboardStore, dashboardStore, &dummyDashAlertExtractor{},
|
||||
featuremgmt.WithFeatures(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
@ -985,7 +985,7 @@ func saveTestFolder(t *testing.T, title string, orgID int64, sqlStore db.DB) *da
|
||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
service := ProvideDashboardService(
|
||||
cfg, dashboardStore, &dummyDashAlertExtractor{},
|
||||
cfg, dashboardStore, dashboardStore, &dummyDashAlertExtractor{},
|
||||
featuremgmt.WithFeatures(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
|
@ -25,10 +25,13 @@ func TestDashboardService(t *testing.T) {
|
||||
fakeStore := dashboards.FakeDashboardStore{}
|
||||
defer fakeStore.AssertExpectations(t)
|
||||
|
||||
folderStore := dashboards.NewFakeFolderStore(t)
|
||||
|
||||
service := &DashboardServiceImpl{
|
||||
cfg: setting.NewCfg(),
|
||||
log: log.New("test.logger"),
|
||||
dashboardStore: &fakeStore,
|
||||
folderStore: folderStore,
|
||||
dashAlertExtractor: &dummyDashAlertExtractor{},
|
||||
}
|
||||
|
||||
@ -227,7 +230,7 @@ func TestDashboardService(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Count dashboards in folder", func(t *testing.T) {
|
||||
fakeStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
folderStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
fakeStore.On("CountDashboardsInFolder", mock.Anything, mock.AnythingOfType("*dashboards.CountDashboardsInFolderRequest")).Return(int64(3), nil)
|
||||
|
||||
// set up a ctx with signed in user
|
||||
|
@ -5,10 +5,8 @@ package dashboards
|
||||
import (
|
||||
context "context"
|
||||
|
||||
folder "github.com/grafana/grafana/pkg/services/folder"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
models "github.com/grafana/grafana/pkg/models"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
quota "github.com/grafana/grafana/pkg/services/quota"
|
||||
)
|
||||
@ -220,75 +218,6 @@ func (_m *FakeDashboardStore) GetDashboardsByPluginID(ctx context.Context, query
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetFolderByID provides a mock function with given fields: ctx, orgID, id
|
||||
func (_m *FakeDashboardStore) GetFolderByID(ctx context.Context, orgID int64, id int64) (*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, orgID, id)
|
||||
|
||||
var r0 *folder.Folder
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, int64) *folder.Folder); ok {
|
||||
r0 = rf(ctx, orgID, id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*folder.Folder)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int64, int64) error); ok {
|
||||
r1 = rf(ctx, orgID, id)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetFolderByTitle provides a mock function with given fields: ctx, orgID, title
|
||||
func (_m *FakeDashboardStore) GetFolderByTitle(ctx context.Context, orgID int64, title string) (*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, orgID, title)
|
||||
|
||||
var r0 *folder.Folder
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) *folder.Folder); ok {
|
||||
r0 = rf(ctx, orgID, title)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*folder.Folder)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
|
||||
r1 = rf(ctx, orgID, title)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetFolderByUID provides a mock function with given fields: ctx, orgID, uid
|
||||
func (_m *FakeDashboardStore) GetFolderByUID(ctx context.Context, orgID int64, uid string) (*folder.Folder, error) {
|
||||
ret := _m.Called(ctx, orgID, uid)
|
||||
|
||||
var r0 *folder.Folder
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64, string) *folder.Folder); ok {
|
||||
r0 = rf(ctx, orgID, uid)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*folder.Folder)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int64, string) error); ok {
|
||||
r1 = rf(ctx, orgID, uid)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetProvisionedDashboardData provides a mock function with given fields: ctx, name
|
||||
func (_m *FakeDashboardStore) GetProvisionedDashboardData(ctx context.Context, name string) ([]*DashboardProvisioning, error) {
|
||||
ret := _m.Called(ctx, name)
|
||||
|
@ -30,13 +30,14 @@ import (
|
||||
type Service struct {
|
||||
store store
|
||||
|
||||
log log.Logger
|
||||
cfg *setting.Cfg
|
||||
dashboardStore dashboards.Store
|
||||
searchService *search.SearchService
|
||||
features featuremgmt.FeatureToggles
|
||||
permissions accesscontrol.FolderPermissionsService
|
||||
accessControl accesscontrol.AccessControl
|
||||
log log.Logger
|
||||
cfg *setting.Cfg
|
||||
dashboardStore dashboards.Store
|
||||
dashboardFolderStore dashboards.FolderStore
|
||||
searchService *search.SearchService
|
||||
features featuremgmt.FeatureToggles
|
||||
permissions accesscontrol.FolderPermissionsService
|
||||
accessControl accesscontrol.AccessControl
|
||||
|
||||
// bus is currently used to publish events that cause scheduler to update rules.
|
||||
bus bus.Bus
|
||||
@ -47,24 +48,26 @@ func ProvideService(
|
||||
bus bus.Bus,
|
||||
cfg *setting.Cfg,
|
||||
dashboardStore dashboards.Store,
|
||||
folderStore dashboards.FolderStore,
|
||||
db db.DB, // DB for the (new) nested folder store
|
||||
features featuremgmt.FeatureToggles,
|
||||
folderPermissionsService accesscontrol.FolderPermissionsService,
|
||||
searchService *search.SearchService,
|
||||
) folder.Service {
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderNameScopeResolver(dashboardStore))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(dashboardStore))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderNameScopeResolver(dashboardStore, folderStore))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewFolderIDScopeResolver(dashboardStore, folderStore))
|
||||
store := ProvideStore(db, cfg, features)
|
||||
svr := &Service{
|
||||
cfg: cfg,
|
||||
log: log.New("folder-service"),
|
||||
dashboardStore: dashboardStore,
|
||||
store: store,
|
||||
searchService: searchService,
|
||||
features: features,
|
||||
permissions: folderPermissionsService,
|
||||
accessControl: ac,
|
||||
bus: bus,
|
||||
cfg: cfg,
|
||||
log: log.New("folder-service"),
|
||||
dashboardStore: dashboardStore,
|
||||
dashboardFolderStore: folderStore,
|
||||
store: store,
|
||||
searchService: searchService,
|
||||
features: features,
|
||||
permissions: folderPermissionsService,
|
||||
accessControl: ac,
|
||||
bus: bus,
|
||||
}
|
||||
if features.IsEnabled(featuremgmt.FlagNestedFolders) {
|
||||
svr.DBMigration(db)
|
||||
@ -166,7 +169,7 @@ func (s *Service) GetChildren(ctx context.Context, cmd *folder.GetChildrenQuery)
|
||||
filtered := make([]*folder.Folder, 0, len(children))
|
||||
for _, f := range children {
|
||||
// fetch folder from dashboard store
|
||||
dashFolder, err := s.dashboardStore.GetFolderByUID(ctx, f.OrgID, f.UID)
|
||||
dashFolder, err := s.dashboardFolderStore.GetFolderByUID(ctx, f.OrgID, f.UID)
|
||||
if err != nil {
|
||||
s.log.Error("failed to fetch folder by UID: %s from dashboard store", f.UID, err)
|
||||
continue
|
||||
@ -220,7 +223,7 @@ func (s *Service) getFolderByID(ctx context.Context, user *user.SignedInUser, id
|
||||
return &folder.Folder{ID: id, Title: "General"}, nil
|
||||
}
|
||||
|
||||
dashFolder, err := s.dashboardStore.GetFolderByID(ctx, orgID, id)
|
||||
dashFolder, err := s.dashboardFolderStore.GetFolderByID(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -244,7 +247,7 @@ func (s *Service) getFolderByID(ctx context.Context, user *user.SignedInUser, id
|
||||
}
|
||||
|
||||
func (s *Service) getFolderByUID(ctx context.Context, user *user.SignedInUser, orgID int64, uid string) (*folder.Folder, error) {
|
||||
dashFolder, err := s.dashboardStore.GetFolderByUID(ctx, orgID, uid)
|
||||
dashFolder, err := s.dashboardFolderStore.GetFolderByUID(ctx, orgID, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -268,7 +271,7 @@ func (s *Service) getFolderByUID(ctx context.Context, user *user.SignedInUser, o
|
||||
}
|
||||
|
||||
func (s *Service) getFolderByTitle(ctx context.Context, user *user.SignedInUser, orgID int64, title string) (*folder.Folder, error) {
|
||||
dashFolder, err := s.dashboardStore.GetFolderByTitle(ctx, orgID, title)
|
||||
dashFolder, err := s.dashboardFolderStore.GetFolderByTitle(ctx, orgID, title)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -330,7 +333,7 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
|
||||
}
|
||||
|
||||
var createdFolder *folder.Folder
|
||||
createdFolder, err = s.dashboardStore.GetFolderByID(ctx, cmd.OrgID, dash.ID)
|
||||
createdFolder, err = s.dashboardFolderStore.GetFolderByID(ctx, cmd.OrgID, dash.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -475,7 +478,7 @@ func (s *Service) legacyUpdate(ctx context.Context, cmd *folder.UpdateFolderComm
|
||||
}
|
||||
|
||||
var foldr *folder.Folder
|
||||
foldr, err = s.dashboardStore.GetFolderByID(ctx, cmd.OrgID, dash.ID)
|
||||
foldr, err = s.dashboardFolderStore.GetFolderByID(ctx, cmd.OrgID, dash.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -534,7 +537,7 @@ func (s *Service) Delete(ctx context.Context, cmd *folder.DeleteFolderCommand) e
|
||||
}
|
||||
}
|
||||
|
||||
dashFolder, err := s.dashboardStore.GetFolderByUID(ctx, cmd.OrgID, cmd.UID)
|
||||
dashFolder, err := s.dashboardFolderStore.GetFolderByUID(ctx, cmd.OrgID, cmd.UID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -38,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, &featuremgmt.FeatureManager{}, nil, nil)
|
||||
ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, nil, nil, nil, &featuremgmt.FeatureManager{}, nil, nil)
|
||||
|
||||
require.Len(t, ac.Calls.RegisterAttributeScopeResolver, 2)
|
||||
})
|
||||
@ -51,7 +51,9 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
t.Run("Folder service tests", func(t *testing.T) {
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
db := sqlstore.InitTestDB(t)
|
||||
store := ProvideStore(db, db.Cfg, featuremgmt.WithFeatures([]interface{}{"nestedFolders"}))
|
||||
nestedFolderStore := ProvideStore(db, db.Cfg, featuremgmt.WithFeatures([]interface{}{"nestedFolders"}))
|
||||
|
||||
folderStore := dashboards.NewFakeFolderStore(t)
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
cfg.RBACEnabled = false
|
||||
@ -59,14 +61,15 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
|
||||
service := &Service{
|
||||
cfg: cfg,
|
||||
log: log.New("test-folder-service"),
|
||||
dashboardStore: dashStore,
|
||||
store: store,
|
||||
searchService: nil,
|
||||
features: features,
|
||||
permissions: folderPermissions,
|
||||
bus: bus.ProvideBus(tracing.InitializeTracerForTest()),
|
||||
cfg: cfg,
|
||||
log: log.New("test-folder-service"),
|
||||
dashboardStore: dashStore,
|
||||
dashboardFolderStore: folderStore,
|
||||
store: nestedFolderStore,
|
||||
searchService: nil,
|
||||
features: features,
|
||||
permissions: folderPermissions,
|
||||
bus: bus.ProvideBus(tracing.InitializeTracerForTest()),
|
||||
}
|
||||
|
||||
t.Run("Given user has no permissions", func(t *testing.T) {
|
||||
@ -80,8 +83,8 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
f.ID = folderId
|
||||
f.UID = folderUID
|
||||
|
||||
dashStore.On("GetFolderByID", mock.Anything, orgID, folderId).Return(f, nil)
|
||||
dashStore.On("GetFolderByUID", mock.Anything, orgID, folderUID).Return(f, nil)
|
||||
folderStore.On("GetFolderByID", mock.Anything, orgID, folderId).Return(f, nil)
|
||||
folderStore.On("GetFolderByUID", mock.Anything, orgID, folderUID).Return(f, nil)
|
||||
|
||||
t.Run("When get folder by id should return access denied error", func(t *testing.T) {
|
||||
_, err := service.Get(context.Background(), &folder.GetFolderQuery{
|
||||
@ -143,8 +146,8 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
newFolder := models.NewFolder("Folder")
|
||||
newFolder.Uid = folderUID
|
||||
|
||||
dashStore.On("GetFolderByID", mock.Anything, orgID, folderId).Return(newFolder, nil)
|
||||
dashStore.On("GetFolderByUID", mock.Anything, orgID, folderUID).Return(newFolder, nil)
|
||||
folderStore.On("GetFolderByID", mock.Anything, orgID, folderId).Return(newFolder, nil)
|
||||
folderStore.On("GetFolderByUID", mock.Anything, orgID, folderUID).Return(newFolder, nil)
|
||||
|
||||
err := service.Delete(context.Background(), &folder.DeleteFolderCommand{
|
||||
UID: folderUID,
|
||||
@ -172,7 +175,7 @@ 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()
|
||||
dashStore.On("GetFolderByID", mock.Anything, orgID, dash.ID).Return(f, nil)
|
||||
folderStore.On("GetFolderByID", mock.Anything, orgID, dash.ID).Return(f, nil)
|
||||
|
||||
actualFolder, err := service.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
@ -205,7 +208,7 @@ 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(dashboardFolder, nil)
|
||||
dashStore.On("GetFolderByID", mock.Anything, orgID, dashboardFolder.ID).Return(f, nil)
|
||||
folderStore.On("GetFolderByID", mock.Anything, orgID, dashboardFolder.ID).Return(f, nil)
|
||||
|
||||
title := "TEST-Folder"
|
||||
req := &folder.UpdateFolderCommand{
|
||||
@ -224,7 +227,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
f := folder.NewFolder(util.GenerateShortUID(), "")
|
||||
f.ID = rand.Int63()
|
||||
f.UID = util.GenerateShortUID()
|
||||
dashStore.On("GetFolderByUID", mock.Anything, orgID, f.UID).Return(f, nil)
|
||||
folderStore.On("GetFolderByUID", mock.Anything, orgID, f.UID).Return(f, nil)
|
||||
|
||||
var actualCmd *dashboards.DeleteDashboardCommand
|
||||
dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
@ -258,7 +261,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
expected := folder.NewFolder(util.GenerateShortUID(), "")
|
||||
expected.ID = rand.Int63()
|
||||
|
||||
dashStore.On("GetFolderByID", mock.Anything, orgID, expected.ID).Return(expected, nil)
|
||||
folderStore.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)
|
||||
@ -269,7 +272,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
expected := folder.NewFolder(util.GenerateShortUID(), "")
|
||||
expected.UID = util.GenerateShortUID()
|
||||
|
||||
dashStore.On("GetFolderByUID", mock.Anything, orgID, expected.UID).Return(expected, nil)
|
||||
folderStore.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)
|
||||
@ -279,7 +282,7 @@ func TestIntegrationFolderService(t *testing.T) {
|
||||
t.Run("When get folder by title should return folder", func(t *testing.T) {
|
||||
expected := folder.NewFolder("TEST-"+util.GenerateShortUID(), "")
|
||||
|
||||
dashStore.On("GetFolderByTitle", mock.Anything, orgID, expected.Title).Return(expected, nil)
|
||||
folderStore.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)
|
||||
@ -322,23 +325,27 @@ func TestNestedFolderServiceFeatureToggle(t *testing.T) {
|
||||
guardian.New = g
|
||||
})
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
nestedFolderStore := NewFakeStore()
|
||||
|
||||
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)
|
||||
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
cfg.RBACEnabled = false
|
||||
folderService := &Service{
|
||||
cfg: cfg,
|
||||
store: folderStore,
|
||||
dashboardStore: &dashStore,
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||
log: log.New("test-folder-service"),
|
||||
cfg: cfg,
|
||||
store: nestedFolderStore,
|
||||
dashboardStore: &dashStore,
|
||||
dashboardFolderStore: dashboardFolderStore,
|
||||
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()}
|
||||
nestedFolderStore.ExpectedFolder = &folder.Folder{ParentUID: util.GenerateShortUID()}
|
||||
res, err := folderService.Create(context.Background(), &folder.CreateFolderCommand{SignedInUser: usr, Title: "my folder"})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res.UID)
|
||||
@ -359,11 +366,13 @@ 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)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures(), nil)
|
||||
nestedFolderStore := NewFakeStore()
|
||||
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures(), nil)
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
OrgID: orgID,
|
||||
Title: "myFolder",
|
||||
@ -372,7 +381,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// CreateFolder should not call the folder store create if the feature toggle is not enabled.
|
||||
require.False(t, folderStore.CreateCalled)
|
||||
require.False(t, nestedFolderStore.CreateCalled)
|
||||
})
|
||||
|
||||
t.Run("When delete folder, no delete in folder table done", func(t *testing.T) {
|
||||
@ -381,16 +390,18 @@ func TestNestedFolderService(t *testing.T) {
|
||||
dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
actualCmd = args.Get(1).(*dashboards.DeleteDashboardCommand)
|
||||
}).Return(nil).Once()
|
||||
dashStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures(), nil)
|
||||
nestedFolderStore := NewFakeStore()
|
||||
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures(), nil)
|
||||
err := folderSvc.Delete(context.Background(), &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
|
||||
require.False(t, folderStore.DeleteCalled)
|
||||
require.False(t, nestedFolderStore.DeleteCalled)
|
||||
})
|
||||
})
|
||||
|
||||
@ -406,11 +417,13 @@ 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)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
nestedFolderStore := NewFakeStore()
|
||||
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
@ -421,7 +434,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// CreateFolder should also call the folder store's create method.
|
||||
require.True(t, folderStore.CreateCalled)
|
||||
require.True(t, nestedFolderStore.CreateCalled)
|
||||
})
|
||||
|
||||
t.Run("create without UID, no error", func(t *testing.T) {
|
||||
@ -435,11 +448,13 @@ 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{UID: "newUID"}, nil)
|
||||
dashStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
nestedFolderStore := NewFakeStore()
|
||||
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
f, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
@ -449,7 +464,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// CreateFolder should also call the folder store's create method.
|
||||
require.True(t, folderStore.CreateCalled)
|
||||
require.True(t, nestedFolderStore.CreateCalled)
|
||||
require.Equal(t, "newUID", f.UID)
|
||||
})
|
||||
|
||||
@ -469,14 +484,16 @@ 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)
|
||||
dashStore.On("GetFolderByID", mock.Anything, orgID, dashboardFolder.ID).Return(f, 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()
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
folderStore.ExpectedParentFolders = []*folder.Folder{
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, orgID, dashboardFolder.ID).Return(f, nil)
|
||||
|
||||
nestedFolderStore := NewFakeStore()
|
||||
nestedFolderStore.ExpectedParentFolders = []*folder.Folder{
|
||||
{UID: "newFolder", ParentUID: "newFolder"},
|
||||
{UID: "newFolder2", ParentUID: "newFolder2"},
|
||||
{UID: "newFolder3", ParentUID: "newFolder3"},
|
||||
@ -491,13 +508,13 @@ func TestNestedFolderService(t *testing.T) {
|
||||
SignedInUser: usr,
|
||||
}
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
_, 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, folderStore.CreateCalled)
|
||||
require.False(t, nestedFolderStore.CreateCalled)
|
||||
require.NotNil(t, actualCmd)
|
||||
})
|
||||
|
||||
@ -513,19 +530,20 @@ 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)
|
||||
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)
|
||||
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 := dashboards.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
// return an error from the folder store
|
||||
folderStore := NewFakeStore()
|
||||
folderStore.ExpectedError = errors.New("FAILED")
|
||||
nestedFolderStore := NewFakeStore()
|
||||
nestedFolderStore.ExpectedError = errors.New("FAILED")
|
||||
|
||||
// the service return success as long as the legacy create succeeds
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
@ -537,7 +555,7 @@ func TestNestedFolderService(t *testing.T) {
|
||||
require.Error(t, err, "FAILED")
|
||||
|
||||
// CreateFolder should also call the folder store's create method.
|
||||
require.True(t, folderStore.CreateCalled)
|
||||
require.True(t, nestedFolderStore.CreateCalled)
|
||||
require.NotNil(t, actualCmd)
|
||||
})
|
||||
|
||||
@ -550,11 +568,12 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
folderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
nestedFolderStore := NewFakeStore()
|
||||
nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
_, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder", OrgID: orgID, SignedInUser: usr})
|
||||
@ -570,11 +589,12 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
folderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
nestedFolderStore := NewFakeStore()
|
||||
nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
_, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder", OrgID: orgID, SignedInUser: usr})
|
||||
@ -590,16 +610,17 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
folderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
folderStore.ExpectedParentFolders = []*folder.Folder{
|
||||
nestedFolderStore := NewFakeStore()
|
||||
nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
nestedFolderStore.ExpectedParentFolders = []*folder.Folder{
|
||||
{UID: "newFolder", ParentUID: "newFolder"},
|
||||
{UID: "newFolder2", ParentUID: "newFolder2"},
|
||||
{UID: "newFolder3", ParentUID: "newFolder3"},
|
||||
}
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
f, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder", OrgID: orgID, SignedInUser: usr})
|
||||
@ -615,12 +636,13 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
folderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
folderStore.ExpectedError = folder.ErrCircularReference
|
||||
nestedFolderStore := NewFakeStore()
|
||||
nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
nestedFolderStore.ExpectedError = folder.ErrCircularReference
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
f, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder", OrgID: orgID, SignedInUser: usr})
|
||||
@ -636,16 +658,17 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
folderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
folderStore.ExpectedParentFolders = []*folder.Folder{
|
||||
nestedFolderStore := NewFakeStore()
|
||||
nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
nestedFolderStore.ExpectedParentFolders = []*folder.Folder{
|
||||
{UID: "newFolder", ParentUID: "newFolder"},
|
||||
{UID: "newFolder2", ParentUID: "newFolder2"},
|
||||
}
|
||||
folderStore.ExpectedFolderHeight = 5
|
||||
nestedFolderStore.ExpectedFolderHeight = 5
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
f, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder2", OrgID: orgID, SignedInUser: usr})
|
||||
@ -661,12 +684,13 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
|
||||
dashStore := &dashboards.FakeDashboardStore{}
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
folderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
folderStore.ExpectedParentFolders = []*folder.Folder{{UID: "myFolder", ParentUID: "12345"}, {UID: "12345", ParentUID: ""}}
|
||||
nestedFolderStore := NewFakeStore()
|
||||
nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
nestedFolderStore.ExpectedParentFolders = []*folder.Folder{{UID: "myFolder", ParentUID: "12345"}, {UID: "12345", ParentUID: ""}}
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
f, err := folderSvc.Move(context.Background(), &folder.MoveFolderCommand{UID: "myFolder", NewParentUID: "newFolder2", OrgID: orgID, SignedInUser: usr})
|
||||
@ -686,19 +710,21 @@ func TestNestedFolderService(t *testing.T) {
|
||||
dashStore.On("DeleteDashboard", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
actualCmd = args.Get(1).(*dashboards.DeleteDashboardCommand)
|
||||
}).Return(nil).Once()
|
||||
dashStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
folderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
dashboardFolderStore := dashboards.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByUID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("string")).Return(&folder.Folder{}, nil)
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
nestedFolderStore := NewFakeStore()
|
||||
nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
err := folderSvc.Delete(context.Background(), &folder.DeleteFolderCommand{UID: "myFolder", OrgID: orgID, SignedInUser: usr})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, actualCmd)
|
||||
|
||||
require.True(t, folderStore.DeleteCalled)
|
||||
require.True(t, nestedFolderStore.DeleteCalled)
|
||||
})
|
||||
|
||||
t.Run("create returns error if maximum depth reached", func(t *testing.T) {
|
||||
@ -713,23 +739,24 @@ 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)
|
||||
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)
|
||||
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 := dashboards.NewFakeFolderStore(t)
|
||||
dashboardFolderStore.On("GetFolderByID", mock.Anything, mock.AnythingOfType("int64"), mock.AnythingOfType("int64")).Return(&folder.Folder{}, nil)
|
||||
|
||||
parents := make([]*folder.Folder, 0, folder.MaxNestedFolderDepth)
|
||||
for i := 0; i < folder.MaxNestedFolderDepth; i++ {
|
||||
parents = append(parents, &folder.Folder{UID: fmt.Sprintf("folder%d", i)})
|
||||
}
|
||||
|
||||
folderStore := NewFakeStore()
|
||||
//folderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
folderStore.ExpectedParentFolders = parents
|
||||
nestedFolderStore := NewFakeStore()
|
||||
//nestedFolderStore.ExpectedFolder = &folder.Folder{UID: "myFolder", ParentUID: "newFolder"}
|
||||
nestedFolderStore.ExpectedParentFolders = parents
|
||||
|
||||
folderSvc := setup(t, dashStore, folderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
folderSvc := setup(t, dashStore, dashboardFolderStore, nestedFolderStore, featuremgmt.WithFeatures("nestedFolders"), actest.FakeAccessControl{
|
||||
ExpectedEvaluate: true,
|
||||
})
|
||||
_, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
|
||||
@ -745,18 +772,19 @@ func TestNestedFolderService(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func setup(t *testing.T, dashStore dashboards.Store, folderStore store, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl) folder.Service {
|
||||
func setup(t *testing.T, dashStore dashboards.Store, dashboardFolderStore dashboards.FolderStore, nestedFolderStore store, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl) folder.Service {
|
||||
t.Helper()
|
||||
|
||||
// nothing enabled yet
|
||||
cfg := setting.NewCfg()
|
||||
cfg.RBACEnabled = false
|
||||
return &Service{
|
||||
cfg: cfg,
|
||||
log: log.New("test-folder-service"),
|
||||
dashboardStore: dashStore,
|
||||
store: folderStore,
|
||||
features: features,
|
||||
accessControl: ac,
|
||||
cfg: cfg,
|
||||
log: log.New("test-folder-service"),
|
||||
dashboardStore: dashStore,
|
||||
dashboardFolderStore: dashboardFolderStore,
|
||||
store: nestedFolderStore,
|
||||
features: features,
|
||||
accessControl: ac,
|
||||
}
|
||||
}
|
||||
|
@ -601,7 +601,7 @@ func setupAccessControlGuardianTest(t *testing.T, uid string, permissions []acce
|
||||
})
|
||||
require.NoError(t, err)
|
||||
ac := accesscontrolmock.New().WithPermissions(permissions)
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardUIDScopeResolver(dashStore))
|
||||
ac.RegisterScopeAttributeResolver(dashboards.NewDashboardUIDScopeResolver(dashStore, dashStore))
|
||||
license := licensingtest.NewFakeLicensing()
|
||||
license.On("FeatureEnabled", "accesscontrol.enforcement").Return(true).Maybe()
|
||||
teamSvc := teamimpl.ProvideService(store, store.Cfg)
|
||||
|
@ -291,7 +291,7 @@ func createDashboard(t *testing.T, sqlStore db.DB, user user.SignedInUser, dash
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||
service := dashboardservice.ProvideDashboardService(
|
||||
cfg, dashboardStore, dashAlertExtractor,
|
||||
cfg, dashboardStore, dashboardStore, dashAlertExtractor,
|
||||
features, folderPermissions, dashboardPermissions, ac,
|
||||
)
|
||||
dashboard, err := service.SaveDashboard(context.Background(), dashItem, true)
|
||||
@ -314,7 +314,7 @@ func createFolderWithACL(t *testing.T, sqlStore db.DB, title string, user user.S
|
||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
|
||||
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, nil, features, folderPermissions, nil)
|
||||
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, 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{
|
||||
@ -435,14 +435,14 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||
dashboardService := dashboardservice.ProvideDashboardService(
|
||||
sqlStore.Cfg, dashboardStore, nil,
|
||||
sqlStore.Cfg, dashboardStore, dashboardStore, nil,
|
||||
features, folderPermissions, dashboardPermissions, ac,
|
||||
)
|
||||
guardian.InitLegacyGuardian(sqlStore, dashboardService, &teamtest.FakeService{})
|
||||
service := LibraryElementService{
|
||||
Cfg: sqlStore.Cfg,
|
||||
SQLStore: sqlStore,
|
||||
folderService: folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), sqlStore.Cfg, dashboardStore, nil, features, folderPermissions, nil),
|
||||
folderService: folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), sqlStore.Cfg, dashboardStore, dashboardStore, nil, features, folderPermissions, nil),
|
||||
}
|
||||
|
||||
// deliberate difference between signed in user and user in db to make it crystal clear
|
||||
|
@ -704,7 +704,7 @@ func createDashboard(t *testing.T, sqlStore db.DB, user *user.SignedInUser, dash
|
||||
dashAlertService := alerting.ProvideDashAlertExtractorService(nil, nil, nil)
|
||||
ac := acmock.New()
|
||||
service := dashboardservice.ProvideDashboardService(
|
||||
cfg, dashboardStore, dashAlertService,
|
||||
cfg, dashboardStore, dashboardStore, dashAlertService,
|
||||
featuremgmt.WithFeatures(), acmock.NewMockedPermissionsService(), acmock.NewMockedPermissionsService(), ac,
|
||||
)
|
||||
dashboard, err := service.SaveDashboard(context.Background(), dashItem, true)
|
||||
@ -726,7 +726,7 @@ func createFolderWithACL(t *testing.T, sqlStore db.DB, title string, user *user.
|
||||
quotaService := quotatest.New(false, nil)
|
||||
dashboardStore, err := database.ProvideDashboardStore(sqlStore, cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, nil, features, folderPermissions, nil)
|
||||
s := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, dashboardStore, nil, features, folderPermissions, nil)
|
||||
|
||||
t.Logf("Creating folder with title and UID %q", title)
|
||||
ctx := appcontext.WithUser(context.Background(), user)
|
||||
@ -835,7 +835,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
|
||||
ac := acmock.New()
|
||||
folderPermissions := acmock.NewMockedPermissionsService()
|
||||
|
||||
folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, nil, features, folderPermissions, nil)
|
||||
folderService := folderimpl.ProvideService(ac, bus.ProvideBus(tracing.InitializeTracerForTest()), cfg, dashboardStore, dashboardStore, nil, features, folderPermissions, nil)
|
||||
|
||||
elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService)
|
||||
service := LibraryPanelService{
|
||||
|
@ -79,13 +79,13 @@ func SetupTestEnv(tb testing.TB, baseInterval time.Duration) (*ngalert.AlertNG,
|
||||
dashboardPermissions := acmock.NewMockedPermissionsService()
|
||||
|
||||
dashboardService := dashboardservice.ProvideDashboardService(
|
||||
cfg, dashboardStore, nil,
|
||||
cfg, dashboardStore, dashboardStore, nil,
|
||||
features, folderPermissions, dashboardPermissions, ac,
|
||||
)
|
||||
|
||||
tracer := tracing.InitializeTracerForTest()
|
||||
bus := bus.ProvideBus(tracer)
|
||||
folderService := folderimpl.ProvideService(ac, bus, cfg, dashboardStore, nil, features, folderPermissions, nil)
|
||||
folderService := folderimpl.ProvideService(ac, bus, cfg, dashboardStore, dashboardStore, nil, features, folderPermissions, nil)
|
||||
|
||||
ng, err := ngalert.ProvideService(
|
||||
cfg, featuremgmt.WithFeatures(), nil, nil, routing.NewRouteRegister(), sqlStore, nil, nil, nil, quotatest.New(false, nil),
|
||||
|
Loading…
Reference in New Issue
Block a user