Dashboards: Move to integration tests (#108734)

This commit is contained in:
Stephanie Hingtgen
2025-07-29 02:52:27 -05:00
committed by GitHub
parent 4392cea75a
commit fe906dfc1e
4 changed files with 545 additions and 1389 deletions
@@ -2,36 +2,20 @@ package database
import (
"context"
"errors"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"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/apiserver"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/folder/folderimpl"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/org/orgimpl"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/search/sort"
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/services/user/userimpl"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/storage/legacysql/dualwrite"
)
var testFeatureToggles = featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch)
@@ -230,197 +214,6 @@ func TestIntegrationDashboardFolderDataAccess(t *testing.T) {
})
}
func TestIntegrationDashboardInheritedFolderRBAC(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
// the maximux nested folder hierarchy starting from parent down to subfolders
nestedFolders := make([]*folder.Folder, 0, folder.MaxNestedFolderDepth+1)
var sqlStore db.DB
var cfg *setting.Cfg
const (
dashInRootTitle = "dashboard in root"
dashInParentTitle = "dashboard in parent"
dashInSubfolderTitle = "dashboard in subfolder"
)
var viewer *user.SignedInUser
setup := func() {
sqlStore, cfg = db.InitTestDBWithCfg(t)
cfg.AutoAssignOrg = true
cfg.AutoAssignOrgId = 1
cfg.AutoAssignOrgRole = string(org.RoleViewer)
tracer := tracing.InitializeTracerForTest()
quotaService := quotatest.New(false, nil)
// enable nested folders so that the folder table is populated for all the tests
features := featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)
var err error
dashboardWriteStore, err := ProvideDashboardStore(sqlStore, cfg, features, tagimpl.ProvideService(sqlStore))
require.NoError(t, err)
orgService, err := orgimpl.ProvideService(sqlStore, cfg, quotaService)
require.NoError(t, err)
usrSvc, err := userimpl.ProvideService(
sqlStore, orgService, cfg, nil, nil, tracer,
quotaService, supportbundlestest.NewFakeBundleService(),
)
require.NoError(t, err)
usr := createUser(t, usrSvc, orgService, "viewer", false)
viewer = &user.SignedInUser{
UserID: usr.ID,
OrgID: usr.OrgID,
OrgRole: org.RoleViewer,
}
// create admin user in the same org
currentUserCmd := user.CreateUserCommand{Login: "admin", Email: "admin@test.com", Name: "an admin", IsAdmin: false, OrgID: viewer.OrgID}
u, err := usrSvc.Create(context.Background(), &currentUserCmd)
require.NoError(t, err)
admin := user.SignedInUser{
UserID: u.ID,
OrgID: u.OrgID,
OrgRole: org.RoleAdmin,
Permissions: map[int64]map[string][]string{u.OrgID: accesscontrol.GroupScopesByActionContext(context.Background(), []accesscontrol.Permission{
{
Action: dashboards.ActionFoldersCreate,
Scope: dashboards.ScopeFoldersAll,
}}),
},
}
require.NotEqual(t, viewer.UserID, admin.UserID)
folderStore := folderimpl.ProvideStore(sqlStore)
folderSvc := folderimpl.ProvideService(
folderStore, mock.New(), bus.ProvideBus(tracer), dashboardWriteStore, folderimpl.ProvideDashboardFolderStore(sqlStore),
nil, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest(), nil, dualwrite.ProvideTestService(), sort.ProvideService(), apiserver.WithoutRestConfig)
parentUID := ""
for i := 0; ; i++ {
uid := fmt.Sprintf("f%d", i)
f, err := folderSvc.Create(context.Background(), &folder.CreateFolderCommand{
UID: uid,
OrgID: admin.OrgID,
Title: uid,
SignedInUser: &admin,
ParentUID: parentUID,
})
if err != nil {
if errors.Is(err, folder.ErrMaximumDepthReached) {
break
}
t.Log("unexpected error", "error", err)
t.Fail()
}
nestedFolders = append(nestedFolders, f)
parentUID = f.UID
}
require.LessOrEqual(t, 2, len(nestedFolders))
saveDashboardCmd := dashboards.SaveDashboardCommand{
UserID: admin.UserID,
OrgID: admin.OrgID,
IsFolder: false,
Dashboard: simplejson.NewFromAny(map[string]any{
"title": dashInRootTitle,
}),
}
_, err = dashboardWriteStore.SaveDashboard(context.Background(), saveDashboardCmd)
require.NoError(t, err)
saveDashboardCmd = dashboards.SaveDashboardCommand{
UserID: admin.UserID,
OrgID: admin.OrgID,
IsFolder: false,
Dashboard: simplejson.NewFromAny(map[string]any{
"title": dashInParentTitle,
}),
FolderUID: nestedFolders[0].UID,
}
_, err = dashboardWriteStore.SaveDashboard(context.Background(), saveDashboardCmd)
require.NoError(t, err)
saveDashboardCmd = dashboards.SaveDashboardCommand{
UserID: admin.UserID,
OrgID: admin.OrgID,
IsFolder: false,
Dashboard: simplejson.NewFromAny(map[string]any{
"title": dashInSubfolderTitle,
}),
FolderUID: nestedFolders[1].UID,
}
_, err = dashboardWriteStore.SaveDashboard(context.Background(), saveDashboardCmd)
require.NoError(t, err)
}
setup()
nestedFolderTitles := make([]string, 0, len(nestedFolders))
for _, f := range nestedFolders {
nestedFolderTitles = append(nestedFolderTitles, f.Title)
}
testCases := []struct {
desc string
features featuremgmt.FeatureToggles
permissions map[string][]string
expectedTitles []string
}{
{
desc: "it should not return folder if ACL is not set for parent folder",
features: featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch),
permissions: nil,
expectedTitles: nil,
},
{
desc: "it should not return subfolder if nested folders are disabled and the user has permission to read folders under parent folder",
features: featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch),
permissions: map[string][]string{
dashboards.ActionFoldersRead: {fmt.Sprintf("folders:uid:%s", nestedFolders[0].UID)},
},
expectedTitles: []string{nestedFolders[0].Title},
},
{
desc: "it should return subfolder if nested folders are enabled and the user has permission to read folders under parent folder",
features: featuremgmt.WithFeatures(featuremgmt.FlagPanelTitleSearch, featuremgmt.FlagNestedFolders),
permissions: map[string][]string{
dashboards.ActionFoldersRead: {fmt.Sprintf("folders:uid:%s", nestedFolders[0].UID)},
},
expectedTitles: nestedFolderTitles,
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
dashboardReadStore, err := ProvideDashboardStore(sqlStore, cfg, tc.features, tagimpl.ProvideService(sqlStore))
require.NoError(t, err)
viewer.Permissions = map[int64]map[string][]string{viewer.OrgID: tc.permissions}
actest.AddUserPermissionToDB(t, sqlStore, viewer)
query := &dashboards.FindPersistedDashboardsQuery{
SignedInUser: viewer,
OrgId: viewer.OrgID,
}
res, err := testSearchDashboards(dashboardReadStore, query)
require.NoError(t, err)
require.Equal(t, len(tc.expectedTitles), len(res))
for i, tlt := range tc.expectedTitles {
assert.Equal(t, tlt, res[i].Title)
}
})
}
}
func moveDashboard(t *testing.T, dashboardStore dashboards.Store, orgId int64, dashboard *simplejson.Json,
newFolderId int64, newFolderUID string) *dashboards.Dashboard {
t.Helper()
@@ -437,15 +230,3 @@ func moveDashboard(t *testing.T, dashboardStore dashboards.Store, orgId int64, d
return dash
}
func createUser(t *testing.T, userSrv user.Service, orgSrv org.Service, name string, isAdmin bool) user.User {
t.Helper()
o, err := orgSrv.CreateWithMember(context.Background(), &org.CreateOrgCommand{Name: fmt.Sprintf("test org %d", time.Now().UnixNano())})
require.NoError(t, err)
currentUserCmd := user.CreateUserCommand{Login: name, Email: name + "@test.com", Name: "a " + name, IsAdmin: isAdmin, OrgID: o.ID}
currentUser, err := userSrv.Create(context.Background(), &currentUserCmd)
require.NoError(t, err)
return *currentUser
}