Use dashboards service to query for dashboard uid when getting library elements (#99369)

This commit is contained in:
Leonor Oliveira 2025-01-27 14:42:57 +01:00 committed by GitHub
parent e94c9f733b
commit abe2a5370d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 39 additions and 30 deletions

View File

@ -501,7 +501,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOn, db, serviceWithFlagOn, dashSrv, ac, b) alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOn, db, serviceWithFlagOn, dashSrv, ac, b)
require.NoError(t, err) require.NoError(t, err)
elementService := libraryelements.ProvideService(cfg, db, routeRegister, serviceWithFlagOn, featuresFlagOn, ac) elementService := libraryelements.ProvideService(cfg, db, routeRegister, serviceWithFlagOn, featuresFlagOn, ac, dashSrv)
lps, err := librarypanels.ProvideService(cfg, db, routeRegister, elementService, serviceWithFlagOn) lps, err := librarypanels.ProvideService(cfg, db, routeRegister, elementService, serviceWithFlagOn)
require.NoError(t, err) require.NoError(t, err)
@ -586,7 +586,7 @@ func TestIntegrationNestedFolderService(t *testing.T) {
alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOff, db, serviceWithFlagOff, dashSrv, ac, b) alertStore, err := ngstore.ProvideDBStore(cfg, featuresFlagOff, db, serviceWithFlagOff, dashSrv, ac, b)
require.NoError(t, err) require.NoError(t, err)
elementService := libraryelements.ProvideService(cfg, db, routeRegister, serviceWithFlagOff, featuresFlagOff, ac) elementService := libraryelements.ProvideService(cfg, db, routeRegister, serviceWithFlagOff, featuresFlagOff, ac, dashSrv)
lps, err := librarypanels.ProvideService(cfg, db, routeRegister, elementService, serviceWithFlagOff) lps, err := librarypanels.ProvideService(cfg, db, routeRegister, elementService, serviceWithFlagOff)
require.NoError(t, err) require.NoError(t, err)
@ -716,10 +716,6 @@ func TestIntegrationNestedFolderService(t *testing.T) {
CanEditValue: true, CanEditValue: true,
}) })
elementService := libraryelements.ProvideService(cfg, db, routeRegister, tc.service, tc.featuresFlag, ac)
lps, err := librarypanels.ProvideService(cfg, db, routeRegister, elementService, tc.service)
require.NoError(t, err)
dashStore, err := database.ProvideDashboardStore(db, cfg, tc.featuresFlag, tagimpl.ProvideService(db)) dashStore, err := database.ProvideDashboardStore(db, cfg, tc.featuresFlag, tagimpl.ProvideService(db))
require.NoError(t, err) require.NoError(t, err)
nestedFolderStore := ProvideStore(db) nestedFolderStore := ProvideStore(db)
@ -731,6 +727,10 @@ func TestIntegrationNestedFolderService(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
dashSrv.RegisterDashboardPermissions(dashboardPermissions) dashSrv.RegisterDashboardPermissions(dashboardPermissions)
elementService := libraryelements.ProvideService(cfg, db, routeRegister, tc.service, tc.featuresFlag, ac, dashSrv)
lps, err := librarypanels.ProvideService(cfg, db, routeRegister, elementService, tc.service)
require.NoError(t, err)
alertStore, err := ngstore.ProvideDBStore(cfg, tc.featuresFlag, db, tc.service, dashSrv, ac, b) alertStore, err := ngstore.ProvideDBStore(cfg, tc.featuresFlag, db, tc.service, dashSrv, ac, b)
require.NoError(t, err) require.NoError(t, err)

View File

@ -695,14 +695,15 @@ func (l *LibraryElementService) getConnections(c context.Context, signedInUser i
} }
var libraryElementConnections []model.LibraryElementConnectionWithMeta var libraryElementConnections []model.LibraryElementConnectionWithMeta
builder := db.NewSqlBuilder(l.Cfg, l.features, l.SQLStore.GetDialect(), recursiveQueriesAreSupported) builder := db.NewSqlBuilder(l.Cfg, l.features, l.SQLStore.GetDialect(), recursiveQueriesAreSupported)
builder.Write("SELECT lec.*, u1.login AS created_by_name, u1.email AS created_by_email, dashboard.uid AS connection_uid") builder.Write("SELECT lec.*, u1.login AS created_by_name, u1.email AS created_by_email")
builder.Write(" FROM " + model.LibraryElementConnectionTableName + " AS lec") builder.Write(" FROM " + model.LibraryElementConnectionTableName + " AS lec")
builder.Write(" LEFT JOIN " + l.SQLStore.GetDialect().Quote("user") + " AS u1 ON lec.created_by = u1.id") builder.Write(" LEFT JOIN " + l.SQLStore.GetDialect().Quote("user") + " AS u1 ON lec.created_by = u1.id")
builder.Write(" INNER JOIN dashboard AS dashboard on lec.connection_id = dashboard.id")
builder.Write(` WHERE lec.element_id=?`, element.ID) builder.Write(` WHERE lec.element_id=?`, element.ID)
if err := session.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&libraryElementConnections); err != nil { if err := session.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&libraryElementConnections); err != nil {
return err return err
} }
// getting all folders a user can see
fs, err := l.folderService.GetFolders(c, folder.GetFoldersQuery{OrgID: signedInUser.GetOrgID(), SignedInUser: signedInUser}) fs, err := l.folderService.GetFolders(c, folder.GetFoldersQuery{OrgID: signedInUser.GetOrgID(), SignedInUser: signedInUser})
if err != nil { if err != nil {
return err return err
@ -712,19 +713,23 @@ func (l *LibraryElementService) getConnections(c context.Context, signedInUser i
for _, f := range fs { for _, f := range fs {
folderUIDS = append(folderUIDS, f.UID) folderUIDS = append(folderUIDS, f.UID)
} }
// if the user is not an admin, we need to filter out elements that are not in folders the user can see
for _, connection := range libraryElementConnections { for _, connection := range libraryElementConnections {
if !signedInUser.HasRole(org.RoleAdmin) { if !signedInUser.HasRole(org.RoleAdmin) {
if !contains(folderUIDS, element.FolderUID) { if !contains(folderUIDS, element.FolderUID) {
continue continue
} }
} }
ds, err := l.dashboardsService.GetDashboardUIDByID(c, &dashboards.GetDashboardRefByIDQuery{ID: connection.ConnectionID})
if err != nil {
return err
}
connections = append(connections, model.LibraryElementConnectionDTO{ connections = append(connections, model.LibraryElementConnectionDTO{
ID: connection.ID, ID: connection.ID,
Kind: connection.Kind, Kind: connection.Kind,
ElementID: connection.ElementID, ElementID: connection.ElementID,
ConnectionID: connection.ConnectionID, ConnectionID: connection.ConnectionID,
ConnectionUID: connection.ConnectionUID, ConnectionUID: ds.UID,
Created: connection.Created, Created: connection.Created,
CreatedBy: librarypanel.LibraryElementDTOMetaUser{ CreatedBy: librarypanel.LibraryElementDTOMetaUser{
Id: connection.CreatedBy, Id: connection.CreatedBy,

View File

@ -9,21 +9,23 @@ import (
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/libraryelements/model" "github.com/grafana/grafana/pkg/services/libraryelements/model"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
func ProvideService(cfg *setting.Cfg, sqlStore db.DB, routeRegister routing.RouteRegister, folderService folder.Service, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl) *LibraryElementService { func ProvideService(cfg *setting.Cfg, sqlStore db.DB, routeRegister routing.RouteRegister, folderService folder.Service, features featuremgmt.FeatureToggles, ac accesscontrol.AccessControl, dashboardsService dashboards.DashboardService) *LibraryElementService {
l := &LibraryElementService{ l := &LibraryElementService{
Cfg: cfg, Cfg: cfg,
SQLStore: sqlStore, SQLStore: sqlStore,
RouteRegister: routeRegister, RouteRegister: routeRegister,
folderService: folderService, folderService: folderService,
log: log.New("library-elements"), dashboardsService: dashboardsService,
features: features, log: log.New("library-elements"),
AccessControl: ac, features: features,
AccessControl: ac,
} }
l.registerAPIEndpoints() l.registerAPIEndpoints()
@ -45,13 +47,14 @@ type Service interface {
// LibraryElementService is the service for the Library Element feature. // LibraryElementService is the service for the Library Element feature.
type LibraryElementService struct { type LibraryElementService struct {
Cfg *setting.Cfg Cfg *setting.Cfg
SQLStore db.DB SQLStore db.DB
RouteRegister routing.RouteRegister RouteRegister routing.RouteRegister
folderService folder.Service folderService folder.Service
log log.Logger dashboardsService dashboards.DashboardService
features featuremgmt.FeatureToggles log log.Logger
AccessControl accesscontrol.AccessControl features featuremgmt.FeatureToggles
AccessControl accesscontrol.AccessControl
} }
var _ Service = (*LibraryElementService)(nil) var _ Service = (*LibraryElementService)(nil)

View File

@ -486,10 +486,11 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
dashService.RegisterDashboardPermissions(dashboardPermissions) dashService.RegisterDashboardPermissions(dashboardPermissions)
guardian.InitAccessControlGuardian(cfg, ac, dashService, folderSvc, log.NewNopLogger()) guardian.InitAccessControlGuardian(cfg, ac, dashService, folderSvc, log.NewNopLogger())
service := LibraryElementService{ service := LibraryElementService{
Cfg: cfg, Cfg: cfg,
features: featuremgmt.WithFeatures(), features: featuremgmt.WithFeatures(),
SQLStore: sqlStore, SQLStore: sqlStore,
folderService: folderSvc, folderService: folderSvc,
dashboardsService: dashService,
} }
// deliberate difference between signed in user and user in db to make it crystal clear // deliberate difference between signed in user and user in db to make it crystal clear

View File

@ -847,7 +847,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore, fStore, ac, bus.ProvideBus(tracing.InitializeTracerForTest()), dashboardStore, folderStore,
nil, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest()) nil, sqlStore, features, supportbundlestest.NewFakeBundleService(), nil, cfg, nil, tracing.InitializeTracerForTest())
elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService, features, ac) elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService, features, ac, dashService)
service := LibraryPanelService{ service := LibraryPanelService{
Cfg: cfg, Cfg: cfg,
SQLStore: sqlStore, SQLStore: sqlStore,