mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
sqlstore split: dashboard permissions (#49962)
* backend/sqlstore split: remove unused GetDashboardPermissionsForUser from sqlstore * remove debugging line * backend/sqlstore: move dashboard permission related functions to dashboard service
This commit is contained in:
@@ -13,9 +13,12 @@ type DashboardService interface {
|
||||
DeleteDashboard(ctx context.Context, dashboardId int64, orgId int64) error
|
||||
FindDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error)
|
||||
GetDashboard(ctx context.Context, query *models.GetDashboardQuery) error
|
||||
GetDashboardAclInfoList(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error
|
||||
GetDashboards(ctx context.Context, query *models.GetDashboardsQuery) error
|
||||
GetDashboardUIDById(ctx context.Context, query *models.GetDashboardRefByIdQuery) error
|
||||
GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*models.PublicDashboardConfig, error)
|
||||
HasAdminPermissionInFolders(ctx context.Context, query *models.HasAdminPermissionInFoldersQuery) error
|
||||
HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error
|
||||
ImportDashboard(ctx context.Context, dto *SaveDashboardDTO) (*models.Dashboard, error)
|
||||
MakeUserAdmin(ctx context.Context, orgID int64, userID, dashboardID int64, setViewAndEditPermissions bool) error
|
||||
SaveDashboard(ctx context.Context, dto *SaveDashboardDTO, allowUiUpdate bool) (*models.Dashboard, error)
|
||||
@@ -49,6 +52,7 @@ type Store interface {
|
||||
DeleteOrphanedProvisionedDashboards(ctx context.Context, cmd *models.DeleteOrphanedProvisionedDashboardsCommand) error
|
||||
FindDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) ([]DashboardSearchProjection, error)
|
||||
GetDashboard(ctx context.Context, query *models.GetDashboardQuery) error
|
||||
GetDashboardAclInfoList(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error
|
||||
GetDashboardUIDById(ctx context.Context, query *models.GetDashboardRefByIdQuery) error
|
||||
GetDashboards(ctx context.Context, query *models.GetDashboardsQuery) error
|
||||
// GetDashboardsByPluginID retrieves dashboards identified by plugin.
|
||||
@@ -57,6 +61,8 @@ type Store interface {
|
||||
GetProvisionedDataByDashboardID(dashboardID int64) (*models.DashboardProvisioning, error)
|
||||
GetProvisionedDataByDashboardUID(orgID int64, dashboardUID string) (*models.DashboardProvisioning, error)
|
||||
GetPublicDashboardConfig(orgId int64, dashboardUid string) (*models.PublicDashboardConfig, error)
|
||||
HasAdminPermissionInFolders(ctx context.Context, query *models.HasAdminPermissionInFoldersQuery) error
|
||||
HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error
|
||||
// SaveAlerts saves dashboard alerts.
|
||||
SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error
|
||||
SaveDashboard(cmd models.SaveDashboardCommand) (*models.Dashboard, error)
|
||||
|
||||
@@ -90,6 +90,20 @@ func (_m *FakeDashboardService) GetDashboard(ctx context.Context, query *models.
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetDashboardAclInfoList provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeDashboardService) GetDashboardAclInfoList(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.GetDashboardAclInfoListQuery) error); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetDashboardUIDById provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeDashboardService) GetDashboardUIDById(ctx context.Context, query *models.GetDashboardRefByIdQuery) error {
|
||||
ret := _m.Called(ctx, query)
|
||||
@@ -141,6 +155,34 @@ func (_m *FakeDashboardService) GetPublicDashboardConfig(ctx context.Context, or
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// HasAdminPermissionInFolders provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeDashboardService) HasAdminPermissionInFolders(ctx context.Context, query *models.HasAdminPermissionInFoldersQuery) error {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.HasAdminPermissionInFoldersQuery) error); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// HasEditPermissionInFolders provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeDashboardService) HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.HasEditPermissionInFoldersQuery) error); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// ImportDashboard provides a mock function with given fields: ctx, dto
|
||||
func (_m *FakeDashboardService) ImportDashboard(ctx context.Context, dto *SaveDashboardDTO) (*models.Dashboard, error) {
|
||||
ret := _m.Called(ctx, dto)
|
||||
|
||||
150
pkg/services/dashboards/database/acl.go
Normal file
150
pkg/services/dashboards/database/acl.go
Normal file
@@ -0,0 +1,150 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
)
|
||||
|
||||
// GetDashboardAclInfoList returns a list of permissions for a dashboard. They can be fetched from three
|
||||
// different places.
|
||||
// 1) Permissions for the dashboard
|
||||
// 2) permissions for its parent folder
|
||||
// 3) if no specific permissions have been set for the dashboard or its parent folder then get the default permissions
|
||||
func (d *DashboardStore) GetDashboardAclInfoList(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error {
|
||||
outerErr := d.sqlStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error {
|
||||
query.Result = make([]*models.DashboardAclInfoDTO, 0)
|
||||
falseStr := d.dialect.BooleanStr(false)
|
||||
|
||||
if query.DashboardID == 0 {
|
||||
sql := `SELECT
|
||||
da.id,
|
||||
da.org_id,
|
||||
da.dashboard_id,
|
||||
da.user_id,
|
||||
da.team_id,
|
||||
da.permission,
|
||||
da.role,
|
||||
da.created,
|
||||
da.updated,
|
||||
'' as user_login,
|
||||
'' as user_email,
|
||||
'' as team,
|
||||
'' as title,
|
||||
'' as slug,
|
||||
'' as uid,` +
|
||||
falseStr + ` AS is_folder,` +
|
||||
falseStr + ` AS inherited
|
||||
FROM dashboard_acl as da
|
||||
WHERE da.dashboard_id = -1`
|
||||
return dbSession.SQL(sql).Find(&query.Result)
|
||||
}
|
||||
|
||||
rawSQL := `
|
||||
-- get permissions for the dashboard and its parent folder
|
||||
SELECT
|
||||
da.id,
|
||||
da.org_id,
|
||||
da.dashboard_id,
|
||||
da.user_id,
|
||||
da.team_id,
|
||||
da.permission,
|
||||
da.role,
|
||||
da.created,
|
||||
da.updated,
|
||||
u.login AS user_login,
|
||||
u.email AS user_email,
|
||||
ug.name AS team,
|
||||
ug.email AS team_email,
|
||||
d.title,
|
||||
d.slug,
|
||||
d.uid,
|
||||
d.is_folder,
|
||||
CASE WHEN (da.dashboard_id = -1 AND d.folder_id > 0) OR da.dashboard_id = d.folder_id THEN ` + d.dialect.BooleanStr(true) + ` ELSE ` + falseStr + ` END AS inherited
|
||||
FROM dashboard as d
|
||||
LEFT JOIN dashboard folder on folder.id = d.folder_id
|
||||
LEFT JOIN dashboard_acl AS da ON
|
||||
da.dashboard_id = d.id OR
|
||||
da.dashboard_id = d.folder_id OR
|
||||
(
|
||||
-- include default permissions -->
|
||||
da.org_id = -1 AND (
|
||||
(folder.id IS NOT NULL AND folder.has_acl = ` + falseStr + `) OR
|
||||
(folder.id IS NULL AND d.has_acl = ` + falseStr + `)
|
||||
)
|
||||
)
|
||||
LEFT JOIN ` + d.dialect.Quote("user") + ` AS u ON u.id = da.user_id
|
||||
LEFT JOIN team ug on ug.id = da.team_id
|
||||
WHERE d.org_id = ? AND d.id = ? AND da.id IS NOT NULL
|
||||
ORDER BY da.id ASC
|
||||
`
|
||||
|
||||
return dbSession.SQL(rawSQL, query.OrgID, query.DashboardID).Find(&query.Result)
|
||||
})
|
||||
|
||||
if outerErr != nil {
|
||||
return outerErr
|
||||
}
|
||||
|
||||
for _, p := range query.Result {
|
||||
p.PermissionName = p.Permission.String()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasEditPermissionInFolders validates that an user have access to a certain folder
|
||||
func (d *DashboardStore) HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error {
|
||||
return d.sqlStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error {
|
||||
if query.SignedInUser.HasRole(models.ROLE_EDITOR) {
|
||||
query.Result = true
|
||||
return nil
|
||||
}
|
||||
|
||||
builder := &sqlstore.SQLBuilder{}
|
||||
builder.Write("SELECT COUNT(dashboard.id) AS count FROM dashboard WHERE dashboard.org_id = ? AND dashboard.is_folder = ?",
|
||||
query.SignedInUser.OrgId, d.dialect.BooleanStr(true))
|
||||
builder.WriteDashboardPermissionFilter(query.SignedInUser, models.PERMISSION_EDIT)
|
||||
|
||||
type folderCount struct {
|
||||
Count int64
|
||||
}
|
||||
|
||||
resp := make([]*folderCount, 0)
|
||||
|
||||
if err := dbSession.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query.Result = len(resp) > 0 && resp[0].Count > 0
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (d *DashboardStore) HasAdminPermissionInFolders(ctx context.Context, query *models.HasAdminPermissionInFoldersQuery) error {
|
||||
return d.sqlStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error {
|
||||
if query.SignedInUser.HasRole(models.ROLE_ADMIN) {
|
||||
query.Result = true
|
||||
return nil
|
||||
}
|
||||
|
||||
builder := &sqlstore.SQLBuilder{}
|
||||
builder.Write("SELECT COUNT(dashboard.id) AS count FROM dashboard WHERE dashboard.org_id = ? AND dashboard.is_folder = ?", query.SignedInUser.OrgId, d.dialect.BooleanStr(true))
|
||||
builder.WriteDashboardPermissionFilter(query.SignedInUser, models.PERMISSION_ADMIN)
|
||||
|
||||
type folderCount struct {
|
||||
Count int64
|
||||
}
|
||||
|
||||
resp := make([]*folderCount, 0)
|
||||
if err := dbSession.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
query.Result = len(resp) > 0 && resp[0].Count > 0
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -1,31 +1,28 @@
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package permissions
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
var sqlStore *sqlstore.SQLStore
|
||||
var currentUser models.User
|
||||
var savedFolder, childDash *models.Dashboard
|
||||
var dashboardStore *database.DashboardStore
|
||||
var dashboardStore *DashboardStore
|
||||
|
||||
setup := func(t *testing.T) {
|
||||
sqlStore = sqlstore.InitTestDB(t)
|
||||
dashboardStore = database.ProvideDashboardStore(sqlStore)
|
||||
dashboardStore = ProvideDashboardStore(sqlStore)
|
||||
currentUser = createUser(t, sqlStore, "viewer", "Viewer", false)
|
||||
savedFolder = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod", "webapp")
|
||||
childDash = insertTestDashboard(t, dashboardStore, "2 test dash", 1, savedFolder.Id, false, "prod", "webapp")
|
||||
@@ -45,7 +42,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
setup(t)
|
||||
query := models.GetDashboardAclInfoListQuery{DashboardID: savedFolder.Id, OrgID: 1}
|
||||
|
||||
err := sqlStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
err := dashboardStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, 2, len(query.Result))
|
||||
@@ -62,7 +59,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
setup(t)
|
||||
query := models.GetDashboardAclInfoListQuery{DashboardID: childDash.Id, OrgID: 1}
|
||||
|
||||
err := sqlStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
err := dashboardStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, 2, len(query.Result))
|
||||
@@ -81,7 +78,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
query := models.GetDashboardAclInfoListQuery{DashboardID: childDash.Id, OrgID: 1}
|
||||
err = sqlStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
err = dashboardStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, 0, len(query.Result))
|
||||
@@ -102,7 +99,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
t.Run("When reading dashboard acl should include acl for parent folder", func(t *testing.T) {
|
||||
query := models.GetDashboardAclInfoListQuery{DashboardID: childDash.Id, OrgID: 1}
|
||||
|
||||
err := sqlStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
err := dashboardStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, 1, len(query.Result))
|
||||
@@ -121,7 +118,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
t.Run("When reading dashboard acl should include acl for parent folder and child", func(t *testing.T) {
|
||||
query := models.GetDashboardAclInfoListQuery{OrgID: 1, DashboardID: childDash.Id}
|
||||
|
||||
err := sqlStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
err := dashboardStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, 2, len(query.Result))
|
||||
@@ -145,7 +142,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
|
||||
query := models.GetDashboardAclInfoListQuery{OrgID: 1, DashboardID: childDash.Id}
|
||||
|
||||
err = sqlStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
err = dashboardStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
require.Nil(t, err)
|
||||
|
||||
defaultPermissionsId := int64(-1)
|
||||
@@ -171,7 +168,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
q1 := &models.GetDashboardAclInfoListQuery{DashboardID: savedFolder.Id, OrgID: 1}
|
||||
err = sqlStore.GetDashboardAclInfoList(context.Background(), q1)
|
||||
err = dashboardStore.GetDashboardAclInfoList(context.Background(), q1)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, savedFolder.Id, q1.Result[0].DashboardId)
|
||||
@@ -185,7 +182,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
q3 := &models.GetDashboardAclInfoListQuery{DashboardID: savedFolder.Id, OrgID: 1}
|
||||
err = sqlStore.GetDashboardAclInfoList(context.Background(), q3)
|
||||
err = dashboardStore.GetDashboardAclInfoList(context.Background(), q3)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 0, len(q3.Result))
|
||||
})
|
||||
@@ -204,7 +201,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
q1 := &models.GetDashboardAclInfoListQuery{DashboardID: savedFolder.Id, OrgID: 1}
|
||||
err = sqlStore.GetDashboardAclInfoList(context.Background(), q1)
|
||||
err = dashboardStore.GetDashboardAclInfoList(context.Background(), q1)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, savedFolder.Id, q1.Result[0].DashboardId)
|
||||
require.Equal(t, models.PERMISSION_EDIT, q1.Result[0].Permission)
|
||||
@@ -224,7 +221,7 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
q3 := &models.GetDashboardAclInfoListQuery{DashboardID: savedFolder.Id, OrgID: 1}
|
||||
err = sqlStore.GetDashboardAclInfoList(context.Background(), q3)
|
||||
err = dashboardStore.GetDashboardAclInfoList(context.Background(), q3)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(q3.Result))
|
||||
require.Equal(t, savedFolder.Id, q3.Result[0].DashboardId)
|
||||
@@ -236,11 +233,11 @@ func TestIntegrationDashboardAclDataAccess(t *testing.T) {
|
||||
t.Run("Default permissions for root folder dashboards", func(t *testing.T) {
|
||||
setup(t)
|
||||
var rootFolderId int64 = 0
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
//sqlStore := sqlstore.InitTestDB(t)
|
||||
|
||||
query := models.GetDashboardAclInfoListQuery{DashboardID: rootFolderId, OrgID: 1}
|
||||
|
||||
err := sqlStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
err := dashboardStore.GetDashboardAclInfoList(context.Background(), &query)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, 2, len(query.Result))
|
||||
@@ -268,39 +265,3 @@ func createUser(t *testing.T, sqlStore *sqlstore.SQLStore, name string, role str
|
||||
require.Equal(t, models.RoleType(role), q1.Result[0].Role)
|
||||
return *currentUser
|
||||
}
|
||||
|
||||
func insertTestDashboard(t *testing.T, dashboardStore *database.DashboardStore, title string, orgId int64,
|
||||
folderId int64, isFolder bool, tags ...interface{}) *models.Dashboard {
|
||||
t.Helper()
|
||||
cmd := models.SaveDashboardCommand{
|
||||
OrgId: orgId,
|
||||
FolderId: folderId,
|
||||
IsFolder: isFolder,
|
||||
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
||||
"id": nil,
|
||||
"title": title,
|
||||
"tags": tags,
|
||||
}),
|
||||
}
|
||||
dash, err := dashboardStore.SaveDashboard(cmd)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, dash)
|
||||
dash.Data.Set("id", dash.Id)
|
||||
dash.Data.Set("uid", dash.Uid)
|
||||
return dash
|
||||
}
|
||||
|
||||
func updateDashboardAcl(t *testing.T, dashboardStore *database.DashboardStore, dashboardID int64,
|
||||
items ...models.DashboardAcl) error {
|
||||
t.Helper()
|
||||
|
||||
var itemPtrs []*models.DashboardAcl
|
||||
for _, it := range items {
|
||||
item := it
|
||||
item.Created = time.Now()
|
||||
item.Updated = time.Now()
|
||||
itemPtrs = append(itemPtrs, &item)
|
||||
}
|
||||
|
||||
return dashboardStore.UpdateDashboardACL(context.Background(), dashboardID, itemPtrs)
|
||||
}
|
||||
@@ -310,24 +310,6 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
require.Equal(t, query.Result[1].ID, folder2.Id)
|
||||
})
|
||||
|
||||
t.Run("should have write access to all folders and dashboards", func(t *testing.T) {
|
||||
query := models.GetDashboardPermissionsForUserQuery{
|
||||
DashboardIds: []int64{folder1.Id, folder2.Id},
|
||||
OrgId: 1,
|
||||
UserId: adminUser.Id,
|
||||
OrgRole: models.ROLE_ADMIN,
|
||||
}
|
||||
|
||||
err := sqlStore.GetDashboardPermissionsForUser(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(query.Result), 2)
|
||||
require.Equal(t, query.Result[0].DashboardId, folder1.Id)
|
||||
require.Equal(t, query.Result[0].Permission, models.PERMISSION_ADMIN)
|
||||
require.Equal(t, query.Result[1].DashboardId, folder2.Id)
|
||||
require.Equal(t, query.Result[1].Permission, models.PERMISSION_ADMIN)
|
||||
})
|
||||
|
||||
t.Run("should have edit permission in folders", func(t *testing.T) {
|
||||
query := &models.HasEditPermissionInFoldersQuery{
|
||||
SignedInUser: &models.SignedInUser{UserId: adminUser.Id, OrgId: 1, OrgRole: models.ROLE_ADMIN},
|
||||
@@ -363,24 +345,6 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
require.Equal(t, query.Result[1].ID, folder2.Id)
|
||||
})
|
||||
|
||||
t.Run("should have edit access to folders with default ACL", func(t *testing.T) {
|
||||
query := models.GetDashboardPermissionsForUserQuery{
|
||||
DashboardIds: []int64{folder1.Id, folder2.Id},
|
||||
OrgId: 1,
|
||||
UserId: editorUser.Id,
|
||||
OrgRole: models.ROLE_EDITOR,
|
||||
}
|
||||
|
||||
err := sqlStore.GetDashboardPermissionsForUser(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(query.Result), 2)
|
||||
require.Equal(t, query.Result[0].DashboardId, folder1.Id)
|
||||
require.Equal(t, query.Result[0].Permission, models.PERMISSION_EDIT)
|
||||
require.Equal(t, query.Result[1].DashboardId, folder2.Id)
|
||||
require.Equal(t, query.Result[1].Permission, models.PERMISSION_EDIT)
|
||||
})
|
||||
|
||||
t.Run("Should have write access to one dashboard folder if default role changed to view for one folder", func(t *testing.T) {
|
||||
err := updateDashboardAcl(t, dashboardStore, folder1.Id, models.DashboardAcl{
|
||||
DashboardID: folder1.Id, OrgID: 1, UserID: editorUser.Id, Permission: models.PERMISSION_VIEW,
|
||||
@@ -427,26 +391,6 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
require.Equal(t, len(query.Result), 0)
|
||||
})
|
||||
|
||||
t.Run("should have view access to folders with default ACL", func(t *testing.T) {
|
||||
setup3()
|
||||
|
||||
query := models.GetDashboardPermissionsForUserQuery{
|
||||
DashboardIds: []int64{folder1.Id, folder2.Id},
|
||||
OrgId: 1,
|
||||
UserId: viewerUser.Id,
|
||||
OrgRole: models.ROLE_VIEWER,
|
||||
}
|
||||
|
||||
err := sqlStore.GetDashboardPermissionsForUser(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(query.Result), 2)
|
||||
require.Equal(t, query.Result[0].DashboardId, folder1.Id)
|
||||
require.Equal(t, query.Result[0].Permission, models.PERMISSION_VIEW)
|
||||
require.Equal(t, query.Result[1].DashboardId, folder2.Id)
|
||||
require.Equal(t, query.Result[1].Permission, models.PERMISSION_VIEW)
|
||||
})
|
||||
|
||||
t.Run("Should be able to get one dashboard folder if default role changed to edit for one folder", func(t *testing.T) {
|
||||
err := updateDashboardAcl(t, dashboardStore, folder1.Id, models.DashboardAcl{
|
||||
DashboardID: folder1.Id, OrgID: 1, UserID: viewerUser.Id, Permission: models.PERMISSION_EDIT,
|
||||
|
||||
@@ -586,3 +586,15 @@ func makeQueryResult(query *models.FindPersistedDashboardsQuery, res []dashboard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (dr *DashboardServiceImpl) GetDashboardAclInfoList(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error {
|
||||
return dr.dashboardStore.GetDashboardAclInfoList(ctx, query)
|
||||
}
|
||||
|
||||
func (dr *DashboardServiceImpl) HasAdminPermissionInFolders(ctx context.Context, query *models.HasAdminPermissionInFoldersQuery) error {
|
||||
return dr.dashboardStore.HasAdminPermissionInFolders(ctx, query)
|
||||
}
|
||||
|
||||
func (dr *DashboardServiceImpl) HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error {
|
||||
return dr.dashboardStore.HasEditPermissionInFolders(ctx, query)
|
||||
}
|
||||
|
||||
@@ -815,8 +815,14 @@ func permissionScenario(t *testing.T, desc string, canSave bool, fn permissionSc
|
||||
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
guardian.InitLegacyGuardian(sqlStore)
|
||||
dashboardStore := database.ProvideDashboardStore(sqlStore)
|
||||
service := ProvideDashboardService(
|
||||
&setting.Cfg{}, dashboardStore, &dummyDashAlertExtractor{},
|
||||
featuremgmt.WithFeatures(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
accesscontrolmock.NewMockedPermissionsService(),
|
||||
)
|
||||
guardian.InitLegacyGuardian(sqlStore, service)
|
||||
|
||||
savedFolder := saveTestFolder(t, "Saved folder", testOrgID, sqlStore)
|
||||
savedDashInFolder := saveTestDashboard(t, "Saved dash in folder", testOrgID, savedFolder.Id, sqlStore)
|
||||
|
||||
@@ -81,6 +81,20 @@ func (_m *FakeDashboardStore) GetDashboard(ctx context.Context, query *models.Ge
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetDashboardAclInfoList provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeDashboardStore) GetDashboardAclInfoList(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.GetDashboardAclInfoListQuery) error); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetDashboardUIDById provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeDashboardStore) GetDashboardUIDById(ctx context.Context, query *models.GetDashboardRefByIdQuery) error {
|
||||
ret := _m.Called(ctx, query)
|
||||
@@ -284,6 +298,34 @@ func (_m *FakeDashboardStore) GetPublicDashboardConfig(orgId int64, dashboardUid
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// HasAdminPermissionInFolders provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeDashboardStore) HasAdminPermissionInFolders(ctx context.Context, query *models.HasAdminPermissionInFoldersQuery) error {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.HasAdminPermissionInFoldersQuery) error); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// HasEditPermissionInFolders provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeDashboardStore) HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.HasEditPermissionInFoldersQuery) error); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// SaveAlerts provides a mock function with given fields: ctx, dashID, alerts
|
||||
func (_m *FakeDashboardStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error {
|
||||
ret := _m.Called(ctx, dashID, alerts)
|
||||
@@ -367,20 +409,6 @@ func (_m *FakeDashboardStore) SavePublicDashboardConfig(cmd models.SavePublicDas
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SearchDashboards provides a mock function with given fields: ctx, query
|
||||
func (_m *FakeDashboardStore) SearchDashboards(ctx context.Context, query *models.FindPersistedDashboardsQuery) error {
|
||||
ret := _m.Called(ctx, query)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.FindPersistedDashboardsQuery) error); ok {
|
||||
r0 = rf(ctx, query)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UnprovisionDashboard provides a mock function with given fields: ctx, id
|
||||
func (_m *FakeDashboardStore) UnprovisionDashboard(ctx context.Context, id int64) error {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
||||
Reference in New Issue
Block a user