mirror of
https://github.com/grafana/grafana.git
synced 2025-02-14 01:23:32 -06:00
RBAC: search v1 permission filter part 1 - cleanup & updating tests (#71913)
* update tests and remove some AC disabled checks * remove test for old permission filter builder
This commit is contained in:
parent
3a50d7ea84
commit
25c4292a5f
@ -35,11 +35,9 @@ func ProvideService(cfg *setting.Cfg, store db.DB, routeRegister routing.RouteRe
|
||||
accessControl accesscontrol.AccessControl, features *featuremgmt.FeatureManager) (*Service, error) {
|
||||
service := ProvideOSSService(cfg, database.ProvideService(store), cache, features)
|
||||
|
||||
if !accesscontrol.IsDisabled(cfg) {
|
||||
api.NewAccessControlAPI(routeRegister, accessControl, service, features).RegisterAPIEndpoints()
|
||||
if err := accesscontrol.DeclareFixedRoles(service, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
api.NewAccessControlAPI(routeRegister, accessControl, service, features).RegisterAPIEndpoints()
|
||||
if err := accesscontrol.DeclareFixedRoles(service, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return service, nil
|
||||
|
@ -1,6 +1,17 @@
|
||||
package actest
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const Concurrency = 10
|
||||
const BatchSize = 1000
|
||||
@ -59,3 +70,64 @@ func ConcurrentBatch(workers, count, size int, eachFn func(start, end int) error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// creates a role, connected it to user and store all permission from the user in database
|
||||
func AddUserPermissionToDB(t testing.TB, db db.DB, user *user.SignedInUser) {
|
||||
t.Helper()
|
||||
err := db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
var oldRole accesscontrol.Role
|
||||
hadOldRole, err := sess.SQL("SELECT * FROM role where uid = 'test_role'").Get(&oldRole)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = sess.Exec("DELETE FROM role WHERE uid = 'test_role'")
|
||||
require.NoError(t, err)
|
||||
|
||||
role := &accesscontrol.Role{
|
||||
OrgID: user.OrgID,
|
||||
UID: "test_role",
|
||||
Name: "test:role",
|
||||
Updated: time.Now(),
|
||||
Created: time.Now(),
|
||||
}
|
||||
|
||||
if _, err := sess.Insert(role); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = sess.Insert(accesscontrol.UserRole{
|
||||
OrgID: role.OrgID,
|
||||
RoleID: role.ID,
|
||||
UserID: user.UserID,
|
||||
Created: time.Now(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
if hadOldRole {
|
||||
if _, err := sess.Exec("DELETE FROM permission WHERE role_id = ?", oldRole.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var permissions []accesscontrol.Permission
|
||||
for action, scopes := range user.Permissions[user.OrgID] {
|
||||
for _, scope := range scopes {
|
||||
p := accesscontrol.Permission{
|
||||
RoleID: role.ID, Action: action, Scope: scope, Created: time.Now(), Updated: time.Now(),
|
||||
}
|
||||
//p.Kind, p.Attribute, p.Identifier = p.SplitScope()
|
||||
|
||||
permissions = append(permissions, p)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := sess.InsertMulti(&permissions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
@ -960,26 +960,13 @@ func (d *dashboardStore) GetDashboards(ctx context.Context, query *dashboards.Ge
|
||||
}
|
||||
|
||||
func (d *dashboardStore) FindDashboards(ctx context.Context, query *dashboards.FindPersistedDashboardsQuery) ([]dashboards.DashboardSearchProjection, error) {
|
||||
filters := []interface{}{
|
||||
permissions.DashboardPermissionFilter{
|
||||
OrgRole: query.SignedInUser.OrgRole,
|
||||
OrgId: query.SignedInUser.OrgID,
|
||||
Dialect: d.store.GetDialect(),
|
||||
UserId: query.SignedInUser.UserID,
|
||||
PermissionLevel: query.Permission,
|
||||
},
|
||||
recursiveQueriesAreSupported, err := d.store.RecursiveQueriesAreSupported()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !ac.IsDisabled(d.cfg) {
|
||||
recursiveQueriesAreSupported, err := d.store.RecursiveQueriesAreSupported()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if access control is enabled, overwrite the filters so far
|
||||
filters = []interface{}{
|
||||
permissions.NewAccessControlDashboardPermissionFilter(query.SignedInUser, query.Permission, query.Type, d.features, recursiveQueriesAreSupported),
|
||||
}
|
||||
filters := []interface{}{
|
||||
permissions.NewAccessControlDashboardPermissionFilter(query.SignedInUser, query.Permission, query.Type, d.features, recursiveQueriesAreSupported),
|
||||
}
|
||||
|
||||
for _, filter := range query.Sort.Filter {
|
||||
@ -1031,7 +1018,7 @@ func (d *dashboardStore) FindDashboards(ctx context.Context, query *dashboards.F
|
||||
|
||||
sql, params := sb.ToSQL(limit, page)
|
||||
|
||||
err := d.store.WithDbSession(ctx, func(sess *db.Session) error {
|
||||
err = d.store.WithDbSession(ctx, func(sess *db.Session) error {
|
||||
return sess.SQL(sql, params...).Find(&res)
|
||||
})
|
||||
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -15,6 +14,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
@ -40,7 +40,7 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
t.Run("Testing DB", func(t *testing.T) {
|
||||
var sqlStore *sqlstore.SQLStore
|
||||
var flder, dashInRoot, childDash *dashboards.Dashboard
|
||||
var currentUser user.User
|
||||
var currentUser *user.SignedInUser
|
||||
var dashboardStore dashboards.Store
|
||||
|
||||
setup := func() {
|
||||
@ -54,16 +54,24 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
dashInRoot = insertTestDashboard(t, dashboardStore, "test dash 67", 1, 0, false, "prod", "webapp")
|
||||
childDash = insertTestDashboard(t, dashboardStore, "test dash 23", 1, flder.ID, false, "prod", "webapp")
|
||||
insertTestDashboard(t, dashboardStore, "test dash 45", 1, flder.ID, false, "prod")
|
||||
currentUser = createUser(t, sqlStore, "viewer", "Viewer", false)
|
||||
currentUser = &user.SignedInUser{
|
||||
UserID: 1,
|
||||
OrgID: 1,
|
||||
OrgRole: org.RoleViewer,
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("Given one dashboard folder with two dashboards and one dashboard in the root folder", func(t *testing.T) {
|
||||
setup()
|
||||
|
||||
t.Run("and no acls are set", func(t *testing.T) {
|
||||
t.Run("should return all dashboards", func(t *testing.T) {
|
||||
t.Run("and user can read folders and dashboards", func(t *testing.T) {
|
||||
currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: []string{dashboards.ScopeDashboardsAll},
|
||||
dashboards.ActionFoldersRead: []string{dashboards.ScopeFoldersAll}}}
|
||||
actest.AddUserPermissionToDB(t, sqlStore, currentUser)
|
||||
|
||||
t.Run("should return all dashboards and folders", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
|
||||
SignedInUser: currentUser,
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{flder.ID, dashInRoot.ID},
|
||||
}
|
||||
@ -75,120 +83,54 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("and acl is set for dashboard folder", func(t *testing.T) {
|
||||
var otherUser int64 = 999
|
||||
err := updateDashboardACL(t, dashboardStore, flder.ID, dashboards.DashboardACL{
|
||||
DashboardID: flder.ID,
|
||||
OrgID: 1,
|
||||
UserID: otherUser,
|
||||
Permission: dashboards.PERMISSION_EDIT,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
t.Run("and user can only read dashboards", func(t *testing.T) {
|
||||
currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: []string{dashboards.ScopeDashboardsAll}}}
|
||||
actest.AddUserPermissionToDB(t, sqlStore, currentUser)
|
||||
|
||||
t.Run("should not return folder", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
|
||||
OrgId: 1, DashboardIds: []int64{flder.ID, dashInRoot.ID},
|
||||
SignedInUser: currentUser,
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{flder.ID, dashInRoot.ID},
|
||||
}
|
||||
hits, err := testSearchDashboards(dashboardStore, query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(hits), 1)
|
||||
require.Equal(t, 1, len(hits))
|
||||
require.Equal(t, hits[0].ID, dashInRoot.ID)
|
||||
})
|
||||
|
||||
t.Run("when the user is given permission", func(t *testing.T) {
|
||||
err := updateDashboardACL(t, dashboardStore, flder.ID, dashboards.DashboardACL{
|
||||
DashboardID: flder.ID, OrgID: 1, UserID: currentUser.ID, Permission: dashboards.PERMISSION_EDIT,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("should be able to access folder", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{flder.ID, dashInRoot.ID},
|
||||
}
|
||||
hits, err := testSearchDashboards(dashboardStore, query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(hits), 2)
|
||||
require.Equal(t, hits[0].ID, flder.ID)
|
||||
require.Equal(t, hits[1].ID, dashInRoot.ID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("when the user is an admin", func(t *testing.T) {
|
||||
t.Run("should be able to access folder", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &user.SignedInUser{
|
||||
UserID: currentUser.ID,
|
||||
OrgID: 1,
|
||||
OrgRole: org.RoleAdmin,
|
||||
},
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{flder.ID, dashInRoot.ID},
|
||||
}
|
||||
hits, err := testSearchDashboards(dashboardStore, query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(hits), 2)
|
||||
require.Equal(t, hits[0].ID, flder.ID)
|
||||
require.Equal(t, hits[1].ID, dashInRoot.ID)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("and acl is set for dashboard child and folder has all permissions removed", func(t *testing.T) {
|
||||
var otherUser int64 = 999
|
||||
err := updateDashboardACL(t, dashboardStore, flder.ID)
|
||||
require.NoError(t, err)
|
||||
err = updateDashboardACL(t, dashboardStore, childDash.ID, dashboards.DashboardACL{
|
||||
DashboardID: flder.ID, OrgID: 1, UserID: otherUser, Permission: dashboards.PERMISSION_EDIT,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
t.Run("and permissions are set for dashboard child and folder has all permissions removed", func(t *testing.T) {
|
||||
currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dashInRoot.UID)}}}
|
||||
actest.AddUserPermissionToDB(t, sqlStore, currentUser)
|
||||
|
||||
t.Run("should not return folder or child", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer}, OrgId: 1, DashboardIds: []int64{flder.ID, childDash.ID, dashInRoot.ID},
|
||||
SignedInUser: currentUser,
|
||||
DashboardIds: []int64{flder.ID, childDash.ID, dashInRoot.ID},
|
||||
}
|
||||
hits, err := testSearchDashboards(dashboardStore, query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(hits), 1)
|
||||
require.Equal(t, 1, len(hits))
|
||||
require.Equal(t, hits[0].ID, dashInRoot.ID)
|
||||
})
|
||||
|
||||
t.Run("when the user is given permission to child", func(t *testing.T) {
|
||||
err := updateDashboardACL(t, dashboardStore, childDash.ID, dashboards.DashboardACL{
|
||||
DashboardID: childDash.ID, OrgID: 1, UserID: currentUser.ID, Permission: dashboards.PERMISSION_EDIT,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsAll}}}
|
||||
actest.AddUserPermissionToDB(t, sqlStore, currentUser)
|
||||
|
||||
t.Run("should be able to search for child dashboard but not folder", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer}, OrgId: 1, DashboardIds: []int64{flder.ID, childDash.ID, dashInRoot.ID}}
|
||||
hits, err := testSearchDashboards(dashboardStore, query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(hits), 2)
|
||||
require.Equal(t, hits[0].ID, childDash.ID)
|
||||
require.Equal(t, hits[1].ID, dashInRoot.ID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("when the user is an admin", func(t *testing.T) {
|
||||
t.Run("should be able to search for child dash and folder", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &user.SignedInUser{
|
||||
UserID: currentUser.ID,
|
||||
OrgID: 1,
|
||||
OrgRole: org.RoleAdmin,
|
||||
},
|
||||
SignedInUser: currentUser,
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{flder.ID, dashInRoot.ID, childDash.ID},
|
||||
DashboardIds: []int64{flder.ID, childDash.ID, dashInRoot.ID},
|
||||
}
|
||||
hits, err := testSearchDashboards(dashboardStore, query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(hits), 3)
|
||||
require.Equal(t, hits[0].ID, flder.ID)
|
||||
require.Equal(t, hits[1].ID, childDash.ID)
|
||||
require.Equal(t, hits[2].ID, dashInRoot.ID)
|
||||
require.Equal(t, 2, len(hits))
|
||||
require.Equal(t, hits[0].ID, childDash.ID)
|
||||
require.Equal(t, hits[1].ID, dashInRoot.ID)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -197,13 +139,14 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
t.Run("Given two dashboard folders with one dashboard each and one dashboard in the root folder", func(t *testing.T) {
|
||||
var sqlStore *sqlstore.SQLStore
|
||||
var folder1, folder2, dashInRoot, childDash1, childDash2 *dashboards.Dashboard
|
||||
var currentUser user.User
|
||||
var rootFolderId int64 = 0
|
||||
var currentUser *user.SignedInUser
|
||||
|
||||
setup2 := func() {
|
||||
sqlStore = db.InitTestDB(t)
|
||||
quotaService := quotatest.New(false, nil)
|
||||
dashboardStore, err := ProvideDashboardStore(sqlStore, sqlStore.Cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
||||
var err error
|
||||
dashboardStore, err = ProvideDashboardStore(sqlStore, sqlStore.Cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
folder1 = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod")
|
||||
folder2 = insertTestDashboard(t, dashboardStore, "2 test dash folder", 1, 0, true, "prod")
|
||||
@ -211,18 +154,26 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
childDash1 = insertTestDashboard(t, dashboardStore, "child dash 1", 1, folder1.ID, false, "prod")
|
||||
childDash2 = insertTestDashboard(t, dashboardStore, "child dash 2", 1, folder2.ID, false, "prod")
|
||||
|
||||
currentUser = createUser(t, sqlStore, "viewer", "Viewer", false)
|
||||
currentUser = &user.SignedInUser{
|
||||
UserID: 1,
|
||||
OrgID: 1,
|
||||
OrgRole: org.RoleViewer,
|
||||
}
|
||||
}
|
||||
|
||||
setup2()
|
||||
t.Run("and one folder is expanded, the other collapsed", func(t *testing.T) {
|
||||
currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsAll}, dashboards.ActionFoldersRead: []string{dashboards.ScopeFoldersAll}}}
|
||||
actest.AddUserPermissionToDB(t, sqlStore, currentUser)
|
||||
|
||||
t.Run("should return dashboards in root and expanded folder", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
FolderIds: []int64{
|
||||
rootFolderId, folder1.ID}, SignedInUser: &user.SignedInUser{UserID: currentUser.ID,
|
||||
OrgID: 1, OrgRole: org.RoleViewer,
|
||||
rootFolderId,
|
||||
folder1.ID,
|
||||
},
|
||||
OrgId: 1,
|
||||
SignedInUser: currentUser,
|
||||
OrgId: 1,
|
||||
}
|
||||
hits, err := testSearchDashboards(dashboardStore, query)
|
||||
require.NoError(t, err)
|
||||
@ -235,18 +186,14 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("and acl is set for one dashboard folder", func(t *testing.T) {
|
||||
const otherUser int64 = 999
|
||||
err := updateDashboardACL(t, dashboardStore, folder1.ID, dashboards.DashboardACL{
|
||||
DashboardID: folder1.ID, OrgID: 1, UserID: otherUser, Permission: dashboards.PERMISSION_EDIT,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("and a dashboard is moved from folder without acl to the folder with an acl", func(t *testing.T) {
|
||||
moveDashboard(t, dashboardStore, 1, childDash2.Data, folder1.ID)
|
||||
currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder2.UID), dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dashInRoot.UID)}}}
|
||||
actest.AddUserPermissionToDB(t, sqlStore, currentUser)
|
||||
|
||||
t.Run("should not return folder with acl or its children", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
|
||||
SignedInUser: currentUser,
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{folder1.ID, childDash1.ID, childDash2.ID, dashInRoot.ID},
|
||||
}
|
||||
@ -259,10 +206,12 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
t.Run("and a dashboard is moved from folder with acl to the folder without an acl", func(t *testing.T) {
|
||||
setup2()
|
||||
moveDashboard(t, dashboardStore, 1, childDash1.Data, folder2.ID)
|
||||
currentUser.Permissions = map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsProvider.GetResourceScopeUID(dashInRoot.UID), dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder2.UID)}, dashboards.ActionFoldersRead: {dashboards.ScopeFoldersProvider.GetResourceScopeUID(folder2.UID)}}}
|
||||
actest.AddUserPermissionToDB(t, sqlStore, currentUser)
|
||||
|
||||
t.Run("should return folder without acl and its children", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
|
||||
SignedInUser: currentUser,
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{folder2.ID, childDash1.ID, childDash2.ID, dashInRoot.ID},
|
||||
}
|
||||
@ -275,127 +224,6 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
|
||||
require.Equal(t, hits[3].ID, dashInRoot.ID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("and a dashboard with an acl is moved to the folder without an acl", func(t *testing.T) {
|
||||
err := updateDashboardACL(t, dashboardStore, childDash1.ID, dashboards.DashboardACL{
|
||||
DashboardID: childDash1.ID, OrgID: 1, UserID: otherUser, Permission: dashboards.PERMISSION_EDIT,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
moveDashboard(t, dashboardStore, 1, childDash1.Data, folder2.ID)
|
||||
|
||||
t.Run("should return folder without acl but not the dashboard with acl", func(t *testing.T) {
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &user.SignedInUser{UserID: currentUser.ID, OrgID: 1, OrgRole: org.RoleViewer},
|
||||
OrgId: 1,
|
||||
DashboardIds: []int64{folder2.ID, childDash1.ID, childDash2.ID, dashInRoot.ID},
|
||||
}
|
||||
hits, err := testSearchDashboards(dashboardStore, query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(hits), 4)
|
||||
require.Equal(t, hits[0].ID, folder2.ID)
|
||||
require.Equal(t, hits[1].ID, childDash1.ID)
|
||||
require.Equal(t, hits[2].ID, childDash2.ID)
|
||||
require.Equal(t, hits[3].ID, dashInRoot.ID)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Given two dashboard folders", func(t *testing.T) {
|
||||
var sqlStore *sqlstore.SQLStore
|
||||
var folder1, folder2 *dashboards.Dashboard
|
||||
var adminUser, editorUser, viewerUser user.User
|
||||
|
||||
setup3 := func() {
|
||||
sqlStore = db.InitTestDB(t)
|
||||
quotaService := quotatest.New(false, nil)
|
||||
dashboardStore, err := ProvideDashboardStore(sqlStore, sqlStore.Cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
||||
require.NoError(t, err)
|
||||
folder1 = insertTestDashboard(t, dashboardStore, "1 test dash folder", 1, 0, true, "prod")
|
||||
folder2 = insertTestDashboard(t, dashboardStore, "2 test dash folder", 1, 0, true, "prod")
|
||||
insertTestDashboard(t, dashboardStore, "folder in another org", 2, 0, true, "prod")
|
||||
|
||||
adminUser = createUser(t, sqlStore, "admin", "Admin", true)
|
||||
editorUser = createUser(t, sqlStore, "editor", "Editor", false)
|
||||
viewerUser = createUser(t, sqlStore, "viewer", "Viewer", false)
|
||||
}
|
||||
|
||||
setup3()
|
||||
t.Run("Admin users", func(t *testing.T) {
|
||||
t.Run("Should have write access to all dashboard folders in their org", func(t *testing.T) {
|
||||
query := dashboards.FindPersistedDashboardsQuery{
|
||||
OrgId: 1,
|
||||
SignedInUser: &user.SignedInUser{UserID: adminUser.ID, OrgRole: org.RoleAdmin, OrgID: 1},
|
||||
Permission: dashboards.PERMISSION_VIEW,
|
||||
Type: "dash-folder",
|
||||
}
|
||||
|
||||
hits, err := testSearchDashboards(dashboardStore, &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(hits), 2)
|
||||
require.Equal(t, hits[0].ID, folder1.ID)
|
||||
require.Equal(t, hits[1].ID, folder2.ID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Editor users", func(t *testing.T) {
|
||||
query := dashboards.FindPersistedDashboardsQuery{
|
||||
OrgId: 1,
|
||||
SignedInUser: &user.SignedInUser{UserID: editorUser.ID, OrgRole: org.RoleEditor, OrgID: 1},
|
||||
Permission: dashboards.PERMISSION_EDIT,
|
||||
}
|
||||
|
||||
t.Run("Should have write access to all dashboard folders with default ACL", func(t *testing.T) {
|
||||
hits, err := testSearchDashboards(dashboardStore, &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(hits), 2)
|
||||
require.Equal(t, hits[0].ID, folder1.ID)
|
||||
require.Equal(t, hits[1].ID, folder2.ID)
|
||||
})
|
||||
|
||||
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, dashboards.DashboardACL{
|
||||
DashboardID: folder1.ID, OrgID: 1, UserID: editorUser.ID, Permission: dashboards.PERMISSION_VIEW,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
hits, err := testSearchDashboards(dashboardStore, &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(hits), 1)
|
||||
require.Equal(t, hits[0].ID, folder2.ID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Viewer users", func(t *testing.T) {
|
||||
query := dashboards.FindPersistedDashboardsQuery{
|
||||
OrgId: 1,
|
||||
SignedInUser: &user.SignedInUser{UserID: viewerUser.ID, OrgRole: org.RoleViewer, OrgID: 1},
|
||||
Permission: dashboards.PERMISSION_EDIT,
|
||||
}
|
||||
|
||||
t.Run("Should have no write access to any dashboard folders with default ACL", func(t *testing.T) {
|
||||
hits, err := testSearchDashboards(dashboardStore, &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(hits), 0)
|
||||
})
|
||||
|
||||
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, dashboards.DashboardACL{
|
||||
DashboardID: folder1.ID, OrgID: 1, UserID: viewerUser.ID, Permission: dashboards.PERMISSION_EDIT,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
hits, err := testSearchDashboards(dashboardStore, &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, len(hits), 1)
|
||||
require.Equal(t, hits[0].ID, folder1.ID)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -415,8 +243,7 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) {
|
||||
dashInParentTitle = "dashboard in parent"
|
||||
dashInSubfolderTitle = "dashboard in subfolder"
|
||||
)
|
||||
var viewer user.SignedInUser
|
||||
var role *accesscontrol.Role
|
||||
var viewer *user.SignedInUser
|
||||
|
||||
setup := func() {
|
||||
sqlStore = db.InitTestDB(t)
|
||||
@ -431,7 +258,7 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
usr := createUser(t, sqlStore, "viewer", "Viewer", false)
|
||||
viewer = user.SignedInUser{
|
||||
viewer = &user.SignedInUser{
|
||||
UserID: usr.ID,
|
||||
OrgID: usr.OrgID,
|
||||
OrgRole: org.RoleViewer,
|
||||
@ -530,8 +357,6 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) {
|
||||
}
|
||||
_, err = dashboardWriteStore.SaveDashboard(context.Background(), saveDashboardCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
role = setupRBACRole(t, *sqlStore, &viewer)
|
||||
}
|
||||
|
||||
setup()
|
||||
@ -593,10 +418,10 @@ func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
viewer.Permissions = map[int64]map[string][]string{viewer.OrgID: tc.permissions}
|
||||
setupRBACPermission(t, *sqlStore, role, &viewer)
|
||||
actest.AddUserPermissionToDB(t, sqlStore, viewer)
|
||||
|
||||
query := &dashboards.FindPersistedDashboardsQuery{
|
||||
SignedInUser: &viewer,
|
||||
SignedInUser: viewer,
|
||||
OrgId: viewer.OrgID,
|
||||
}
|
||||
|
||||
@ -626,61 +451,3 @@ func moveDashboard(t *testing.T, dashboardStore dashboards.Store, orgId int64, d
|
||||
|
||||
return dash
|
||||
}
|
||||
|
||||
func setupRBACRole(t *testing.T, db sqlstore.SQLStore, user *user.SignedInUser) *accesscontrol.Role {
|
||||
t.Helper()
|
||||
var role *accesscontrol.Role
|
||||
err := db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
role = &accesscontrol.Role{
|
||||
OrgID: user.OrgID,
|
||||
UID: "test_role",
|
||||
Name: "test:role",
|
||||
Updated: time.Now(),
|
||||
Created: time.Now(),
|
||||
}
|
||||
_, err := sess.Insert(role)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = sess.Insert(accesscontrol.UserRole{
|
||||
OrgID: role.OrgID,
|
||||
RoleID: role.ID,
|
||||
UserID: user.UserID,
|
||||
Created: time.Now(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
return role
|
||||
}
|
||||
|
||||
func setupRBACPermission(t *testing.T, db sqlstore.SQLStore, role *accesscontrol.Role, user *user.SignedInUser) {
|
||||
t.Helper()
|
||||
err := db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
if _, err := sess.Exec("DELETE FROM permission WHERE role_id = ?", role.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var acPermission []accesscontrol.Permission
|
||||
for action, scopes := range user.Permissions[user.OrgID] {
|
||||
for _, scope := range scopes {
|
||||
acPermission = append(acPermission, accesscontrol.Permission{
|
||||
RoleID: role.ID, Action: action, Scope: scope, Created: time.Now(), Updated: time.Now(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := sess.InsertMulti(&acPermission); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
@ -4,13 +4,13 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/actest"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
dashboardsDB "github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
@ -85,11 +85,12 @@ func TestIntegrationListPublicDashboard(t *testing.T) {
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: fmt.Sprintf("dashboards:uid:%s", cDash.UID)},
|
||||
}
|
||||
|
||||
err := insertPermissions(sqlStore, orgId, "viewer", permissions)
|
||||
require.NoError(t, err)
|
||||
usr := &user.SignedInUser{UserID: 1, OrgID: orgId, Permissions: map[int64]map[string][]string{orgId: accesscontrol.GroupScopesByAction(permissions)}}
|
||||
|
||||
actest.AddUserPermissionToDB(t, sqlStore, usr)
|
||||
|
||||
query := &PublicDashboardListQuery{
|
||||
User: &user.SignedInUser{UserID: 1, OrgID: orgId, Permissions: map[int64]map[string][]string{orgId: accesscontrol.GroupScopesByAction(permissions)}},
|
||||
User: usr,
|
||||
OrgID: orgId,
|
||||
Page: 1,
|
||||
Limit: 50,
|
||||
@ -113,11 +114,12 @@ func TestIntegrationListPublicDashboard(t *testing.T) {
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: fmt.Sprintf("dashboards:uid:%s", cDash.UID)},
|
||||
}
|
||||
|
||||
err := insertPermissions(sqlStore, orgId, "viewer", permissions)
|
||||
require.NoError(t, err)
|
||||
usr := &user.SignedInUser{UserID: 1, OrgID: orgId, Permissions: map[int64]map[string][]string{orgId: accesscontrol.GroupScopesByAction(permissions)}}
|
||||
|
||||
actest.AddUserPermissionToDB(t, sqlStore, usr)
|
||||
|
||||
query := &PublicDashboardListQuery{
|
||||
User: &user.SignedInUser{UserID: 1, OrgID: orgId, Permissions: map[int64]map[string][]string{orgId: accesscontrol.GroupScopesByAction(permissions)}},
|
||||
User: usr,
|
||||
OrgID: orgId,
|
||||
Page: 1,
|
||||
Limit: 50,
|
||||
@ -140,11 +142,12 @@ func TestIntegrationListPublicDashboard(t *testing.T) {
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:another-dashboard-2-uid"},
|
||||
}
|
||||
|
||||
err := insertPermissions(sqlStore, orgId, "viewer", permissions)
|
||||
require.NoError(t, err)
|
||||
usr := &user.SignedInUser{UserID: 1, OrgID: orgId, Permissions: map[int64]map[string][]string{orgId: accesscontrol.GroupScopesByAction(permissions)}}
|
||||
|
||||
actest.AddUserPermissionToDB(t, sqlStore, usr)
|
||||
|
||||
query := &PublicDashboardListQuery{
|
||||
User: &user.SignedInUser{UserID: 1, OrgID: orgId, Permissions: map[int64]map[string][]string{orgId: accesscontrol.GroupScopesByAction(permissions)}},
|
||||
User: usr,
|
||||
OrgID: orgId,
|
||||
Page: 1,
|
||||
Limit: 50,
|
||||
@ -917,50 +920,3 @@ func insertPublicDashboard(t *testing.T, publicdashboardStore *PublicDashboardSt
|
||||
|
||||
return pubdash
|
||||
}
|
||||
|
||||
func insertPermissions(sqlStore *sqlstore.SQLStore, orgId int64, role string, permissions []accesscontrol.Permission) error {
|
||||
return sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
newRole := &accesscontrol.Role{
|
||||
OrgID: orgId,
|
||||
UID: fmt.Sprintf("basic_%s", role),
|
||||
Name: fmt.Sprintf("basic:%s", role),
|
||||
Updated: time.Now(),
|
||||
Created: time.Now(),
|
||||
}
|
||||
_, err := sess.Insert(newRole)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = sess.Insert(accesscontrol.BuiltinRole{
|
||||
OrgID: orgId,
|
||||
RoleID: newRole.ID,
|
||||
Role: strings.ToUpper(role[:1]) + role[1:],
|
||||
Created: time.Now(),
|
||||
Updated: time.Now(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range permissions {
|
||||
permissions[i].RoleID = newRole.ID
|
||||
permissions[i].Created = time.Now()
|
||||
permissions[i].Updated = time.Now()
|
||||
}
|
||||
|
||||
_, err = sess.InsertMulti(&permissions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = sess.Insert(accesscontrol.UserRole{
|
||||
OrgID: orgId,
|
||||
RoleID: newRole.ID,
|
||||
UserID: 1,
|
||||
Created: time.Now(),
|
||||
})
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/permissions"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
@ -29,68 +28,25 @@ type simpleAuthService struct {
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
type dashIdQueryResult struct {
|
||||
UID string `xorm:"uid"`
|
||||
}
|
||||
|
||||
func (a *simpleAuthService) GetDashboardReadFilter(ctx context.Context, orgID int64, user *user.SignedInUser) (ResourceFilter, error) {
|
||||
if !a.ac.IsDisabled() {
|
||||
canReadDashboard, canReadFolder := accesscontrol.Checker(user, dashboards.ActionDashboardsRead), accesscontrol.Checker(user, dashboards.ActionFoldersRead)
|
||||
return func(kind entityKind, uid, parent string) bool {
|
||||
if kind == entityKindFolder {
|
||||
scopes, err := dashboards.GetInheritedScopes(ctx, orgID, uid, a.folderService)
|
||||
if err != nil {
|
||||
a.logger.Debug("could not retrieve inherited folder scopes:", "err", err)
|
||||
}
|
||||
scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(uid))
|
||||
return canReadFolder(scopes...)
|
||||
} else if kind == entityKindDashboard {
|
||||
scopes, err := dashboards.GetInheritedScopes(ctx, orgID, parent, a.folderService)
|
||||
if err != nil {
|
||||
a.logger.Debug("could not retrieve inherited folder scopes:", "err", err)
|
||||
}
|
||||
scopes = append(scopes, dashboards.ScopeDashboardsProvider.GetResourceScopeUID(uid))
|
||||
scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(parent))
|
||||
return canReadDashboard(scopes...)
|
||||
canReadDashboard, canReadFolder := accesscontrol.Checker(user, dashboards.ActionDashboardsRead), accesscontrol.Checker(user, dashboards.ActionFoldersRead)
|
||||
return func(kind entityKind, uid, parent string) bool {
|
||||
if kind == entityKindFolder {
|
||||
scopes, err := dashboards.GetInheritedScopes(ctx, orgID, uid, a.folderService)
|
||||
if err != nil {
|
||||
a.logger.Debug("could not retrieve inherited folder scopes:", "err", err)
|
||||
}
|
||||
return false
|
||||
}, nil
|
||||
}
|
||||
|
||||
filter := permissions.DashboardPermissionFilter{
|
||||
OrgRole: user.OrgRole,
|
||||
OrgId: user.OrgID,
|
||||
Dialect: a.sql.GetDialect(),
|
||||
UserId: user.UserID,
|
||||
PermissionLevel: dashboards.PERMISSION_VIEW,
|
||||
}
|
||||
rows := make([]*dashIdQueryResult, 0)
|
||||
|
||||
err := a.sql.WithDbSession(context.Background(), func(sess *db.Session) error {
|
||||
sql, params := filter.Where()
|
||||
sess.Table("dashboard").
|
||||
Where(sql, params...).
|
||||
Where("org_id = ?", user.OrgID).
|
||||
Cols("uid")
|
||||
|
||||
err := sess.Find(&rows)
|
||||
if err != nil {
|
||||
return err
|
||||
scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(uid))
|
||||
return canReadFolder(scopes...)
|
||||
} else if kind == entityKindDashboard {
|
||||
scopes, err := dashboards.GetInheritedScopes(ctx, orgID, parent, a.folderService)
|
||||
if err != nil {
|
||||
a.logger.Debug("could not retrieve inherited folder scopes:", "err", err)
|
||||
}
|
||||
scopes = append(scopes, dashboards.ScopeDashboardsProvider.GetResourceScopeUID(uid))
|
||||
scopes = append(scopes, dashboards.ScopeFoldersProvider.GetResourceScopeUID(parent))
|
||||
return canReadDashboard(scopes...)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uids := make(map[string]bool, len(rows)+1)
|
||||
for i := 0; i < len(rows); i++ {
|
||||
uids[rows[i].UID] = true
|
||||
}
|
||||
|
||||
return func(_ entityKind, uid, _ string) bool {
|
||||
return uids[uid]
|
||||
}, err
|
||||
return false
|
||||
}, nil
|
||||
}
|
||||
|
@ -10,8 +10,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/folder"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
@ -19,73 +17,6 @@ import (
|
||||
// maximum possible capacity for recursive queries array: one query for folder and one for dashboard actions
|
||||
const maximumRecursiveQueries = 2
|
||||
|
||||
type DashboardPermissionFilter struct {
|
||||
OrgRole org.RoleType
|
||||
Dialect migrator.Dialect
|
||||
UserId int64
|
||||
OrgId int64
|
||||
PermissionLevel dashboards.PermissionType
|
||||
}
|
||||
|
||||
func (d DashboardPermissionFilter) Where() (string, []interface{}) {
|
||||
if d.OrgRole == org.RoleAdmin {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
okRoles := []interface{}{d.OrgRole}
|
||||
if d.OrgRole == org.RoleEditor {
|
||||
okRoles = append(okRoles, org.RoleViewer)
|
||||
}
|
||||
|
||||
falseStr := d.Dialect.BooleanStr(false)
|
||||
|
||||
sql := `(
|
||||
dashboard.id IN (
|
||||
SELECT distinct DashboardId from (
|
||||
SELECT d.id AS DashboardId
|
||||
FROM dashboard AS d
|
||||
LEFT JOIN dashboard_acl AS da ON
|
||||
da.dashboard_id = d.id OR
|
||||
da.dashboard_id = d.folder_id
|
||||
WHERE
|
||||
d.org_id = ? AND
|
||||
da.permission >= ? AND
|
||||
(
|
||||
da.user_id = ? OR
|
||||
da.team_id IN (SELECT team_id from team_member AS tm WHERE tm.user_id = ?) OR
|
||||
da.role IN (?` + strings.Repeat(",?", len(okRoles)-1) + `)
|
||||
)
|
||||
UNION
|
||||
SELECT d.id AS DashboardId
|
||||
FROM dashboard AS d
|
||||
LEFT JOIN dashboard AS folder on folder.id = d.folder_id
|
||||
LEFT JOIN dashboard_acl AS da ON
|
||||
(
|
||||
-- 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 + `)
|
||||
)
|
||||
)
|
||||
WHERE
|
||||
d.org_id = ? AND
|
||||
da.permission >= ? AND
|
||||
(
|
||||
da.user_id = ? OR
|
||||
da.role IN (?` + strings.Repeat(",?", len(okRoles)-1) + `)
|
||||
)
|
||||
) AS a
|
||||
)
|
||||
)
|
||||
`
|
||||
|
||||
params := []interface{}{d.OrgId, d.PermissionLevel, d.UserId, d.UserId}
|
||||
params = append(params, okRoles...)
|
||||
params = append(params, d.OrgId, d.PermissionLevel, d.UserId)
|
||||
params = append(params, okRoles...)
|
||||
return sql, params
|
||||
}
|
||||
|
||||
type clause struct {
|
||||
string
|
||||
params []interface{}
|
||||
|
@ -113,43 +113,6 @@ func TestBuilder_Pagination(t *testing.T) {
|
||||
assert.Equal(t, "P", resPg2[0].Title, "page 2 should start with the 16th dashboard")
|
||||
}
|
||||
|
||||
func TestBuilder_Permissions(t *testing.T) {
|
||||
user := &user.SignedInUser{
|
||||
UserID: 1,
|
||||
OrgID: 1,
|
||||
OrgRole: org.RoleViewer,
|
||||
}
|
||||
|
||||
store := setupTestEnvironment(t)
|
||||
createDashboards(t, store, 0, 1, user.OrgID)
|
||||
|
||||
level := dashboards.PERMISSION_EDIT
|
||||
|
||||
builder := &searchstore.Builder{
|
||||
Filters: []interface{}{
|
||||
searchstore.OrgFilter{OrgId: user.OrgID},
|
||||
searchstore.TitleSorter{},
|
||||
permissions.DashboardPermissionFilter{
|
||||
Dialect: store.GetDialect(),
|
||||
OrgRole: user.OrgRole,
|
||||
OrgId: user.OrgID,
|
||||
UserId: user.UserID,
|
||||
PermissionLevel: level,
|
||||
},
|
||||
},
|
||||
Dialect: store.GetDialect(),
|
||||
}
|
||||
|
||||
res := []dashboards.DashboardSearchProjection{}
|
||||
err := store.WithDbSession(context.Background(), func(sess *db.Session) error {
|
||||
sql, params := builder.ToSQL(limit, page)
|
||||
return sess.SQL(sql, params...).Find(&res)
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Len(t, res, 0)
|
||||
}
|
||||
|
||||
func TestBuilder_RBAC(t *testing.T) {
|
||||
testsCases := []struct {
|
||||
desc string
|
||||
|
Loading…
Reference in New Issue
Block a user