The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/services/dashboards/database/acl_test.go

292 lines
11 KiB

package database
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotaimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
"github.com/grafana/grafana/pkg/services/team/teamimpl"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
)
func TestIntegrationDashboardACLDataAccess(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
var sqlStore *sqlstore.SQLStore
var currentUser user.User
var savedFolder, childDash *dashboards.Dashboard
var dashboardStore *DashboardStore
setup := func(t *testing.T) {
sqlStore = db.InitTestDB(t)
quotaService := quotatest.New(false, nil)
var err error
dashboardStore, err = ProvideDashboardStore(sqlStore, sqlStore.Cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
require.NoError(t, err)
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")
}
t.Run("Dashboard permission with userId and teamId set to 0", func(t *testing.T) {
setup(t)
err := updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{
OrgID: 1,
DashboardID: savedFolder.ID,
Permission: models.PERMISSION_EDIT,
})
require.Equal(t, models.ErrDashboardACLInfoMissing, err)
})
t.Run("Folder acl should include default acl", func(t *testing.T) {
setup(t)
query := dashboards.GetDashboardACLInfoListQuery{DashboardID: savedFolder.ID, OrgID: 1}
queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query)
require.Nil(t, err)
require.Equal(t, 2, len(queryResult))
defaultPermissionsId := int64(-1)
require.Equal(t, defaultPermissionsId, queryResult[0].DashboardID)
require.Equal(t, org.RoleViewer, *queryResult[0].Role)
require.False(t, queryResult[0].Inherited)
require.Equal(t, defaultPermissionsId, queryResult[1].DashboardID)
require.Equal(t, org.RoleEditor, *queryResult[1].Role)
require.False(t, queryResult[1].Inherited)
})
t.Run("Dashboard acl should include acl for parent folder", func(t *testing.T) {
setup(t)
query := dashboards.GetDashboardACLInfoListQuery{DashboardID: childDash.ID, OrgID: 1}
queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query)
require.Nil(t, err)
require.Equal(t, 2, len(queryResult))
defaultPermissionsId := int64(-1)
require.Equal(t, defaultPermissionsId, queryResult[0].DashboardID)
require.Equal(t, org.RoleViewer, *queryResult[0].Role)
require.True(t, queryResult[0].Inherited)
require.Equal(t, defaultPermissionsId, queryResult[1].DashboardID)
require.Equal(t, org.RoleEditor, *queryResult[1].Role)
require.True(t, queryResult[1].Inherited)
})
t.Run("Folder with removed default permissions returns no acl items", func(t *testing.T) {
setup(t)
err := dashboardStore.UpdateDashboardACL(context.Background(), savedFolder.ID, nil)
require.Nil(t, err)
query := dashboards.GetDashboardACLInfoListQuery{DashboardID: childDash.ID, OrgID: 1}
queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query)
require.Nil(t, err)
require.Equal(t, 0, len(queryResult))
})
t.Run("Given a dashboard folder and a user", func(t *testing.T) {
t.Run("Given dashboard folder permission", func(t *testing.T) {
setup(t)
err := updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{
OrgID: 1,
UserID: currentUser.ID,
DashboardID: savedFolder.ID,
Permission: models.PERMISSION_EDIT,
})
require.Nil(t, err)
t.Run("When reading dashboard acl should include acl for parent folder", func(t *testing.T) {
query := dashboards.GetDashboardACLInfoListQuery{DashboardID: childDash.ID, OrgID: 1}
queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query)
require.Nil(t, err)
require.Equal(t, 1, len(queryResult))
require.Equal(t, savedFolder.ID, queryResult[0].DashboardID)
})
t.Run("Given child dashboard permission", func(t *testing.T) {
err := updateDashboardACL(t, dashboardStore, childDash.ID, dashboards.DashboardACL{
OrgID: 1,
UserID: currentUser.ID,
DashboardID: childDash.ID,
Permission: models.PERMISSION_EDIT,
})
require.Nil(t, err)
t.Run("When reading dashboard acl should include acl for parent folder and child", func(t *testing.T) {
query := dashboards.GetDashboardACLInfoListQuery{OrgID: 1, DashboardID: childDash.ID}
queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query)
require.Nil(t, err)
require.Equal(t, 2, len(queryResult))
require.Equal(t, savedFolder.ID, queryResult[0].DashboardID)
require.True(t, queryResult[0].Inherited)
require.Equal(t, childDash.ID, queryResult[1].DashboardID)
require.False(t, queryResult[1].Inherited)
})
})
})
t.Run("Reading dashboard acl should include default acl for parent folder and the child acl", func(t *testing.T) {
setup(t)
err := updateDashboardACL(t, dashboardStore, childDash.ID, dashboards.DashboardACL{
OrgID: 1,
UserID: currentUser.ID,
DashboardID: childDash.ID,
Permission: models.PERMISSION_EDIT,
})
require.Nil(t, err)
query := dashboards.GetDashboardACLInfoListQuery{OrgID: 1, DashboardID: childDash.ID}
queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query)
require.Nil(t, err)
defaultPermissionsId := int64(-1)
require.Equal(t, 3, len(queryResult))
require.Equal(t, defaultPermissionsId, queryResult[0].DashboardID)
require.Equal(t, org.RoleViewer, *queryResult[0].Role)
require.True(t, queryResult[0].Inherited)
require.Equal(t, defaultPermissionsId, queryResult[1].DashboardID)
require.Equal(t, org.RoleEditor, *queryResult[1].Role)
require.True(t, queryResult[1].Inherited)
require.Equal(t, childDash.ID, queryResult[2].DashboardID)
require.False(t, queryResult[2].Inherited)
})
t.Run("Add and delete dashboard permission", func(t *testing.T) {
setup(t)
err := updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{
OrgID: 1,
UserID: currentUser.ID,
DashboardID: savedFolder.ID,
Permission: models.PERMISSION_EDIT,
})
require.Nil(t, err)
q1 := &dashboards.GetDashboardACLInfoListQuery{DashboardID: savedFolder.ID, OrgID: 1}
q1Result, err := dashboardStore.GetDashboardACLInfoList(context.Background(), q1)
require.Nil(t, err)
require.Equal(t, savedFolder.ID, q1Result[0].DashboardID)
require.Equal(t, models.PERMISSION_EDIT, q1Result[0].Permission)
require.Equal(t, "Edit", q1Result[0].PermissionName)
require.Equal(t, currentUser.ID, q1Result[0].UserID)
require.Equal(t, currentUser.Login, q1Result[0].UserLogin)
require.Equal(t, currentUser.Email, q1Result[0].UserEmail)
err = updateDashboardACL(t, dashboardStore, savedFolder.ID)
require.Nil(t, err)
q3 := &dashboards.GetDashboardACLInfoListQuery{DashboardID: savedFolder.ID, OrgID: 1}
q3Result, err := dashboardStore.GetDashboardACLInfoList(context.Background(), q3)
require.Nil(t, err)
require.Equal(t, 0, len(q3Result))
})
t.Run("Should be able to add a user permission for a team", func(t *testing.T) {
setup(t)
teamSvc := teamimpl.ProvideService(sqlStore, sqlStore.Cfg)
team1, err := teamSvc.CreateTeam("group1 name", "", 1)
require.Nil(t, err)
err = updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{
OrgID: 1,
TeamID: team1.ID,
DashboardID: savedFolder.ID,
Permission: models.PERMISSION_EDIT,
})
require.Nil(t, err)
q1 := &dashboards.GetDashboardACLInfoListQuery{DashboardID: savedFolder.ID, OrgID: 1}
q1Result, err := dashboardStore.GetDashboardACLInfoList(context.Background(), q1)
require.Nil(t, err)
require.Equal(t, savedFolder.ID, q1Result[0].DashboardID)
require.Equal(t, models.PERMISSION_EDIT, q1Result[0].Permission)
require.Equal(t, team1.ID, q1Result[0].TeamID)
})
t.Run("Should be able to update an existing permission for a team", func(t *testing.T) {
setup(t)
teamSvc := teamimpl.ProvideService(sqlStore, sqlStore.Cfg)
team1, err := teamSvc.CreateTeam("group1 name", "", 1)
require.Nil(t, err)
err = updateDashboardACL(t, dashboardStore, savedFolder.ID, dashboards.DashboardACL{
OrgID: 1,
TeamID: team1.ID,
DashboardID: savedFolder.ID,
Permission: models.PERMISSION_ADMIN,
})
require.Nil(t, err)
q3 := &dashboards.GetDashboardACLInfoListQuery{DashboardID: savedFolder.ID, OrgID: 1}
q3Result, err := dashboardStore.GetDashboardACLInfoList(context.Background(), q3)
require.Nil(t, err)
require.Equal(t, 1, len(q3Result))
require.Equal(t, savedFolder.ID, q3Result[0].DashboardID)
require.Equal(t, models.PERMISSION_ADMIN, q3Result[0].Permission)
require.Equal(t, team1.ID, q3Result[0].TeamID)
})
})
t.Run("Default permissions for root folder dashboards", func(t *testing.T) {
setup(t)
var rootFolderId int64 = 0
//sqlStore := db.InitTestDB(t)
query := dashboards.GetDashboardACLInfoListQuery{DashboardID: rootFolderId, OrgID: 1}
queryResult, err := dashboardStore.GetDashboardACLInfoList(context.Background(), &query)
require.Nil(t, err)
require.Equal(t, 2, len(queryResult))
defaultPermissionsId := int64(-1)
require.Equal(t, defaultPermissionsId, queryResult[0].DashboardID)
require.Equal(t, org.RoleViewer, *queryResult[0].Role)
require.False(t, queryResult[0].Inherited)
require.Equal(t, defaultPermissionsId, queryResult[1].DashboardID)
require.Equal(t, org.RoleEditor, *queryResult[1].Role)
require.False(t, queryResult[1].Inherited)
})
t.Run("Delete acl by user", func(t *testing.T) {
setup(t)
err := dashboardStore.DeleteACLByUser(context.Background(), currentUser.ID)
require.NoError(t, err)
})
}
func createUser(t *testing.T, sqlStore *sqlstore.SQLStore, name string, role string, isAdmin bool) user.User {
t.Helper()
sqlStore.Cfg.AutoAssignOrg = true
sqlStore.Cfg.AutoAssignOrgId = 1
sqlStore.Cfg.AutoAssignOrgRole = role
qs := quotaimpl.ProvideService(sqlStore, sqlStore.Cfg)
orgService, err := orgimpl.ProvideService(sqlStore, sqlStore.Cfg, qs)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(sqlStore, orgService, sqlStore.Cfg, nil, nil, qs)
require.NoError(t, err)
currentUserCmd := user.CreateUserCommand{Login: name, Email: name + "@test.com", Name: "a " + name, IsAdmin: isAdmin}
currentUser, err := usrSvc.CreateUserForTests(context.Background(), &currentUserCmd)
require.NoError(t, err)
orgs, err := orgService.GetUserOrgList(context.Background(), &org.GetUserOrgListQuery{UserID: currentUser.ID})
require.NoError(t, err)
require.Equal(t, org.RoleType(role), orgs[0].Role)
return *currentUser
}