mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Public dashboards: fix public dashboard permissions so that annotations are displayed (#85091)
* fix public dashboard anonymous user permissions so they include the new annotation permissions * test fix
This commit is contained in:
parent
fb01ef749f
commit
df40e13333
@ -334,7 +334,7 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T)
|
|||||||
|
|
||||||
license := licensingtest.NewFakeLicensing()
|
license := licensingtest.NewFakeLicensing()
|
||||||
license.On("FeatureEnabled", FeaturePublicDashboardsEmailSharing).Return(false)
|
license.On("FeatureEnabled", FeaturePublicDashboardsEmailSharing).Return(false)
|
||||||
pds := publicdashboardsService.ProvideService(cfg, store, qds, annotationsService, ac, ws, dashService, license)
|
pds := publicdashboardsService.ProvideService(cfg, featuremgmt.WithFeatures(), store, qds, annotationsService, ac, ws, dashService, license)
|
||||||
pubdash, err := pds.Create(context.Background(), &user.SignedInUser{}, savePubDashboardCmd)
|
pubdash, err := pds.Create(context.Background(), &user.SignedInUser{}, savePubDashboardCmd)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -47,5 +47,6 @@ func newPublicDashboardServiceImpl(
|
|||||||
store: publicDashboardStore,
|
store: publicDashboardStore,
|
||||||
serviceWrapper: serviceWrapper,
|
serviceWrapper: serviceWrapper,
|
||||||
license: license,
|
license: license,
|
||||||
|
features: featuremgmt.WithFeatures(),
|
||||||
}, sqlStore
|
}, sqlStore
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/annotations"
|
"github.com/grafana/grafana/pkg/services/annotations"
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
"github.com/grafana/grafana/pkg/services/datasources"
|
"github.com/grafana/grafana/pkg/services/datasources"
|
||||||
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
"github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||||
"github.com/grafana/grafana/pkg/services/publicdashboards/validation"
|
"github.com/grafana/grafana/pkg/services/publicdashboards/validation"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
@ -36,7 +37,7 @@ func (pd *PublicDashboardServiceImpl) FindAnnotations(ctx context.Context, reqDT
|
|||||||
return nil, models.ErrInternalServerError.Errorf("FindAnnotations: failed to unmarshal dashboard annotations: %w", err)
|
return nil, models.ErrInternalServerError.Errorf("FindAnnotations: failed to unmarshal dashboard annotations: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
anonymousUser := buildAnonymousUser(ctx, dash)
|
anonymousUser := buildAnonymousUser(ctx, dash, pd.features)
|
||||||
|
|
||||||
uniqueEvents := make(map[int64]models.AnnotationEvent, 0)
|
uniqueEvents := make(map[int64]models.AnnotationEvent, 0)
|
||||||
for _, anno := range annoDto.Annotations.List {
|
for _, anno := range annoDto.Annotations.List {
|
||||||
@ -138,7 +139,7 @@ func (pd *PublicDashboardServiceImpl) GetQueryDataResponse(ctx context.Context,
|
|||||||
return nil, models.ErrPanelQueriesNotFound.Errorf("GetQueryDataResponse: failed to extract queries from panel")
|
return nil, models.ErrPanelQueriesNotFound.Errorf("GetQueryDataResponse: failed to extract queries from panel")
|
||||||
}
|
}
|
||||||
|
|
||||||
anonymousUser := buildAnonymousUser(ctx, dashboard)
|
anonymousUser := buildAnonymousUser(ctx, dashboard, pd.features)
|
||||||
res, err := pd.QueryDataService.QueryData(ctx, anonymousUser, skipDSCache, metricReq)
|
res, err := pd.QueryDataService.QueryData(ctx, anonymousUser, skipDSCache, metricReq)
|
||||||
|
|
||||||
reqDatasources := metricReq.GetUniqueDatasourceTypes()
|
reqDatasources := metricReq.GetUniqueDatasourceTypes()
|
||||||
@ -180,7 +181,7 @@ func (pd *PublicDashboardServiceImpl) buildMetricRequest(dashboard *dashboards.D
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buildAnonymousUser creates a user with permissions to read from all datasources used in the dashboard
|
// buildAnonymousUser creates a user with permissions to read from all datasources used in the dashboard
|
||||||
func buildAnonymousUser(ctx context.Context, dashboard *dashboards.Dashboard) *user.SignedInUser {
|
func buildAnonymousUser(ctx context.Context, dashboard *dashboards.Dashboard, features featuremgmt.FeatureToggles) *user.SignedInUser {
|
||||||
datasourceUids := getUniqueDashboardDatasourceUids(dashboard.Data)
|
datasourceUids := getUniqueDashboardDatasourceUids(dashboard.Data)
|
||||||
|
|
||||||
// Create a user with blank permissions
|
// Create a user with blank permissions
|
||||||
@ -204,8 +205,12 @@ func buildAnonymousUser(ctx context.Context, dashboard *dashboards.Dashboard) *u
|
|||||||
permissions := make(map[string][]string)
|
permissions := make(map[string][]string)
|
||||||
permissions[datasources.ActionQuery] = queryScopes
|
permissions[datasources.ActionQuery] = queryScopes
|
||||||
permissions[datasources.ActionRead] = readScopes
|
permissions[datasources.ActionRead] = readScopes
|
||||||
permissions[accesscontrol.ActionAnnotationsRead] = annotationScopes
|
|
||||||
permissions[dashboards.ActionDashboardsRead] = dashboardScopes
|
permissions[dashboards.ActionDashboardsRead] = dashboardScopes
|
||||||
|
permissions[accesscontrol.ActionAnnotationsRead] = annotationScopes
|
||||||
|
|
||||||
|
if features.IsEnabled(ctx, featuremgmt.FlagAnnotationPermissionUpdate) {
|
||||||
|
permissions[accesscontrol.ActionAnnotationsRead] = dashboardScopes
|
||||||
|
}
|
||||||
|
|
||||||
anonymousUser.Permissions[dashboard.OrgID] = permissions
|
anonymousUser.Permissions[dashboard.OrgID] = permissions
|
||||||
|
|
||||||
|
@ -732,6 +732,7 @@ func TestGetQueryDataResponse(t *testing.T) {
|
|||||||
func TestFindAnnotations(t *testing.T) {
|
func TestFindAnnotations(t *testing.T) {
|
||||||
color := "red"
|
color := "red"
|
||||||
name := "annoName"
|
name := "annoName"
|
||||||
|
features := featuremgmt.WithFeatures(featuremgmt.FlagAnnotationPermissionUpdate)
|
||||||
t.Run("will build anonymous user with correct permissions to get annotations", func(t *testing.T) {
|
t.Run("will build anonymous user with correct permissions to get annotations", func(t *testing.T) {
|
||||||
fakeStore := &FakePublicDashboardStore{}
|
fakeStore := &FakePublicDashboardStore{}
|
||||||
fakeStore.On("FindByAccessToken", mock.Anything, mock.AnythingOfType("string")).
|
fakeStore.On("FindByAccessToken", mock.Anything, mock.AnythingOfType("string")).
|
||||||
@ -747,7 +748,7 @@ func TestFindAnnotations(t *testing.T) {
|
|||||||
dash := dashboards.NewDashboard("testDashboard")
|
dash := dashboards.NewDashboard("testDashboard")
|
||||||
|
|
||||||
items, _ := service.FindAnnotations(context.Background(), reqDTO, "abc123")
|
items, _ := service.FindAnnotations(context.Background(), reqDTO, "abc123")
|
||||||
anonUser := buildAnonymousUser(context.Background(), dash)
|
anonUser := buildAnonymousUser(context.Background(), dash, features)
|
||||||
|
|
||||||
assert.Equal(t, "dashboards:*", anonUser.Permissions[0]["dashboards:read"][0])
|
assert.Equal(t, "dashboards:*", anonUser.Permissions[0]["dashboards:read"][0])
|
||||||
assert.Len(t, items, 0)
|
assert.Len(t, items, 0)
|
||||||
@ -1323,9 +1324,10 @@ func TestBuildAnonymousUser(t *testing.T) {
|
|||||||
dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil))
|
dashboardStore, err := dashboardsDB.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore), quotatest.New(false, nil))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]interface{}{}, nil)
|
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, "", true, []map[string]interface{}{}, nil)
|
||||||
|
features := featuremgmt.WithFeatures()
|
||||||
|
|
||||||
t.Run("will add datasource read and query permissions to user for each datasource in dashboard", func(t *testing.T) {
|
t.Run("will add datasource read and query permissions to user for each datasource in dashboard", func(t *testing.T) {
|
||||||
user := buildAnonymousUser(context.Background(), dashboard)
|
user := buildAnonymousUser(context.Background(), dashboard, features)
|
||||||
|
|
||||||
require.Equal(t, dashboard.OrgID, user.OrgID)
|
require.Equal(t, dashboard.OrgID, user.OrgID)
|
||||||
require.Equal(t, "datasources:uid:ds1", user.Permissions[user.OrgID]["datasources:query"][0])
|
require.Equal(t, "datasources:uid:ds1", user.Permissions[user.OrgID]["datasources:query"][0])
|
||||||
@ -1334,12 +1336,20 @@ func TestBuildAnonymousUser(t *testing.T) {
|
|||||||
require.Equal(t, "datasources:uid:ds3", user.Permissions[user.OrgID]["datasources:read"][1])
|
require.Equal(t, "datasources:uid:ds3", user.Permissions[user.OrgID]["datasources:read"][1])
|
||||||
})
|
})
|
||||||
t.Run("will add dashboard and annotation permissions needed for getting annotations", func(t *testing.T) {
|
t.Run("will add dashboard and annotation permissions needed for getting annotations", func(t *testing.T) {
|
||||||
user := buildAnonymousUser(context.Background(), dashboard)
|
user := buildAnonymousUser(context.Background(), dashboard, features)
|
||||||
|
|
||||||
require.Equal(t, dashboard.OrgID, user.OrgID)
|
require.Equal(t, dashboard.OrgID, user.OrgID)
|
||||||
require.Equal(t, "annotations:type:dashboard", user.Permissions[user.OrgID]["annotations:read"][0])
|
require.Equal(t, "annotations:type:dashboard", user.Permissions[user.OrgID]["annotations:read"][0])
|
||||||
require.Equal(t, "dashboards:*", user.Permissions[user.OrgID]["dashboards:read"][0])
|
require.Equal(t, "dashboards:*", user.Permissions[user.OrgID]["dashboards:read"][0])
|
||||||
})
|
})
|
||||||
|
t.Run("will add dashboard and annotation permissions needed for getting annotations when FlagAnnotationPermissionUpdate is enabled", func(t *testing.T) {
|
||||||
|
features = featuremgmt.WithFeatures(featuremgmt.FlagAnnotationPermissionUpdate)
|
||||||
|
user := buildAnonymousUser(context.Background(), dashboard, features)
|
||||||
|
|
||||||
|
require.Equal(t, dashboard.OrgID, user.OrgID)
|
||||||
|
require.Equal(t, "dashboards:*", user.Permissions[user.OrgID]["annotations:read"][0])
|
||||||
|
require.Equal(t, "dashboards:*", user.Permissions[user.OrgID]["dashboards:read"][0])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGroupQueriesByPanelId(t *testing.T) {
|
func TestGroupQueriesByPanelId(t *testing.T) {
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/annotations"
|
"github.com/grafana/grafana/pkg/services/annotations"
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/services/licensing"
|
"github.com/grafana/grafana/pkg/services/licensing"
|
||||||
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
"github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||||
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||||
@ -32,6 +33,7 @@ import (
|
|||||||
type PublicDashboardServiceImpl struct {
|
type PublicDashboardServiceImpl struct {
|
||||||
log log.Logger
|
log log.Logger
|
||||||
cfg *setting.Cfg
|
cfg *setting.Cfg
|
||||||
|
features featuremgmt.FeatureToggles
|
||||||
store publicdashboards.Store
|
store publicdashboards.Store
|
||||||
intervalCalculator intervalv2.Calculator
|
intervalCalculator intervalv2.Calculator
|
||||||
QueryDataService query.Service
|
QueryDataService query.Service
|
||||||
@ -52,6 +54,7 @@ var _ publicdashboards.Service = (*PublicDashboardServiceImpl)(nil)
|
|||||||
// builds the service, and api, and configures routes
|
// builds the service, and api, and configures routes
|
||||||
func ProvideService(
|
func ProvideService(
|
||||||
cfg *setting.Cfg,
|
cfg *setting.Cfg,
|
||||||
|
features featuremgmt.FeatureToggles,
|
||||||
store publicdashboards.Store,
|
store publicdashboards.Store,
|
||||||
qds query.Service,
|
qds query.Service,
|
||||||
anno annotations.Repository,
|
anno annotations.Repository,
|
||||||
@ -63,6 +66,7 @@ func ProvideService(
|
|||||||
return &PublicDashboardServiceImpl{
|
return &PublicDashboardServiceImpl{
|
||||||
log: log.New(LogPrefix),
|
log: log.New(LogPrefix),
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
|
features: features,
|
||||||
store: store,
|
store: store,
|
||||||
intervalCalculator: intervalv2.NewCalculator(),
|
intervalCalculator: intervalv2.NewCalculator(),
|
||||||
QueryDataService: qds,
|
QueryDataService: qds,
|
||||||
|
Loading…
Reference in New Issue
Block a user