From b0a08807b80e082dc859fec05b6518416ffe86fe Mon Sep 17 00:00:00 2001 From: maicon Date: Thu, 30 Oct 2025 14:26:30 -0300 Subject: [PATCH] [release-11.6.8] Annotations: Honor dashboardUID on dashboardsWithVisibleAnnotations (#113235) Annotations: Honor dashboardUID on dashboardsWithVisibleAnnotations (#112350) * Annotations: Honor dashboardUID on dashboardsWithVisibleAnnotations --------- (cherry picked from commit 75a1846344ec598d38ad7421ff636c69d1162df6) Signed-off-by: Maicon Costa --- .../accesscontrol/accesscontrol.go | 15 +-- .../accesscontrol/accesscontrol_test.go | 93 +++++++++++++++++++ 2 files changed, 102 insertions(+), 6 deletions(-) diff --git a/pkg/services/annotations/accesscontrol/accesscontrol.go b/pkg/services/annotations/accesscontrol/accesscontrol.go index 19eeca27b63..5d0963364d0 100644 --- a/pkg/services/annotations/accesscontrol/accesscontrol.go +++ b/pkg/services/annotations/accesscontrol/accesscontrol.go @@ -131,7 +131,9 @@ func (authz *AuthService) dashboardsWithVisibleAnnotations(ctx context.Context, searchstore.OrgFilter{OrgId: query.OrgID}, } + var dashboardUIDs []string if query.DashboardUID != "" { + dashboardUIDs = append(dashboardUIDs, query.DashboardUID) filters = append(filters, searchstore.DashboardFilter{ UIDs: []string{query.DashboardUID}, }) @@ -143,12 +145,13 @@ func (authz *AuthService) dashboardsWithVisibleAnnotations(ctx context.Context, } dashs, err := authz.dashSvc.SearchDashboards(ctx, &dashboards.FindPersistedDashboardsQuery{ - OrgId: query.SignedInUser.GetOrgID(), - Filters: filters, - SignedInUser: query.SignedInUser, - Page: query.Page, - Type: filterType, - Limit: authz.searchDashboardsPageLimit, + DashboardUIDs: dashboardUIDs, + OrgId: query.SignedInUser.GetOrgID(), + Filters: filters, + SignedInUser: query.SignedInUser, + Page: query.Page, + Type: filterType, + Limit: authz.searchDashboardsPageLimit, }) if err != nil { return nil, err diff --git a/pkg/services/annotations/accesscontrol/accesscontrol_test.go b/pkg/services/annotations/accesscontrol/accesscontrol_test.go index d3a4caec1ba..3b7f59d0f91 100644 --- a/pkg/services/annotations/accesscontrol/accesscontrol_test.go +++ b/pkg/services/annotations/accesscontrol/accesscontrol_test.go @@ -18,18 +18,24 @@ import ( "github.com/grafana/grafana/pkg/services/annotations/testutil" "github.com/grafana/grafana/pkg/services/apiserver/client" "github.com/grafana/grafana/pkg/services/dashboards" + "github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess" "github.com/grafana/grafana/pkg/services/dashboards/database" dashboardsservice "github.com/grafana/grafana/pkg/services/dashboards/service" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/folder/folderimpl" "github.com/grafana/grafana/pkg/services/guardian" "github.com/grafana/grafana/pkg/services/quota/quotatest" + "github.com/grafana/grafana/pkg/services/search/model" "github.com/grafana/grafana/pkg/services/search/sort" + "github.com/grafana/grafana/pkg/services/sqlstore/permissions" + "github.com/grafana/grafana/pkg/services/sqlstore/searchstore" "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/storage/legacysql/dualwrite" "github.com/grafana/grafana/pkg/tests/testsuite" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" ) func TestMain(m *testing.M) { @@ -225,3 +231,90 @@ func TestIntegrationAuthorize(t *testing.T) { }) } } + +func TestDashboardsWithVisibleAnnotations(t *testing.T) { + store := db.InitTestDB(t) + + user := &user.SignedInUser{ + OrgID: 1, + } + + // Create permission filters + p1 := permissions.NewAccessControlDashboardPermissionFilter(user, dashboardaccess.PERMISSION_VIEW, searchstore.TypeDashboard, featuremgmt.WithFeatures(), true, store.GetDialect()) + p2 := searchstore.OrgFilter{OrgId: 1} + + // If DashboardUID is provided, it should be added as a filter + p3 := searchstore.DashboardFilter{UIDs: []string{"uid1"}} + + dashSvc := &dashboards.FakeDashboardService{} + + // First call, without DashboardUID + queryNoDashboardUID := &dashboards.FindPersistedDashboardsQuery{ + OrgId: 1, + SignedInUser: user, + Type: "dash-db", + Limit: int64(100), + Page: int64(1), + Filters: []any{ + p1, + p2, + }, + } + dashSvc.On("SearchDashboards", mock.Anything, queryNoDashboardUID).Return(model.HitList{ + &model.Hit{UID: "uid1", ID: 101}, + &model.Hit{UID: "uid2", ID: 102}, + }, nil) + + // Second call, with DashboardUID filter + queryWithDashboardUID := &dashboards.FindPersistedDashboardsQuery{ + OrgId: 1, + SignedInUser: user, + Type: "dash-db", + Limit: int64(100), + Page: int64(1), + Filters: []any{ + p1, + p2, + // This filter should be added on second call + p3, + }, + DashboardUIDs: []string{"uid1"}, + } + + dashSvc.On("SearchDashboards", mock.Anything, queryWithDashboardUID).Return(model.HitList{ + &model.Hit{UID: "uid1", ID: 101}, + }, nil) + + // Create auth service + authz := &AuthService{ + db: store, + features: featuremgmt.WithFeatures(), + dashSvc: dashSvc, + searchDashboardsPageLimit: 100, + } + + // First call without DashboardUID + result, err := authz.dashboardsWithVisibleAnnotations(context.Background(), annotations.ItemQuery{ + SignedInUser: user, + OrgID: 1, + Page: 1, + }) + assert.NoError(t, err) + // Should return two dashboards + assert.Equal(t, map[string]int64{"uid1": 101, "uid2": 102}, result) + // Ensure SearchDashboards was called with correct query + dashSvc.AssertCalled(t, "SearchDashboards", mock.Anything, queryNoDashboardUID) + + // Second call with DashboardUID + result, err = authz.dashboardsWithVisibleAnnotations(context.Background(), annotations.ItemQuery{ + SignedInUser: user, + OrgID: 1, + Page: 1, + DashboardUID: "uid1", + }) + assert.NoError(t, err) + // Should only return one dashboard + assert.Equal(t, map[string]int64{"uid1": 101}, result) + // Ensure SearchDashboards was called with correct query (including DashboardUID filter) + dashSvc.AssertCalled(t, "SearchDashboards", mock.Anything, queryWithDashboardUID) +}