Nested folders: Remove feature flag (#109212)
This commit is contained in:
@@ -37,14 +37,9 @@ func (b *Builder) ToSQL(limit, page int64) (string, []any) {
|
||||
INNER JOIN dashboard ON ids.id = dashboard.id`)
|
||||
b.sql.WriteString("\n")
|
||||
|
||||
if b.Features.IsEnabledGlobally(featuremgmt.FlagNestedFolders) {
|
||||
// covered by UQE_folder_org_id_uid
|
||||
b.sql.WriteString(
|
||||
`LEFT OUTER JOIN folder ON folder.uid = dashboard.folder_uid AND folder.org_id = dashboard.org_id`)
|
||||
} else {
|
||||
b.sql.WriteString(`
|
||||
LEFT OUTER JOIN dashboard AS folder ON folder.id = dashboard.folder_id`)
|
||||
}
|
||||
// covered by UQE_folder_org_id_uid
|
||||
b.sql.WriteString(
|
||||
`LEFT OUTER JOIN folder ON folder.uid = dashboard.folder_uid AND folder.org_id = dashboard.org_id`)
|
||||
b.sql.WriteString(`
|
||||
LEFT OUTER JOIN dashboard_tag ON dashboard.id = dashboard_tag.dashboard_id`)
|
||||
b.sql.WriteString("\n")
|
||||
@@ -69,17 +64,9 @@ func (b *Builder) buildSelect() {
|
||||
dashboard.folder_id,
|
||||
dashboard.deleted,
|
||||
folder.uid AS folder_uid,
|
||||
folder.title AS folder_slug,
|
||||
folder.title AS folder_title
|
||||
`)
|
||||
if b.Features.IsEnabledGlobally(featuremgmt.FlagNestedFolders) {
|
||||
b.sql.WriteString(`
|
||||
folder.title AS folder_slug,`)
|
||||
} else {
|
||||
b.sql.WriteString(`
|
||||
folder.slug AS folder_slug,`)
|
||||
}
|
||||
b.sql.WriteString(`
|
||||
folder.title AS folder_title `)
|
||||
|
||||
for _, f := range b.Filters {
|
||||
if f, ok := f.(model.FilterSelect); ok {
|
||||
b.sql.WriteString(fmt.Sprintf(", %s", f.Select()))
|
||||
|
||||
@@ -66,10 +66,9 @@ func (f FolderFilter) Where() (string, []any) {
|
||||
}
|
||||
|
||||
type FolderUIDFilter struct {
|
||||
Dialect migrator.Dialect
|
||||
OrgID int64
|
||||
UIDs []string
|
||||
NestedFoldersEnabled bool
|
||||
Dialect migrator.Dialect
|
||||
OrgID int64
|
||||
UIDs []string
|
||||
}
|
||||
|
||||
func (f FolderUIDFilter) Where() (string, []any) {
|
||||
@@ -92,35 +91,19 @@ func (f FolderUIDFilter) Where() (string, []any) {
|
||||
case len(params) < 1:
|
||||
// do nothing
|
||||
case len(params) == 1:
|
||||
q = "dashboard.folder_id IN (SELECT id FROM dashboard WHERE org_id = ? AND uid = ?)"
|
||||
if f.NestedFoldersEnabled {
|
||||
q = "dashboard.org_id = ? AND dashboard.folder_uid = ?"
|
||||
}
|
||||
q = "dashboard.org_id = ? AND dashboard.folder_uid = ?"
|
||||
params = append([]any{f.OrgID}, params...)
|
||||
default:
|
||||
sqlArray := "(?" + strings.Repeat(",?", len(params)-1) + ")"
|
||||
q = "dashboard.folder_id IN (SELECT id FROM dashboard WHERE org_id = ? AND uid IN " + sqlArray + ")"
|
||||
if f.NestedFoldersEnabled {
|
||||
q = "dashboard.org_id = ? AND dashboard.folder_uid IN " + sqlArray
|
||||
}
|
||||
q = "dashboard.org_id = ? AND dashboard.folder_uid IN " + sqlArray
|
||||
params = append([]any{f.OrgID}, params...)
|
||||
}
|
||||
|
||||
if includeGeneral {
|
||||
if q == "" {
|
||||
if f.NestedFoldersEnabled {
|
||||
q = "dashboard.folder_uid IS NULL "
|
||||
} else {
|
||||
q = "dashboard.folder_id = ? "
|
||||
params = append(params, 0)
|
||||
}
|
||||
q = "dashboard.folder_uid IS NULL "
|
||||
} else {
|
||||
if f.NestedFoldersEnabled {
|
||||
q = "(" + q + " OR dashboard.folder_uid IS NULL)"
|
||||
} else {
|
||||
q = "(" + q + " OR dashboard.folder_id = ?)"
|
||||
params = append(params, 0)
|
||||
}
|
||||
q = "(" + q + " OR dashboard.folder_uid IS NULL)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,67 +12,34 @@ func TestIntegrationFolderUIDFilter(t *testing.T) {
|
||||
t.Skip("skipping integration test in short mode")
|
||||
}
|
||||
testCases := []struct {
|
||||
description string
|
||||
uids []string
|
||||
expectedSql string
|
||||
expectedParams []any
|
||||
nestedFoldersEnabled bool
|
||||
description string
|
||||
uids []string
|
||||
expectedSql string
|
||||
expectedParams []any
|
||||
}{
|
||||
{
|
||||
description: "searching general folder",
|
||||
uids: []string{"general"},
|
||||
expectedSql: "dashboard.folder_id = ? ",
|
||||
expectedParams: []any{0},
|
||||
nestedFoldersEnabled: false,
|
||||
description: "searching general folder",
|
||||
uids: []string{"general"},
|
||||
expectedSql: "dashboard.folder_uid IS NULL ",
|
||||
expectedParams: []any{},
|
||||
},
|
||||
{
|
||||
description: "searching a specific folder",
|
||||
uids: []string{"abc-123"},
|
||||
expectedSql: "dashboard.folder_id IN (SELECT id FROM dashboard WHERE org_id = ? AND uid = ?)",
|
||||
expectedParams: []any{int64(1), "abc-123"},
|
||||
nestedFoldersEnabled: false,
|
||||
description: "searching a specific folder",
|
||||
uids: []string{"abc-123"},
|
||||
expectedSql: "dashboard.org_id = ? AND dashboard.folder_uid = ?",
|
||||
expectedParams: []any{int64(1), "abc-123"},
|
||||
},
|
||||
{
|
||||
description: "searching a specific folders",
|
||||
uids: []string{"abc-123", "def-456"},
|
||||
expectedSql: "dashboard.folder_id IN (SELECT id FROM dashboard WHERE org_id = ? AND uid IN (?,?))",
|
||||
expectedParams: []any{int64(1), "abc-123", "def-456"},
|
||||
nestedFoldersEnabled: false,
|
||||
description: "searching a specific folders",
|
||||
uids: []string{"abc-123", "def-456"},
|
||||
expectedSql: "dashboard.org_id = ? AND dashboard.folder_uid IN (?,?)",
|
||||
expectedParams: []any{int64(1), "abc-123", "def-456"},
|
||||
},
|
||||
{
|
||||
description: "searching a specific folders or general",
|
||||
uids: []string{"general", "abc-123", "def-456"},
|
||||
expectedSql: "(dashboard.folder_id IN (SELECT id FROM dashboard WHERE org_id = ? AND uid IN (?,?)) OR dashboard.folder_id = ?)",
|
||||
expectedParams: []any{int64(1), "abc-123", "def-456", 0},
|
||||
nestedFoldersEnabled: false,
|
||||
},
|
||||
{
|
||||
description: "searching general folder with nestedFoldersEnabled",
|
||||
uids: []string{"general"},
|
||||
expectedSql: "dashboard.folder_uid IS NULL ",
|
||||
expectedParams: []any{},
|
||||
nestedFoldersEnabled: true,
|
||||
},
|
||||
{
|
||||
description: "searching a specific folder with nestedFoldersEnabled",
|
||||
uids: []string{"abc-123"},
|
||||
expectedSql: "dashboard.org_id = ? AND dashboard.folder_uid = ?",
|
||||
expectedParams: []any{int64(1), "abc-123"},
|
||||
nestedFoldersEnabled: true,
|
||||
},
|
||||
{
|
||||
description: "searching a specific folders with nestedFoldersEnabled",
|
||||
uids: []string{"abc-123", "def-456"},
|
||||
expectedSql: "dashboard.org_id = ? AND dashboard.folder_uid IN (?,?)",
|
||||
expectedParams: []any{int64(1), "abc-123", "def-456"},
|
||||
nestedFoldersEnabled: true,
|
||||
},
|
||||
{
|
||||
description: "searching a specific folders or general with nestedFoldersEnabled",
|
||||
uids: []string{"general", "abc-123", "def-456"},
|
||||
expectedSql: "(dashboard.org_id = ? AND dashboard.folder_uid IN (?,?) OR dashboard.folder_uid IS NULL)",
|
||||
expectedParams: []any{int64(1), "abc-123", "def-456"},
|
||||
nestedFoldersEnabled: true,
|
||||
description: "searching a specific folders or general",
|
||||
uids: []string{"general", "abc-123", "def-456"},
|
||||
expectedSql: "(dashboard.org_id = ? AND dashboard.folder_uid IN (?,?) OR dashboard.folder_uid IS NULL)",
|
||||
expectedParams: []any{int64(1), "abc-123", "def-456"},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -81,10 +48,9 @@ func TestIntegrationFolderUIDFilter(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
f := searchstore.FolderUIDFilter{
|
||||
Dialect: store.GetDialect(),
|
||||
OrgID: 1,
|
||||
UIDs: tc.uids,
|
||||
NestedFoldersEnabled: tc.nestedFoldersEnabled,
|
||||
Dialect: store.GetDialect(),
|
||||
OrgID: 1,
|
||||
UIDs: tc.uids,
|
||||
}
|
||||
|
||||
sql, params := f.Where()
|
||||
|
||||
@@ -146,48 +146,6 @@ func TestIntegrationBuilder_RBAC(t *testing.T) {
|
||||
int64(1),
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "user with view permission",
|
||||
userPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"},
|
||||
},
|
||||
level: dashboardaccess.PERMISSION_VIEW,
|
||||
features: featuremgmt.WithFeatures(),
|
||||
expectedParams: []any{
|
||||
int64(1),
|
||||
int64(1),
|
||||
int64(1),
|
||||
0,
|
||||
"Viewer",
|
||||
int64(1),
|
||||
0,
|
||||
"dashboards:read",
|
||||
"dashboards:view",
|
||||
"dashboards:edit",
|
||||
"dashboards:admin",
|
||||
int64(1),
|
||||
int64(1),
|
||||
int64(1),
|
||||
0,
|
||||
"Viewer",
|
||||
int64(1),
|
||||
0,
|
||||
"dashboards:read",
|
||||
"folders:view",
|
||||
"folders:edit",
|
||||
"folders:admin",
|
||||
int64(1),
|
||||
int64(1),
|
||||
0,
|
||||
"Viewer",
|
||||
int64(1),
|
||||
0,
|
||||
"folders:read",
|
||||
"folders:view",
|
||||
"folders:edit",
|
||||
"folders:admin",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "user with write permission",
|
||||
userPermissions: []accesscontrol.Permission{
|
||||
@@ -196,16 +154,6 @@ func TestIntegrationBuilder_RBAC(t *testing.T) {
|
||||
level: dashboardaccess.PERMISSION_EDIT,
|
||||
features: featuremgmt.WithFeatures(),
|
||||
expectedParams: []any{
|
||||
int64(1),
|
||||
int64(1),
|
||||
int64(1),
|
||||
0,
|
||||
"Viewer",
|
||||
int64(1),
|
||||
0,
|
||||
"dashboards:write",
|
||||
"dashboards:edit",
|
||||
"dashboards:admin",
|
||||
int64(1),
|
||||
int64(1),
|
||||
int64(1),
|
||||
@@ -218,6 +166,7 @@ func TestIntegrationBuilder_RBAC(t *testing.T) {
|
||||
"folders:admin",
|
||||
int64(1),
|
||||
int64(1),
|
||||
int64(1),
|
||||
0,
|
||||
"Viewer",
|
||||
int64(1),
|
||||
@@ -225,15 +174,26 @@ func TestIntegrationBuilder_RBAC(t *testing.T) {
|
||||
"dashboards:create",
|
||||
"folders:edit",
|
||||
"folders:admin",
|
||||
int64(1),
|
||||
int64(1),
|
||||
int64(1),
|
||||
0,
|
||||
"Viewer",
|
||||
int64(1),
|
||||
0,
|
||||
"dashboards:write",
|
||||
"dashboards:edit",
|
||||
"dashboards:admin",
|
||||
int64(1),
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "user with view permission with nesting",
|
||||
desc: "user with view permission",
|
||||
userPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"},
|
||||
},
|
||||
level: dashboardaccess.PERMISSION_VIEW,
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders),
|
||||
features: featuremgmt.WithFeatures(),
|
||||
expectedParams: []any{
|
||||
int64(1),
|
||||
int64(1),
|
||||
@@ -272,53 +232,12 @@ func TestIntegrationBuilder_RBAC(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "user with view permission with remove subquery",
|
||||
userPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsRead, Scope: "dashboards:uid:1"},
|
||||
},
|
||||
level: dashboardaccess.PERMISSION_VIEW,
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||
expectedParams: []any{
|
||||
int64(1),
|
||||
int64(1),
|
||||
int64(1),
|
||||
0,
|
||||
"Viewer",
|
||||
int64(1),
|
||||
0,
|
||||
"dashboards:read",
|
||||
"dashboards:view",
|
||||
"dashboards:edit",
|
||||
"dashboards:admin",
|
||||
int64(1),
|
||||
int64(1),
|
||||
0,
|
||||
"Viewer",
|
||||
int64(1),
|
||||
0,
|
||||
"dashboards:read",
|
||||
"folders:view",
|
||||
"folders:edit",
|
||||
"folders:admin",
|
||||
int64(1),
|
||||
int64(1),
|
||||
0,
|
||||
"Viewer",
|
||||
int64(1),
|
||||
0,
|
||||
"folders:read",
|
||||
"folders:view",
|
||||
"folders:edit",
|
||||
"folders:admin",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "user with edit permission with nesting and remove subquery",
|
||||
desc: "user with edit permission remove subquery",
|
||||
userPermissions: []accesscontrol.Permission{
|
||||
{Action: dashboards.ActionDashboardsWrite, Scope: "dashboards:uid:1"},
|
||||
},
|
||||
level: dashboardaccess.PERMISSION_EDIT,
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders, featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||
features: featuremgmt.WithFeatures(featuremgmt.FlagPermissionsFilterRemoveSubquery),
|
||||
expectedParams: []any{
|
||||
int64(1),
|
||||
int64(1),
|
||||
|
||||
Reference in New Issue
Block a user