mirror of https://github.com/grafana/grafana.git
Search: Modify query for better performance (#77576)
* Add missing `org_id` in query condition * Update benchmarks
This commit is contained in:
parent
20b4cebc47
commit
f999fe3d12
|
|
@ -96,49 +96,97 @@ func BenchmarkFolderListAndSearch(b *testing.B) {
|
||||||
features *featuremgmt.FeatureManager
|
features *featuremgmt.FeatureManager
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "get root folders with nested folders feature enabled",
|
desc: "impl=default nested_folders=on get root folders",
|
||||||
|
url: "/api/folders",
|
||||||
|
expectedLen: LEVEL0_FOLDER_NUM,
|
||||||
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "impl=permissionsFilterRemoveSubquery nested_folders=on get root folders",
|
||||||
url: "/api/folders",
|
url: "/api/folders",
|
||||||
expectedLen: LEVEL0_FOLDER_NUM,
|
expectedLen: LEVEL0_FOLDER_NUM,
|
||||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "get subfolders with nested folders feature enabled",
|
desc: "impl=default nested_folders=on get subfolders",
|
||||||
|
url: "/api/folders?parentUid=folder0",
|
||||||
|
expectedLen: LEVEL1_FOLDER_NUM,
|
||||||
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "impl=permissionsFilterRemoveSubquery nested_folders=on get subfolders",
|
||||||
url: "/api/folders?parentUid=folder0",
|
url: "/api/folders?parentUid=folder0",
|
||||||
expectedLen: LEVEL1_FOLDER_NUM,
|
expectedLen: LEVEL1_FOLDER_NUM,
|
||||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "list all inherited dashboards with nested folders feature enabled",
|
desc: "impl=default nested_folders=on list all inherited dashboards",
|
||||||
|
url: "/api/search?type=dash-db&limit=5000",
|
||||||
|
expectedLen: withLimit(all),
|
||||||
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "impl=permissionsFilterRemoveSubquery nested_folders=on list all inherited dashboards",
|
||||||
url: "/api/search?type=dash-db&limit=5000",
|
url: "/api/search?type=dash-db&limit=5000",
|
||||||
expectedLen: withLimit(all),
|
expectedLen: withLimit(all),
|
||||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "search for pattern with nested folders feature enabled",
|
desc: "impl=default nested_folders=on search for pattern",
|
||||||
|
url: "/api/search?type=dash-db&query=dashboard_0_0&limit=5000",
|
||||||
|
expectedLen: withLimit(1 + LEVEL1_DASHBOARD_NUM + LEVEL2_FOLDER_NUM*LEVEL2_DASHBOARD_NUM),
|
||||||
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "impl=permissionsFilterRemoveSubquery nested_folders=on search for pattern",
|
||||||
url: "/api/search?type=dash-db&query=dashboard_0_0&limit=5000",
|
url: "/api/search?type=dash-db&query=dashboard_0_0&limit=5000",
|
||||||
expectedLen: withLimit(1 + LEVEL1_DASHBOARD_NUM + LEVEL2_FOLDER_NUM*LEVEL2_DASHBOARD_NUM),
|
expectedLen: withLimit(1 + LEVEL1_DASHBOARD_NUM + LEVEL2_FOLDER_NUM*LEVEL2_DASHBOARD_NUM),
|
||||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "search for specific dashboard nested folders feature enabled",
|
desc: "impl=default nested_folders=on search for specific dashboard",
|
||||||
|
url: "/api/search?type=dash-db&query=dashboard_0_0_0_0",
|
||||||
|
expectedLen: 1,
|
||||||
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "impl=permissionsFilterRemoveSubquery nested_folders=on search for specific dashboard",
|
||||||
url: "/api/search?type=dash-db&query=dashboard_0_0_0_0",
|
url: "/api/search?type=dash-db&query=dashboard_0_0_0_0",
|
||||||
expectedLen: 1,
|
expectedLen: 1,
|
||||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "get root folders with nested folders feature disabled",
|
desc: "impl=default nested_folders=off get root folders",
|
||||||
|
url: "/api/folders?limit=5000",
|
||||||
|
expectedLen: withLimit(LEVEL0_FOLDER_NUM),
|
||||||
|
features: featuremgmt.WithFeatures(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "impl=permissionsFilterRemoveSubquery nested_folders=off get root folders",
|
||||||
url: "/api/folders?limit=5000",
|
url: "/api/folders?limit=5000",
|
||||||
expectedLen: withLimit(LEVEL0_FOLDER_NUM),
|
expectedLen: withLimit(LEVEL0_FOLDER_NUM),
|
||||||
features: featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
features: featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "list all dashboards with nested folders feature disabled",
|
desc: "impl=default nested_folders=off list all dashboards",
|
||||||
|
url: "/api/search?type=dash-db&limit=5000",
|
||||||
|
expectedLen: withLimit(LEVEL0_FOLDER_NUM * LEVEL0_DASHBOARD_NUM),
|
||||||
|
features: featuremgmt.WithFeatures(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "impl=permissionsFilterRemoveSubquery nested_folders=off list all dashboards",
|
||||||
url: "/api/search?type=dash-db&limit=5000",
|
url: "/api/search?type=dash-db&limit=5000",
|
||||||
expectedLen: withLimit(LEVEL0_FOLDER_NUM * LEVEL0_DASHBOARD_NUM),
|
expectedLen: withLimit(LEVEL0_FOLDER_NUM * LEVEL0_DASHBOARD_NUM),
|
||||||
features: featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
features: featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "search specific dashboard with nested folders feature disabled",
|
desc: "impl=default nested_folders=off search specific dashboard",
|
||||||
|
url: "/api/search?type=dash-db&query=dashboard_0_0",
|
||||||
|
expectedLen: 1,
|
||||||
|
features: featuremgmt.WithFeatures(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "impl=permissionsFilterRemoveSubquery nested_folders=off search specific dashboard",
|
||||||
url: "/api/search?type=dash-db&query=dashboard_0_0",
|
url: "/api/search?type=dash-db&query=dashboard_0_0",
|
||||||
expectedLen: 1,
|
expectedLen: 1,
|
||||||
features: featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
features: featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ type PermissionsFilter interface {
|
||||||
Where() (string, []any)
|
Where() (string, []any)
|
||||||
|
|
||||||
buildClauses()
|
buildClauses()
|
||||||
nestedFoldersSelectors(permSelector string, permSelectorArgs []any, leftTableCol string, rightTableCol string) (string, []any)
|
nestedFoldersSelectors(permSelector string, permSelectorArgs []any, leftTableCol string, rightTableCol string, orgID int64) (string, []any)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccessControlDashboardPermissionFilter creates a new AccessControlDashboardPermissionFilter that is configured with specific actions calculated based on the dashboards.PermissionType and query type
|
// NewAccessControlDashboardPermissionFilter creates a new AccessControlDashboardPermissionFilter that is configured with specific actions calculated based on the dashboards.PermissionType and query type
|
||||||
|
|
@ -126,7 +126,8 @@ func (f *accessControlDashboardPermissionFilter) buildClauses() {
|
||||||
userID, _ = identity.IntIdentifier(namespaceID, identifier)
|
userID, _ = identity.IntIdentifier(namespaceID, identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
filter, params := accesscontrol.UserRolesFilter(f.user.GetOrgID(), userID, f.user.GetTeams(), accesscontrol.GetOrgRoles(f.user))
|
orgID := f.user.GetOrgID()
|
||||||
|
filter, params := accesscontrol.UserRolesFilter(orgID, userID, f.user.GetTeams(), accesscontrol.GetOrgRoles(f.user))
|
||||||
rolesFilter := " AND role_id IN(SELECT id FROM role " + filter + ") "
|
rolesFilter := " AND role_id IN(SELECT id FROM role " + filter + ") "
|
||||||
var args []any
|
var args []any
|
||||||
builder := strings.Builder{}
|
builder := strings.Builder{}
|
||||||
|
|
@ -208,9 +209,10 @@ func (f *accessControlDashboardPermissionFilter) buildClauses() {
|
||||||
builder.WriteString("(dashboard.folder_id IN (SELECT d.id FROM dashboard as d ")
|
builder.WriteString("(dashboard.folder_id IN (SELECT d.id FROM dashboard as d ")
|
||||||
recQueryName := fmt.Sprintf("RecQry%d", len(f.recQueries))
|
recQueryName := fmt.Sprintf("RecQry%d", len(f.recQueries))
|
||||||
f.addRecQry(recQueryName, permSelector.String(), permSelectorArgs)
|
f.addRecQry(recQueryName, permSelector.String(), permSelectorArgs)
|
||||||
builder.WriteString(fmt.Sprintf("WHERE d.uid IN (SELECT uid FROM %s)", recQueryName))
|
builder.WriteString(fmt.Sprintf("WHERE d.org_id = ? AND d.uid IN (SELECT uid FROM %s)", recQueryName))
|
||||||
|
args = append(args, orgID)
|
||||||
default:
|
default:
|
||||||
nestedFoldersSelectors, nestedFoldersArgs := f.nestedFoldersSelectors(permSelector.String(), permSelectorArgs, "dashboard.folder_id", "d.id")
|
nestedFoldersSelectors, nestedFoldersArgs := f.nestedFoldersSelectors(permSelector.String(), permSelectorArgs, "dashboard.folder_id", "d.id", orgID)
|
||||||
builder.WriteRune('(')
|
builder.WriteRune('(')
|
||||||
builder.WriteString(nestedFoldersSelectors)
|
builder.WriteString(nestedFoldersSelectors)
|
||||||
args = append(args, nestedFoldersArgs...)
|
args = append(args, nestedFoldersArgs...)
|
||||||
|
|
@ -222,7 +224,8 @@ func (f *accessControlDashboardPermissionFilter) buildClauses() {
|
||||||
default:
|
default:
|
||||||
builder.WriteString("(dashboard.folder_id IN (SELECT d.id FROM dashboard as d ")
|
builder.WriteString("(dashboard.folder_id IN (SELECT d.id FROM dashboard as d ")
|
||||||
if len(permSelectorArgs) > 0 {
|
if len(permSelectorArgs) > 0 {
|
||||||
builder.WriteString("WHERE d.uid IN ")
|
builder.WriteString("WHERE d.org_id = ? AND d.uid IN ")
|
||||||
|
args = append(args, orgID)
|
||||||
builder.WriteString(permSelector.String())
|
builder.WriteString(permSelector.String())
|
||||||
args = append(args, permSelectorArgs...)
|
args = append(args, permSelectorArgs...)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -287,7 +290,7 @@ func (f *accessControlDashboardPermissionFilter) buildClauses() {
|
||||||
builder.WriteString("(dashboard.uid IN ")
|
builder.WriteString("(dashboard.uid IN ")
|
||||||
builder.WriteString(fmt.Sprintf("(SELECT uid FROM %s)", recQueryName))
|
builder.WriteString(fmt.Sprintf("(SELECT uid FROM %s)", recQueryName))
|
||||||
default:
|
default:
|
||||||
nestedFoldersSelectors, nestedFoldersArgs := f.nestedFoldersSelectors(permSelector.String(), permSelectorArgs, "dashboard.uid", "d.uid")
|
nestedFoldersSelectors, nestedFoldersArgs := f.nestedFoldersSelectors(permSelector.String(), permSelectorArgs, "dashboard.uid", "d.uid", orgID)
|
||||||
builder.WriteRune('(')
|
builder.WriteRune('(')
|
||||||
builder.WriteString(nestedFoldersSelectors)
|
builder.WriteString(nestedFoldersSelectors)
|
||||||
builder.WriteRune(')')
|
builder.WriteRune(')')
|
||||||
|
|
@ -372,7 +375,7 @@ func actionsToCheck(actions []string, permissions map[string][]string, wildcards
|
||||||
return toCheck
|
return toCheck
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *accessControlDashboardPermissionFilter) nestedFoldersSelectors(permSelector string, permSelectorArgs []any, leftTableCol string, rightTableCol string) (string, []any) {
|
func (f *accessControlDashboardPermissionFilter) nestedFoldersSelectors(permSelector string, permSelectorArgs []any, leftTableCol string, rightTableCol string, orgID int64) (string, []any) {
|
||||||
wheres := make([]string, 0, folder.MaxNestedFolderDepth+1)
|
wheres := make([]string, 0, folder.MaxNestedFolderDepth+1)
|
||||||
args := make([]any, 0, len(permSelectorArgs)*(folder.MaxNestedFolderDepth+1))
|
args := make([]any, 0, len(permSelectorArgs)*(folder.MaxNestedFolderDepth+1))
|
||||||
|
|
||||||
|
|
@ -387,7 +390,8 @@ func (f *accessControlDashboardPermissionFilter) nestedFoldersSelectors(permSele
|
||||||
s := fmt.Sprintf(tmpl, t, prev, onCol, t, prev, t)
|
s := fmt.Sprintf(tmpl, t, prev, onCol, t, prev, t)
|
||||||
joins = append(joins, s)
|
joins = append(joins, s)
|
||||||
|
|
||||||
wheres = append(wheres, fmt.Sprintf("(%s IN (SELECT %s FROM dashboard d %s WHERE %s.uid IN %s)", leftTableCol, rightTableCol, strings.Join(joins, " "), t, permSelector))
|
wheres = append(wheres, fmt.Sprintf("(%s IN (SELECT %s FROM dashboard d %s WHERE %s.org_id = ? AND %s.uid IN %s)", leftTableCol, rightTableCol, strings.Join(joins, " "), t, t, permSelector))
|
||||||
|
args = append(args, orgID)
|
||||||
args = append(args, permSelectorArgs...)
|
args = append(args, permSelectorArgs...)
|
||||||
|
|
||||||
prev = t
|
prev = t
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,8 @@ func (f *accessControlDashboardPermissionFilterNoFolderSubquery) buildClauses()
|
||||||
userID, _ = identity.IntIdentifier(namespaceID, identifier)
|
userID, _ = identity.IntIdentifier(namespaceID, identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
filter, params := accesscontrol.UserRolesFilter(f.user.GetOrgID(), userID, f.user.GetTeams(), accesscontrol.GetOrgRoles(f.user))
|
orgID := f.user.GetOrgID()
|
||||||
|
filter, params := accesscontrol.UserRolesFilter(orgID, userID, f.user.GetTeams(), accesscontrol.GetOrgRoles(f.user))
|
||||||
rolesFilter := " AND role_id IN(SELECT id FROM role " + filter + ") "
|
rolesFilter := " AND role_id IN(SELECT id FROM role " + filter + ") "
|
||||||
var args []any
|
var args []any
|
||||||
builder := strings.Builder{}
|
builder := strings.Builder{}
|
||||||
|
|
@ -124,7 +125,7 @@ func (f *accessControlDashboardPermissionFilterNoFolderSubquery) buildClauses()
|
||||||
f.addRecQry(recQueryName, permSelector.String(), permSelectorArgs)
|
f.addRecQry(recQueryName, permSelector.String(), permSelectorArgs)
|
||||||
builder.WriteString("(folder.uid IN (SELECT uid FROM " + recQueryName)
|
builder.WriteString("(folder.uid IN (SELECT uid FROM " + recQueryName)
|
||||||
default:
|
default:
|
||||||
nestedFoldersSelectors, nestedFoldersArgs := f.nestedFoldersSelectors(permSelector.String(), permSelectorArgs, "folder.uid", "")
|
nestedFoldersSelectors, nestedFoldersArgs := f.nestedFoldersSelectors(permSelector.String(), permSelectorArgs, "folder.uid", "", orgID)
|
||||||
builder.WriteRune('(')
|
builder.WriteRune('(')
|
||||||
builder.WriteString(nestedFoldersSelectors)
|
builder.WriteString(nestedFoldersSelectors)
|
||||||
args = append(args, nestedFoldersArgs...)
|
args = append(args, nestedFoldersArgs...)
|
||||||
|
|
@ -202,7 +203,7 @@ func (f *accessControlDashboardPermissionFilterNoFolderSubquery) buildClauses()
|
||||||
builder.WriteString("(dashboard.uid IN ")
|
builder.WriteString("(dashboard.uid IN ")
|
||||||
builder.WriteString(fmt.Sprintf("(SELECT uid FROM %s)", recQueryName))
|
builder.WriteString(fmt.Sprintf("(SELECT uid FROM %s)", recQueryName))
|
||||||
default:
|
default:
|
||||||
nestedFoldersSelectors, nestedFoldersArgs := f.nestedFoldersSelectors(permSelector.String(), permSelectorArgs, "dashboard.uid", "")
|
nestedFoldersSelectors, nestedFoldersArgs := f.nestedFoldersSelectors(permSelector.String(), permSelectorArgs, "dashboard.uid", "", orgID)
|
||||||
builder.WriteRune('(')
|
builder.WriteRune('(')
|
||||||
builder.WriteString(nestedFoldersSelectors)
|
builder.WriteString(nestedFoldersSelectors)
|
||||||
builder.WriteRune(')')
|
builder.WriteRune(')')
|
||||||
|
|
@ -230,7 +231,7 @@ func (f *accessControlDashboardPermissionFilterNoFolderSubquery) buildClauses()
|
||||||
f.where = clause{string: builder.String(), params: args}
|
f.where = clause{string: builder.String(), params: args}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *accessControlDashboardPermissionFilterNoFolderSubquery) nestedFoldersSelectors(permSelector string, permSelectorArgs []any, leftTableCol string, _ string) (string, []any) {
|
func (f *accessControlDashboardPermissionFilterNoFolderSubquery) nestedFoldersSelectors(permSelector string, permSelectorArgs []any, leftTableCol string, _ string, orgID int64) (string, []any) {
|
||||||
wheres := make([]string, 0, folder.MaxNestedFolderDepth+1)
|
wheres := make([]string, 0, folder.MaxNestedFolderDepth+1)
|
||||||
args := make([]any, 0, len(permSelectorArgs)*(folder.MaxNestedFolderDepth+1))
|
args := make([]any, 0, len(permSelectorArgs)*(folder.MaxNestedFolderDepth+1))
|
||||||
|
|
||||||
|
|
@ -247,7 +248,8 @@ func (f *accessControlDashboardPermissionFilterNoFolderSubquery) nestedFoldersSe
|
||||||
s := fmt.Sprintf(tmpl, t, prev, t, prev, t)
|
s := fmt.Sprintf(tmpl, t, prev, t, prev, t)
|
||||||
joins = append(joins, s)
|
joins = append(joins, s)
|
||||||
|
|
||||||
wheres = append(wheres, fmt.Sprintf("(%s IN (SELECT f1.uid FROM folder f1 %s WHERE %s.uid IN %s)", leftTableCol, strings.Join(joins, " "), t, permSelector))
|
wheres = append(wheres, fmt.Sprintf("(%s IN (SELECT f1.uid FROM folder f1 %s WHERE %s.org_id = ? AND %s.uid IN %s)", leftTableCol, strings.Join(joins, " "), t, t, permSelector))
|
||||||
|
args = append(args, orgID)
|
||||||
args = append(args, permSelectorArgs...)
|
args = append(args, permSelectorArgs...)
|
||||||
|
|
||||||
prev = t
|
prev = t
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package searchstore_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
@ -120,12 +119,12 @@ func TestBuilder_RBAC(t *testing.T) {
|
||||||
testsCases := []struct {
|
testsCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
userPermissions []accesscontrol.Permission
|
userPermissions []accesscontrol.Permission
|
||||||
features []any
|
features featuremgmt.FeatureToggles
|
||||||
expectedParams []any
|
expectedParams []any
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
desc: "no user permissions",
|
desc: "no user permissions",
|
||||||
features: []any{},
|
features: featuremgmt.WithFeatures(),
|
||||||
expectedParams: []any{
|
expectedParams: []any{
|
||||||
int64(1),
|
int64(1),
|
||||||
},
|
},
|
||||||
|
|
@ -135,7 +134,83 @@ func TestBuilder_RBAC(t *testing.T) {
|
||||||
userPermissions: []accesscontrol.Permission{
|
userPermissions: []accesscontrol.Permission{
|
||||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"},
|
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"},
|
||||||
},
|
},
|
||||||
features: []any{},
|
features: featuremgmt.WithFeatures(),
|
||||||
|
expectedParams: []any{
|
||||||
|
int64(1),
|
||||||
|
int64(1),
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"Viewer",
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"dashboards:read",
|
||||||
|
"dashboards:write",
|
||||||
|
2,
|
||||||
|
int64(1),
|
||||||
|
int64(1),
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"Viewer",
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"dashboards:read",
|
||||||
|
"dashboards:write",
|
||||||
|
2,
|
||||||
|
int64(1),
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"Viewer",
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"folders:read",
|
||||||
|
"dashboards:create",
|
||||||
|
2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "user with view permission with nesting",
|
||||||
|
userPermissions: []accesscontrol.Permission{
|
||||||
|
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"},
|
||||||
|
},
|
||||||
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||||
|
expectedParams: []any{
|
||||||
|
int64(1),
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"Viewer",
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"dashboards:read",
|
||||||
|
"dashboards:write",
|
||||||
|
2,
|
||||||
|
int64(1),
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"Viewer",
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"folders:read",
|
||||||
|
"dashboards:create",
|
||||||
|
2,
|
||||||
|
int64(1),
|
||||||
|
int64(1),
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"Viewer",
|
||||||
|
int64(1),
|
||||||
|
0,
|
||||||
|
"dashboards:read",
|
||||||
|
"dashboards:write",
|
||||||
|
2,
|
||||||
|
int64(1),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "user with view permission with remove subquery",
|
||||||
|
userPermissions: []accesscontrol.Permission{
|
||||||
|
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"},
|
||||||
|
},
|
||||||
|
features: featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||||
expectedParams: []any{
|
expectedParams: []any{
|
||||||
int64(1),
|
int64(1),
|
||||||
int64(1),
|
int64(1),
|
||||||
|
|
@ -168,11 +243,11 @@ func TestBuilder_RBAC(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "user with view permission with nesting",
|
desc: "user with view permission with nesting and remove subquery",
|
||||||
userPermissions: []accesscontrol.Permission{
|
userPermissions: []accesscontrol.Permission{
|
||||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"},
|
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"},
|
||||||
},
|
},
|
||||||
features: []any{featuremgmt.FlagNestedFolders},
|
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||||
expectedParams: []any{
|
expectedParams: []any{
|
||||||
int64(1),
|
int64(1),
|
||||||
int64(1),
|
int64(1),
|
||||||
|
|
@ -219,48 +294,39 @@ func TestBuilder_RBAC(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
for _, tc := range testsCases {
|
for _, tc := range testsCases {
|
||||||
for _, features := range []*featuremgmt.FeatureManager{featuremgmt.WithFeatures(tc.features...), featuremgmt.WithFeatures(append(tc.features, featuremgmt.FlagPermissionsFilterRemoveSubquery)...)} {
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
m := features.GetEnabled(context.Background())
|
if len(tc.userPermissions) > 0 {
|
||||||
keys := make([]string, 0, len(m))
|
user.Permissions = map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tc.userPermissions)}
|
||||||
for k := range m {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run(tc.desc+" with features "+strings.Join(keys, ","), func(t *testing.T) {
|
level := dashboards.PERMISSION_EDIT
|
||||||
if len(tc.userPermissions) > 0 {
|
|
||||||
user.Permissions = map[int64]map[string][]string{1: accesscontrol.GroupScopesByAction(tc.userPermissions)}
|
|
||||||
}
|
|
||||||
|
|
||||||
level := dashboards.PERMISSION_EDIT
|
builder := &searchstore.Builder{
|
||||||
|
Filters: []any{
|
||||||
|
searchstore.OrgFilter{OrgId: user.OrgID},
|
||||||
|
searchstore.TitleSorter{},
|
||||||
|
permissions.NewAccessControlDashboardPermissionFilter(
|
||||||
|
user,
|
||||||
|
level,
|
||||||
|
"",
|
||||||
|
tc.features,
|
||||||
|
recursiveQueriesAreSupported,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Dialect: store.GetDialect(),
|
||||||
|
Features: tc.features,
|
||||||
|
}
|
||||||
|
|
||||||
builder := &searchstore.Builder{
|
res := []dashboards.DashboardSearchProjection{}
|
||||||
Filters: []any{
|
err := store.WithDbSession(context.Background(), func(sess *db.Session) error {
|
||||||
searchstore.OrgFilter{OrgId: user.OrgID},
|
sql, params := builder.ToSQL(limit, page)
|
||||||
searchstore.TitleSorter{},
|
assert.Equal(t, tc.expectedParams, params)
|
||||||
permissions.NewAccessControlDashboardPermissionFilter(
|
return sess.SQL(sql, params...).Find(&res)
|
||||||
user,
|
|
||||||
level,
|
|
||||||
"",
|
|
||||||
features,
|
|
||||||
recursiveQueriesAreSupported,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
Dialect: store.GetDialect(),
|
|
||||||
Features: features,
|
|
||||||
}
|
|
||||||
|
|
||||||
res := []dashboards.DashboardSearchProjection{}
|
|
||||||
err := store.WithDbSession(context.Background(), func(sess *db.Session) error {
|
|
||||||
sql, params := builder.ToSQL(limit, page)
|
|
||||||
// TODO: replace with a proper test
|
|
||||||
assert.Equal(t, tc.expectedParams, params)
|
|
||||||
return sess.SQL(sql, params...).Find(&res)
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.Len(t, res, 0)
|
|
||||||
})
|
})
|
||||||
}
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Len(t, res, 0)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue