From 3ee26df41ec82e9fafdf98453b4047e5ecb0e61c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 25 Aug 2023 20:56:02 +0200 Subject: [PATCH] PublicDashboards: Variables refactor (#73476) Co-authored-by: Juan Cabanas Co-authored-by: Ezequiel Victorero Co-authored-by: Ryan McKinley --- packages/grafana-data/src/types/config.ts | 2 +- packages/grafana-data/src/types/datasource.ts | 1 - packages/grafana-runtime/src/config.ts | 3 +- pkg/api/api.go | 2 +- pkg/api/dtos/dashboard.go | 55 +++++++++---------- pkg/api/dtos/frontend_settings.go | 2 +- pkg/api/dtos/models.go | 2 - pkg/api/frontendsettings.go | 3 +- pkg/api/index.go | 2 - pkg/services/contexthandler/contexthandler.go | 26 ++++----- pkg/services/contexthandler/model/model.go | 8 ++- pkg/services/navtree/navtreeimpl/navtree.go | 2 +- pkg/services/ngalert/api/util_test.go | 22 ++++---- .../clientmiddleware/caching_metrics.go | 2 +- .../publicdashboards/api/middleware.go | 6 +- .../publicdashboards/api/middleware_test.go | 8 +-- pkg/services/publicdashboards/api/query.go | 28 +++++----- pkg/services/query/query_test.go | 36 ++++++------ .../app/angular/panel/metrics_panel_ctrl.ts | 1 - .../annotations/executeAnnotationQuery.ts | 1 - .../annotations/standardAnnotationSupport.ts | 2 +- .../dashgrid/PanelHeader/PanelHeader.test.tsx | 8 ++- .../dashgrid/PanelHeader/PanelHeader.tsx | 4 +- .../dashboard/dashgrid/PanelStateWrapper.tsx | 1 - .../PublicDashboardDataSource.test.ts | 43 ++------------- .../services/PublicDashboardDataSource.ts | 13 ++--- .../dashboard/services/TimeSrv.test.ts | 2 +- .../features/dashboard/services/TimeSrv.ts | 2 +- .../features/dashboard/state/PanelModel.ts | 9 +-- .../AnnotationsWorker.test.ts | 9 --- .../DashboardQueryRunner/AnnotationsWorker.ts | 11 ++-- .../UnifiedAlertStatesWorker.test.ts | 11 ++-- .../UnifiedAlertStatesWorker.ts | 4 +- .../state/DashboardQueryRunner/testHelpers.ts | 4 +- .../features/query/state/PanelQueryRunner.ts | 14 ++--- .../opentsdb/specs/datasource.test.ts | 1 - public/app/types/dashboard.ts | 1 - 37 files changed, 147 insertions(+), 204 deletions(-) diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index a0d75a32db8..04ebffbb4cf 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -147,7 +147,7 @@ export interface BootData { * @internal */ export interface GrafanaConfig { - isPublicDashboardView: boolean; + publicDashboardAccessToken?: string; snapshotEnabled: boolean; datasources: { [str: string]: DataSourceInstanceSettings }; panels: { [key: string]: PanelPluginMeta }; diff --git a/packages/grafana-data/src/types/datasource.ts b/packages/grafana-data/src/types/datasource.ts index 44d588650bb..2644c14e063 100644 --- a/packages/grafana-data/src/types/datasource.ts +++ b/packages/grafana-data/src/types/datasource.ts @@ -530,7 +530,6 @@ export interface DataQueryRequest { timeInfo?: string; // The query time description (blue text in the upper right) panelId?: number; dashboardUID?: string; - publicDashboardAccessToken?: string; // Request Timing startTime: number; diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 2762a6d5729..431d4ddc3be 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -33,7 +33,7 @@ export type AppPluginConfig = { }; export class GrafanaBootConfig implements GrafanaConfig { - isPublicDashboardView: boolean; + publicDashboardAccessToken?: string; snapshotEnabled = true; datasources: { [str: string]: DataSourceInstanceSettings } = {}; panels: { [key: string]: PanelPluginMeta } = {}; @@ -166,7 +166,6 @@ export class GrafanaBootConfig implements GrafanaConfig { constructor(options: GrafanaBootConfig) { this.bootData = options.bootData; - this.isPublicDashboardView = options.bootData.settings.isPublicDashboardView; const defaults = { datasources: {}, diff --git a/pkg/api/api.go b/pkg/api/api.go index 7359a643ac3..494e5c2ac42 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -165,7 +165,7 @@ func (hs *HTTPServer) registerRoutes() { // anonymous view public dashboard r.Get("/public-dashboards/:accessToken", - publicdashboardsapi.SetPublicDashboardFlag, + publicdashboardsapi.SetPublicDashboardAccessToken, publicdashboardsapi.SetPublicDashboardOrgIdOnContext(hs.PublicDashboardsApi.PublicDashboardService), publicdashboardsapi.CountPublicDashboardRequest(), hs.Index, diff --git a/pkg/api/dtos/dashboard.go b/pkg/api/dtos/dashboard.go index 3918374cf7f..8e920a20e12 100644 --- a/pkg/api/dtos/dashboard.go +++ b/pkg/api/dtos/dashboard.go @@ -7,34 +7,33 @@ import ( ) type DashboardMeta struct { - IsStarred bool `json:"isStarred,omitempty"` - IsSnapshot bool `json:"isSnapshot,omitempty"` - Type string `json:"type,omitempty"` - CanSave bool `json:"canSave"` - CanEdit bool `json:"canEdit"` - CanAdmin bool `json:"canAdmin"` - CanStar bool `json:"canStar"` - CanDelete bool `json:"canDelete"` - Slug string `json:"slug"` - Url string `json:"url"` - Expires time.Time `json:"expires"` - Created time.Time `json:"created"` - Updated time.Time `json:"updated"` - UpdatedBy string `json:"updatedBy"` - CreatedBy string `json:"createdBy"` - Version int `json:"version"` - HasACL bool `json:"hasAcl" xorm:"has_acl"` - IsFolder bool `json:"isFolder"` - FolderId int64 `json:"folderId"` - FolderUid string `json:"folderUid"` - FolderTitle string `json:"folderTitle"` - FolderUrl string `json:"folderUrl"` - Provisioned bool `json:"provisioned"` - ProvisionedExternalId string `json:"provisionedExternalId"` - AnnotationsPermissions *AnnotationPermission `json:"annotationsPermissions"` - PublicDashboardAccessToken string `json:"publicDashboardAccessToken"` - PublicDashboardUID string `json:"publicDashboardUid"` - PublicDashboardEnabled bool `json:"publicDashboardEnabled"` + IsStarred bool `json:"isStarred,omitempty"` + IsSnapshot bool `json:"isSnapshot,omitempty"` + Type string `json:"type,omitempty"` + CanSave bool `json:"canSave"` + CanEdit bool `json:"canEdit"` + CanAdmin bool `json:"canAdmin"` + CanStar bool `json:"canStar"` + CanDelete bool `json:"canDelete"` + Slug string `json:"slug"` + Url string `json:"url"` + Expires time.Time `json:"expires"` + Created time.Time `json:"created"` + Updated time.Time `json:"updated"` + UpdatedBy string `json:"updatedBy"` + CreatedBy string `json:"createdBy"` + Version int `json:"version"` + HasACL bool `json:"hasAcl" xorm:"has_acl"` + IsFolder bool `json:"isFolder"` + FolderId int64 `json:"folderId"` + FolderUid string `json:"folderUid"` + FolderTitle string `json:"folderTitle"` + FolderUrl string `json:"folderUrl"` + Provisioned bool `json:"provisioned"` + ProvisionedExternalId string `json:"provisionedExternalId"` + AnnotationsPermissions *AnnotationPermission `json:"annotationsPermissions"` + PublicDashboardUID string `json:"publicDashboardUid,omitempty"` + PublicDashboardEnabled bool `json:"publicDashboardEnabled,omitempty"` } type AnnotationPermission struct { Dashboard AnnotationActions `json:"dashboard"` diff --git a/pkg/api/dtos/frontend_settings.go b/pkg/api/dtos/frontend_settings.go index 61f21faef16..9cb747f55fd 100644 --- a/pkg/api/dtos/frontend_settings.go +++ b/pkg/api/dtos/frontend_settings.go @@ -217,7 +217,7 @@ type FrontendSettingsDTO struct { GeomapDefaultBaseLayerConfig *map[string]interface{} `json:"geomapDefaultBaseLayerConfig,omitempty"` GeomapDisableCustomBaseLayer bool `json:"geomapDisableCustomBaseLayer"` - IsPublicDashboardView bool `json:"isPublicDashboardView"` + PublicDashboardAccessToken string `json:"publicDashboardAccessToken"` DateFormats setting.DateFormats `json:"dateFormats,omitempty"` diff --git a/pkg/api/dtos/models.go b/pkg/api/dtos/models.go index b1154cfe401..95cd149b465 100644 --- a/pkg/api/dtos/models.go +++ b/pkg/api/dtos/models.go @@ -77,8 +77,6 @@ type MetricRequest struct { Queries []*simplejson.Json `json:"queries"` // required: false Debug bool `json:"debug"` - - PublicDashboardAccessToken string `json:"publicDashboardAccessToken"` } func (mr *MetricRequest) GetUniqueDatasourceTypes() []string { diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index f116a7c6b8f..32a498f8775 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -152,6 +152,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro DateFormats: hs.Cfg.DateFormats, SecureSocksDSProxyEnabled: hs.Cfg.SecureSocksDSProxy.Enabled && hs.Cfg.SecureSocksDSProxy.ShowUI, DisableFrontendSandboxForPlugins: hs.Cfg.DisableFrontendSandboxForPlugins, + PublicDashboardAccessToken: c.PublicDashboardAccessToken, Auth: dtos.FrontendSettingsAuthDTO{ OAuthSkipOrgRoleUpdateSync: hs.Cfg.OAuthSkipOrgRoleUpdateSync, @@ -282,7 +283,7 @@ func (hs *HTTPServer) getFSDataSources(c *contextmodel.ReqContext, availablePlug return nil, err } - if c.IsPublicDashboardView { + if c.IsPublicDashboardView() { // If RBAC is enabled, it will filter out all datasources for a public user, so we need to skip it orgDataSources = dataSources } else { diff --git a/pkg/api/index.go b/pkg/api/index.go index e6988767327..385ad644dea 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -29,8 +29,6 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV return nil, err } - settings.IsPublicDashboardView = c.IsPublicDashboardView - prefsQuery := pref.GetPreferenceWithDefaultsQuery{UserID: c.UserID, OrgID: c.OrgID, Teams: c.Teams} prefs, err := hs.preferenceService.GetWithDefaults(c.Req.Context(), &prefsQuery) if err != nil { diff --git a/pkg/services/contexthandler/contexthandler.go b/pkg/services/contexthandler/contexthandler.go index 9fedce32749..fa0a6fb4c20 100644 --- a/pkg/services/contexthandler/contexthandler.go +++ b/pkg/services/contexthandler/contexthandler.go @@ -61,19 +61,19 @@ func CopyWithReqContext(ctx context.Context) context.Context { Resp: web.NewResponseWriter(origReqCtx.Req.Method, response.CreateNormalResponse(http.Header{}, []byte{}, 0)), } reqCtx := &contextmodel.ReqContext{ - Context: webCtx, - SignedInUser: origReqCtx.SignedInUser, - UserToken: origReqCtx.UserToken, - IsSignedIn: origReqCtx.IsSignedIn, - IsRenderCall: origReqCtx.IsRenderCall, - AllowAnonymous: origReqCtx.AllowAnonymous, - SkipDSCache: origReqCtx.SkipDSCache, - SkipQueryCache: origReqCtx.SkipQueryCache, - Logger: origReqCtx.Logger, - Error: origReqCtx.Error, - RequestNonce: origReqCtx.RequestNonce, - IsPublicDashboardView: origReqCtx.IsPublicDashboardView, - LookupTokenErr: origReqCtx.LookupTokenErr, + Context: webCtx, + SignedInUser: origReqCtx.SignedInUser, + UserToken: origReqCtx.UserToken, + IsSignedIn: origReqCtx.IsSignedIn, + IsRenderCall: origReqCtx.IsRenderCall, + AllowAnonymous: origReqCtx.AllowAnonymous, + SkipDSCache: origReqCtx.SkipDSCache, + SkipQueryCache: origReqCtx.SkipQueryCache, + Logger: origReqCtx.Logger, + Error: origReqCtx.Error, + RequestNonce: origReqCtx.RequestNonce, + PublicDashboardAccessToken: origReqCtx.PublicDashboardAccessToken, + LookupTokenErr: origReqCtx.LookupTokenErr, } return context.WithValue(ctx, reqContextKey{}, reqCtx) } diff --git a/pkg/services/contexthandler/model/model.go b/pkg/services/contexthandler/model/model.go index d1dd30844fd..679b68afeee 100644 --- a/pkg/services/contexthandler/model/model.go +++ b/pkg/services/contexthandler/model/model.go @@ -30,8 +30,8 @@ type ReqContext struct { Logger log.Logger Error error // RequestNonce is a cryptographic request identifier for use with Content Security Policy. - RequestNonce string - IsPublicDashboardView bool + RequestNonce string + PublicDashboardAccessToken string PerfmonTimer prometheus.Summary LookupTokenErr error @@ -60,6 +60,10 @@ func (ctx *ReqContext) IsApiRequest() bool { return strings.HasPrefix(ctx.Req.URL.Path, "/api") } +func (ctx *ReqContext) IsPublicDashboardView() bool { + return ctx.PublicDashboardAccessToken != "" +} + func (ctx *ReqContext) JsonApiErr(status int, message string, err error) { resp := make(map[string]interface{}) traceID := tracing.TraceIDFromContext(ctx.Req.Context(), false) diff --git a/pkg/services/navtree/navtreeimpl/navtree.go b/pkg/services/navtree/navtreeimpl/navtree.go index 6bb32e14949..a09261395b9 100644 --- a/pkg/services/navtree/navtreeimpl/navtree.go +++ b/pkg/services/navtree/navtreeimpl/navtree.go @@ -95,7 +95,7 @@ func (s *ServiceImpl) GetNavTree(c *contextmodel.ReqContext, prefs *pref.Prefere }) } - if c.IsPublicDashboardView || hasAccess(ac.EvalAny( + if c.IsPublicDashboardView() || hasAccess(ac.EvalAny( ac.EvalPermission(dashboards.ActionFoldersRead), ac.EvalPermission(dashboards.ActionFoldersCreate), ac.EvalPermission(dashboards.ActionDashboardsRead), ac.EvalPermission(dashboards.ActionDashboardsCreate)), ) { diff --git a/pkg/services/ngalert/api/util_test.go b/pkg/services/ngalert/api/util_test.go index 8933cc60164..92fad5cce6e 100644 --- a/pkg/services/ngalert/api/util_test.go +++ b/pkg/services/ngalert/api/util_test.go @@ -46,16 +46,16 @@ func TestAlertingProxy_createProxyContext(t *testing.T) { Context: &web.Context{ Req: &http.Request{}, }, - SignedInUser: &user.SignedInUser{}, - UserToken: &auth.UserToken{}, - IsSignedIn: rand.Int63()%2 == 1, - IsRenderCall: rand.Int63()%2 == 1, - AllowAnonymous: rand.Int63()%2 == 1, - SkipDSCache: rand.Int63()%2 == 1, - SkipQueryCache: rand.Int63()%2 == 1, - Logger: log.New("test"), - RequestNonce: util.GenerateShortUID(), - IsPublicDashboardView: rand.Int63()%2 == 1, + SignedInUser: &user.SignedInUser{}, + UserToken: &auth.UserToken{}, + IsSignedIn: rand.Int63()%2 == 1, + IsRenderCall: rand.Int63()%2 == 1, + AllowAnonymous: rand.Int63()%2 == 1, + SkipDSCache: rand.Int63()%2 == 1, + SkipQueryCache: rand.Int63()%2 == 1, + Logger: log.New("test"), + RequestNonce: util.GenerateShortUID(), + PublicDashboardAccessToken: util.GenerateShortUID(), } t.Run("should create a copy of request context", func(t *testing.T) { @@ -81,7 +81,7 @@ func TestAlertingProxy_createProxyContext(t *testing.T) { require.Equal(t, ctx.SkipQueryCache, newCtx.SkipQueryCache) require.Equal(t, ctx.Logger, newCtx.Logger) require.Equal(t, ctx.RequestNonce, newCtx.RequestNonce) - require.Equal(t, ctx.IsPublicDashboardView, newCtx.IsPublicDashboardView) + require.Equal(t, ctx.PublicDashboardAccessToken, newCtx.PublicDashboardAccessToken) } }) t.Run("should overwrite response writer", func(t *testing.T) { diff --git a/pkg/services/pluginsintegration/clientmiddleware/caching_metrics.go b/pkg/services/pluginsintegration/clientmiddleware/caching_metrics.go index 27a0708d10d..2f452d550c8 100644 --- a/pkg/services/pluginsintegration/clientmiddleware/caching_metrics.go +++ b/pkg/services/pluginsintegration/clientmiddleware/caching_metrics.go @@ -36,7 +36,7 @@ var ResourceCachingRequestHistogram = prometheus.NewHistogramVec(prometheus.Hist }, []string{"plugin_id", "cache"}) func getQueryType(req *contextmodel.ReqContext) string { - if req.IsPublicDashboardView { + if req.IsPublicDashboardView() { return QueryPubdash } return QueryDashboard diff --git a/pkg/services/publicdashboards/api/middleware.go b/pkg/services/publicdashboards/api/middleware.go index 1805ae9c358..cac27ffbc79 100644 --- a/pkg/services/publicdashboards/api/middleware.go +++ b/pkg/services/publicdashboards/api/middleware.go @@ -28,9 +28,9 @@ func SetPublicDashboardOrgIdOnContext(publicDashboardService publicdashboards.Se } } -// SetPublicDashboardFlag Adds public dashboard flag on context -func SetPublicDashboardFlag(c *contextmodel.ReqContext) { - c.IsPublicDashboardView = true +// SetPublicDashboardAccessToken Adds public dashboard flag on context +func SetPublicDashboardAccessToken(c *contextmodel.ReqContext) { + c.PublicDashboardAccessToken = web.Params(c.Req)[":accessToken"] } // RequiresExistingAccessToken Middleware to enforce that a public dashboards exists before continuing to handler. This diff --git a/pkg/services/publicdashboards/api/middleware_test.go b/pkg/services/publicdashboards/api/middleware_test.go index 3e6f9811705..a7c9c5cf0ec 100644 --- a/pkg/services/publicdashboards/api/middleware_test.go +++ b/pkg/services/publicdashboards/api/middleware_test.go @@ -145,10 +145,10 @@ func TestSetPublicDashboardOrgIdOnContext(t *testing.T) { } func TestSetPublicDashboardFlag(t *testing.T) { - t.Run("Adds context.IsPublicDashboardView=true to request", func(t *testing.T) { - ctx := &contextmodel.ReqContext{} - SetPublicDashboardFlag(ctx) - assert.True(t, ctx.IsPublicDashboardView) + t.Run("Adds context.PublicDashboardAccessToken to request", func(t *testing.T) { + ctx := &contextmodel.ReqContext{Context: &web.Context{Req: web.SetURLParams(&http.Request{}, map[string]string{":accessToken": "asdfasdfasdfsadfasdfsfd"})}} + SetPublicDashboardAccessToken(ctx) + assert.NotEmpty(t, ctx.PublicDashboardAccessToken) }) } diff --git a/pkg/services/publicdashboards/api/query.go b/pkg/services/publicdashboards/api/query.go index b1575095cb9..2c5c5b410c6 100644 --- a/pkg/services/publicdashboards/api/query.go +++ b/pkg/services/publicdashboards/api/query.go @@ -30,21 +30,21 @@ func (api *Api) ViewPublicDashboard(c *contextmodel.ReqContext) response.Respons } meta := dtos.DashboardMeta{ - Slug: dash.Slug, - Type: dashboards.DashTypeDB, - CanStar: false, - CanSave: false, - CanEdit: false, - CanAdmin: false, - CanDelete: false, - Created: dash.Created, - Updated: dash.Updated, - Version: dash.Version, - IsFolder: false, - FolderId: dash.FolderID, - PublicDashboardAccessToken: pubdash.AccessToken, - PublicDashboardEnabled: pubdash.IsEnabled, + Slug: dash.Slug, + Type: dashboards.DashTypeDB, + CanStar: false, + CanSave: false, + CanEdit: false, + CanAdmin: false, + CanDelete: false, + Created: dash.Created, + Updated: dash.Updated, + Version: dash.Version, + IsFolder: false, + FolderId: dash.FolderID, + PublicDashboardEnabled: pubdash.IsEnabled, } + dash.Data.Get("timepicker").Set("hidden", !pubdash.TimeSelectionEnabled) dto := dtos.DashboardFullWithMeta{Meta: meta, Dashboard: dash.Data} diff --git a/pkg/services/query/query_test.go b/pkg/services/query/query_test.go index babf12a2ef3..5f0d3da55fa 100644 --- a/pkg/services/query/query_test.go +++ b/pkg/services/query/query_test.go @@ -287,11 +287,10 @@ func TestQueryDataMultipleSources(t *testing.T) { require.NoError(t, err) queries := []*simplejson.Json{query1, query2} reqDTO := dtos.MetricRequest{ - From: "2022-01-01", - To: "2022-01-02", - Queries: queries, - Debug: false, - PublicDashboardAccessToken: "abc123", + From: "2022-01-01", + To: "2022-01-02", + Queries: queries, + Debug: false, } req, err := http.NewRequest("POST", "http://localhost:3000", nil) @@ -351,11 +350,10 @@ func TestQueryDataMultipleSources(t *testing.T) { require.NoError(t, err) queries := []*simplejson.Json{query1, query2, query3} reqDTO := dtos.MetricRequest{ - From: "2022-01-01", - To: "2022-01-02", - Queries: queries, - Debug: false, - PublicDashboardAccessToken: "abc123", + From: "2022-01-01", + To: "2022-01-02", + Queries: queries, + Debug: false, } // without query parameter @@ -406,11 +404,10 @@ func TestQueryDataMultipleSources(t *testing.T) { queries := []*simplejson.Json{query1, query2} reqDTO := dtos.MetricRequest{ - From: "2022-01-01", - To: "2022-01-02", - Queries: queries, - Debug: false, - PublicDashboardAccessToken: "abc123", + From: "2022-01-01", + To: "2022-01-02", + Queries: queries, + Debug: false, } res, err := tc.queryService.QueryData(context.Background(), tc.signedInUser, true, reqDTO) @@ -436,11 +433,10 @@ func TestQueryDataMultipleSources(t *testing.T) { require.NoError(t, err) queries := []*simplejson.Json{query1} reqDTO := dtos.MetricRequest{ - From: "2022-01-01", - To: "2022-01-02", - Queries: queries, - Debug: false, - PublicDashboardAccessToken: "abc123", + From: "2022-01-01", + To: "2022-01-02", + Queries: queries, + Debug: false, } _, err = tc.queryService.QueryData(context.Background(), tc.signedInUser, true, reqDTO) diff --git a/public/app/angular/panel/metrics_panel_ctrl.ts b/public/app/angular/panel/metrics_panel_ctrl.ts index c92c02485a7..c969a6c70aa 100644 --- a/public/app/angular/panel/metrics_panel_ctrl.ts +++ b/public/app/angular/panel/metrics_panel_ctrl.ts @@ -200,7 +200,6 @@ class MetricsPanelCtrl extends PanelCtrl { timeRange: this.range, maxDataPoints: panel.maxDataPoints || this.width, minInterval: panel.interval, - publicDashboardAccessToken: this.dashboard.meta.publicDashboardAccessToken, scopedVars: panel.scopedVars, cacheTimeout: panel.cacheTimeout, queryCachingTTL: panel.queryCachingTTL, diff --git a/public/app/features/annotations/executeAnnotationQuery.ts b/public/app/features/annotations/executeAnnotationQuery.ts index eced30eb074..0bc7c72db7a 100644 --- a/public/app/features/annotations/executeAnnotationQuery.ts +++ b/public/app/features/annotations/executeAnnotationQuery.ts @@ -57,7 +57,6 @@ export function executeAnnotationQuery( scopedVars, ...interval, app: CoreApp.Dashboard, - publicDashboardAccessToken: options.dashboard.meta.publicDashboardAccessToken, timezone: options.dashboard.timezone, diff --git a/public/app/features/annotations/standardAnnotationSupport.ts b/public/app/features/annotations/standardAnnotationSupport.ts index c1782a691a3..869b639466f 100644 --- a/public/app/features/annotations/standardAnnotationSupport.ts +++ b/public/app/features/annotations/standardAnnotationSupport.ts @@ -133,7 +133,7 @@ export const publicDashboardEventNames: AnnotationFieldInfo[] = [ // Given legacy infrastructure, alert events are passed though the same annotation // pipeline, but include fields that should not be exposed generally const alertEventAndAnnotationFields: AnnotationFieldInfo[] = [ - ...(config.isPublicDashboardView ? publicDashboardEventNames : []), + ...(config.publicDashboardAccessToken ? publicDashboardEventNames : []), ...annotationEventNames, { key: 'userId' }, { key: 'login' }, diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.test.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.test.tsx index 9a74f820677..fa1ea16bdac 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.test.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.test.tsx @@ -1,6 +1,8 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; +import { config } from '@grafana/runtime'; + import { createEmptyQueryResponse } from '../../../explore/state/utils'; import { PanelModel } from '../../state'; import { createDashboardModelFixture } from '../../state/__fixtures__/dashboardFixtures'; @@ -17,9 +19,10 @@ let panelModel = new PanelModel({ let panelData = createEmptyQueryResponse(); describe('Panel Header', () => { - const dashboardModel = createDashboardModelFixture({}, { publicDashboardAccessToken: 'abc123' }); + const dashboardModel = createDashboardModelFixture({}, {}); it('will render header title but not render dropdown icon when dashboard is being viewed publicly', () => { window.history.pushState({}, 'Test Title', '/public-dashboards/abc123'); + config.publicDashboardAccessToken = 'abc123'; render( @@ -30,8 +33,9 @@ describe('Panel Header', () => { }); it('will render header title and dropdown icon when dashboard is not being viewed publicly', () => { - const dashboardModel = createDashboardModelFixture({}, { publicDashboardAccessToken: '' }); + const dashboardModel = createDashboardModelFixture({}, {}); window.history.pushState({}, 'Test Title', '/d/abc/123'); + config.publicDashboardAccessToken = ''; render( diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx index 144b7d4336a..36610b50921 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { DataLink, GrafanaTheme2, PanelData } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; -import { reportInteraction } from '@grafana/runtime'; +import { config, reportInteraction } from '@grafana/runtime'; import { Icon, useStyles2, ClickOutsideWrapper } from '@grafana/ui'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; @@ -65,7 +65,7 @@ export function PanelHeader({ panel, error, isViewing, isEditing, data, alertSta /> ) : null}

{title}

- {!dashboard.meta.publicDashboardAccessToken && ( + {!config.publicDashboardAccessToken && (
{panelMenuOpen ? : null} diff --git a/public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx b/public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx index cda7caa7081..067f92a9eea 100644 --- a/public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx +++ b/public/app/features/dashboard/dashgrid/PanelStateWrapper.tsx @@ -353,7 +353,6 @@ export class PanelStateWrapper extends PureComponent { panel.runAllPanelQueries({ dashboardUID: dashboard.uid, dashboardTimezone: dashboard.getTimezone(), - publicDashboardAccessToken: dashboard.meta.publicDashboardAccessToken, timeData, width, }); diff --git a/public/app/features/dashboard/services/PublicDashboardDataSource.test.ts b/public/app/features/dashboard/services/PublicDashboardDataSource.test.ts index 15fc9b3312d..dd31afc7b2f 100644 --- a/public/app/features/dashboard/services/PublicDashboardDataSource.test.ts +++ b/public/app/features/dashboard/services/PublicDashboardDataSource.test.ts @@ -1,7 +1,7 @@ import { of } from 'rxjs'; import { DataQueryRequest, DataSourceInstanceSettings, DataSourceRef, dateTime, TimeRange } from '@grafana/data'; -import { BackendSrvRequest, BackendSrv, DataSourceWithBackend } from '@grafana/runtime'; +import { BackendSrvRequest, BackendSrv, DataSourceWithBackend, config } from '@grafana/runtime'; import { GrafanaQueryType } from 'app/plugins/datasource/grafana/types'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; @@ -45,41 +45,14 @@ describe('PublicDashboardDatasource', () => { expect(annotation?.queryType).toEqual(GrafanaQueryType.Annotations); }); - test('will not fetch annotations when access token is falsey', async () => { - mockDatasourceRequest.mockReset(); - mockDatasourceRequest.mockReturnValue(Promise.resolve([])); - - const ds = new PublicDashboardDataSource('public'); - const panelId = 1; - const publicDashboardAccessToken = undefined; - - await ds.query({ - maxDataPoints: 10, - intervalMs: 5000, - targets: [ - { - refId: 'A', - datasource: { uid: GRAFANA_DATASOURCE_NAME, type: 'sample' }, - queryType: GrafanaQueryType.Annotations, - }, - ], - panelId, - publicDashboardAccessToken, - range: { from: new Date().toLocaleString(), to: new Date().toLocaleString() } as unknown as TimeRange, - } as DataQueryRequest); - - const mock = mockDatasourceRequest.mock; - - expect(mock.calls.length).toBe(0); - }); - test('fetches results from the pubdash annotations endpoint when it is an annotation query', async () => { mockDatasourceRequest.mockReset(); mockDatasourceRequest.mockReturnValue(Promise.resolve([])); const ds = new PublicDashboardDataSource('public'); const panelId = 1; - const publicDashboardAccessToken = 'abc123'; + + config.publicDashboardAccessToken = 'abc123'; await ds.query({ maxDataPoints: 10, @@ -92,14 +65,13 @@ describe('PublicDashboardDatasource', () => { }, ], panelId, - publicDashboardAccessToken, range: { from: new Date().toLocaleString(), to: new Date().toLocaleString() } as unknown as TimeRange, } as DataQueryRequest); const mock = mockDatasourceRequest.mock; expect(mock.calls.length).toBe(1); - expect(mock.lastCall[0]).toEqual(`/api/public/dashboards/${publicDashboardAccessToken}/annotations`); + expect(mock.lastCall[0]).toEqual(`/api/public/dashboards/abc123/annotations`); }); test('fetches results from the pubdash query endpoint when not annotation query', () => { @@ -108,7 +80,7 @@ describe('PublicDashboardDatasource', () => { const ds = new PublicDashboardDataSource('public'); const panelId = 1; - const publicDashboardAccessToken = 'abc123'; + config.publicDashboardAccessToken = 'abc123'; ds.query({ maxDataPoints: 10, @@ -123,15 +95,12 @@ describe('PublicDashboardDatasource', () => { to: 'now', }, }, - publicDashboardAccessToken, } as DataQueryRequest); const mock = mockDatasourceRequest.mock; expect(mock.calls.length).toBe(1); - expect(mock.lastCall[0].url).toEqual( - `/api/public/dashboards/${publicDashboardAccessToken}/panels/${panelId}/query` - ); + expect(mock.lastCall[0].url).toEqual(`/api/public/dashboards/abc123/panels/${panelId}/query`); }); test('returns public datasource uid when datasource passed in is null', () => { diff --git a/public/app/features/dashboard/services/PublicDashboardDataSource.ts b/public/app/features/dashboard/services/PublicDashboardDataSource.ts index 4b5cc9fc0bf..05abe8a45fe 100644 --- a/public/app/features/dashboard/services/PublicDashboardDataSource.ts +++ b/public/app/features/dashboard/services/PublicDashboardDataSource.ts @@ -12,7 +12,7 @@ import { DataSourceRef, toDataFrame, } from '@grafana/data'; -import { BackendDataSourceResponse, getBackendSrv, toDataQueryResponse } from '@grafana/runtime'; +import { BackendDataSourceResponse, config, getBackendSrv, toDataQueryResponse } from '@grafana/runtime'; import { GrafanaQueryType } from '../../../plugins/datasource/grafana/types'; import { MIXED_DATASOURCE_NAME } from '../../../plugins/datasource/mixed/MixedDataSource'; @@ -85,7 +85,6 @@ export class PublicDashboardDataSource extends DataSourceApi({ - url: `/api/public/dashboards/${publicDashboardAccessToken}/panels/${panelId}/query`, + url: `/api/public/dashboards/${config.publicDashboardAccessToken!}/panels/${panelId}/query`, method: 'POST', data: body, requestId, @@ -138,7 +137,6 @@ export class PublicDashboardDataSource extends DataSourceApi): Promise { const { - publicDashboardAccessToken: accessToken, range: { to, from }, } = request; @@ -147,9 +145,10 @@ export class PublicDashboardDataSource extends DataSourceApi { }; locationService.push('/d/id?from=now-24h&to=now'); - config.isPublicDashboardView = true; + config.publicDashboardAccessToken = 'abc123'; timeSrv = new TimeSrv(new ContextSrvStub()); }); diff --git a/public/app/features/dashboard/services/TimeSrv.ts b/public/app/features/dashboard/services/TimeSrv.ts index 4ab6dfae24e..0a1b7fe8268 100644 --- a/public/app/features/dashboard/services/TimeSrv.ts +++ b/public/app/features/dashboard/services/TimeSrv.ts @@ -149,7 +149,7 @@ export class TimeSrv { } private initTimeFromUrl() { - if (config.isPublicDashboardView && this.timeModel?.timepicker?.hidden) { + if (config.publicDashboardAccessToken && this.timeModel?.timepicker?.hidden) { return; } diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index fddf8a198a3..0c05bc7ef23 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -359,19 +359,12 @@ export class PanelModel implements DataConfigSource, IPanelModel { this.render(); } - runAllPanelQueries({ - dashboardUID, - dashboardTimezone, - timeData, - width, - publicDashboardAccessToken, - }: RunPanelQueryOptions) { + runAllPanelQueries({ dashboardUID, dashboardTimezone, timeData, width }: RunPanelQueryOptions) { this.getQueryRunner().run({ datasource: this.datasource, queries: this.targets, panelId: this.id, dashboardUID: dashboardUID, - publicDashboardAccessToken, timezone: dashboardTimezone, timeRange: timeData.timeRange, timeInfo: timeData.timeInfo, diff --git a/public/app/features/query/state/DashboardQueryRunner/AnnotationsWorker.test.ts b/public/app/features/query/state/DashboardQueryRunner/AnnotationsWorker.test.ts index d83545fc021..7f0a6558550 100644 --- a/public/app/features/query/state/DashboardQueryRunner/AnnotationsWorker.test.ts +++ b/public/app/features/query/state/DashboardQueryRunner/AnnotationsWorker.test.ts @@ -91,15 +91,6 @@ describe('AnnotationsWorker', () => { }); }); - describe('when canWork is called with correct props for a public dashboard with public view', () => { - it('then it should return true', () => { - const options = getDefaultOptions(); - options.dashboard.meta.publicDashboardAccessToken = 'accessTokenString'; - - expect(worker.canWork(options)).toBe(true); - }); - }); - describe('when canWork is called with incorrect props', () => { it('then it should return false', () => { const dashboard = { annotations: { list: [] } } as unknown as DashboardModel; diff --git a/public/app/features/query/state/DashboardQueryRunner/AnnotationsWorker.ts b/public/app/features/query/state/DashboardQueryRunner/AnnotationsWorker.ts index 1c7bd84cbcb..b31b0fb0fbc 100644 --- a/public/app/features/query/state/DashboardQueryRunner/AnnotationsWorker.ts +++ b/public/app/features/query/state/DashboardQueryRunner/AnnotationsWorker.ts @@ -3,8 +3,7 @@ import { from, merge, Observable, of } from 'rxjs'; import { catchError, filter, finalize, map, mergeAll, mergeMap, reduce, takeUntil } from 'rxjs/operators'; import { AnnotationQuery, DataSourceApi } from '@grafana/data'; -import { getDataSourceSrv } from '@grafana/runtime'; -import { getConfig } from 'app/core/config'; +import { config, getDataSourceSrv } from '@grafana/runtime'; import { AnnotationQueryFinished, AnnotationQueryStarted } from '../../../../types/events'; import { PUBLIC_DATASOURCE, PublicDashboardDataSource } from '../../../dashboard/services/PublicDashboardDataSource'; @@ -41,14 +40,16 @@ export class AnnotationsWorker implements DashboardQueryRunnerWorker { const { dashboard, range } = options; let annotations = dashboard.annotations.list.filter(AnnotationsWorker.getAnnotationsToProcessFilter); + // We only want to create a single PublicDashboardDatasource. This will get all annotations in one request. - if (dashboard.meta.publicDashboardAccessToken && annotations.length > 0) { + if (config.publicDashboardAccessToken && annotations.length > 0) { annotations = [annotations[0]]; } + const observables = annotations.map((annotation) => { let datasourceObservable; - if (getConfig().isPublicDashboardView) { + if (config.publicDashboardAccessToken) { const pubdashDatasource = new PublicDashboardDataSource(PUBLIC_DATASOURCE); datasourceObservable = of(pubdashDatasource).pipe(catchError(handleDatasourceSrvError)); } else { @@ -78,7 +79,7 @@ export class AnnotationsWorker implements DashboardQueryRunnerWorker { annotation.snapshotData = cloneDeep(results); } // translate result - if (dashboard.meta.publicDashboardAccessToken) { + if (config.publicDashboardAccessToken) { return results; } else { return translateQueryResult(annotation, results); diff --git a/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.test.ts b/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.test.ts index 8d58e1bf12d..2b7ab9064ab 100644 --- a/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.test.ts +++ b/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.test.ts @@ -1,6 +1,7 @@ import { lastValueFrom } from 'rxjs'; import { AlertState, getDefaultTimeRange, TimeRange } from '@grafana/data'; +import { config } from '@grafana/runtime'; import { backendSrv } from 'app/core/services/backend_srv'; import { disableRBAC, enableRBAC, grantUserPermissions } from 'app/features/alerting/unified/mocks'; import { Annotation } from 'app/features/alerting/unified/utils/constants'; @@ -25,9 +26,7 @@ function getDefaultOptions(): DashboardQueryRunnerOptions { id: 12345, uid: 'a uid', }, - { - publicDashboardAccessToken: '', - } + {} ); const range = getDefaultTimeRange(); @@ -46,6 +45,10 @@ function getTestContext() { describe('UnifiedAlertStatesWorker', () => { const worker = new UnifiedAlertStatesWorker(); + beforeEach(() => { + config.publicDashboardAccessToken = ''; + }); + beforeAll(() => { disableRBAC(); }); @@ -61,7 +64,7 @@ describe('UnifiedAlertStatesWorker', () => { describe('when canWork is called on a public dashboard view', () => { it('then it should return false', () => { const options = getDefaultOptions(); - options.dashboard.meta.publicDashboardAccessToken = 'abc123'; + config.publicDashboardAccessToken = 'abc123'; expect(worker.canWork(options)).toBe(false); }); diff --git a/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.ts b/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.ts index 29d2cb02fc0..0591d0b8ae0 100644 --- a/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.ts +++ b/public/app/features/query/state/DashboardQueryRunner/UnifiedAlertStatesWorker.ts @@ -2,7 +2,7 @@ import { from, Observable } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; import { AlertState, AlertStateInfo } from '@grafana/data'; -import { getBackendSrv } from '@grafana/runtime'; +import { config, getBackendSrv } from '@grafana/runtime'; import { contextSrv } from 'app/core/services/context_srv'; import { Annotation } from 'app/features/alerting/unified/utils/constants'; import { isAlertingRule } from 'app/features/alerting/unified/utils/rules'; @@ -24,7 +24,7 @@ export class UnifiedAlertStatesWorker implements DashboardQueryRunnerWorker { } // Cannot fetch rules while on a public dashboard since it's unauthenticated - if (dashboard.meta.publicDashboardAccessToken) { + if (config.publicDashboardAccessToken) { return false; } diff --git a/public/app/features/query/state/DashboardQueryRunner/testHelpers.ts b/public/app/features/query/state/DashboardQueryRunner/testHelpers.ts index 2235db10425..9e90efdf8a2 100644 --- a/public/app/features/query/state/DashboardQueryRunner/testHelpers.ts +++ b/public/app/features/query/state/DashboardQueryRunner/testHelpers.ts @@ -55,9 +55,7 @@ export function getDefaultOptions(): DashboardQueryRunnerOptions { publish: jest.fn(), }, panels: [{ alert: {} } as any], - meta: { - publicDashboardAccessToken: '', - }, + meta: {}, }; const range = getDefaultTimeRange(); diff --git a/public/app/features/query/state/PanelQueryRunner.ts b/public/app/features/query/state/PanelQueryRunner.ts index 2ffa6f2cd9c..23ac379b56a 100644 --- a/public/app/features/query/state/PanelQueryRunner.ts +++ b/public/app/features/query/state/PanelQueryRunner.ts @@ -29,7 +29,7 @@ import { toDataFrame, transformDataFrame, } from '@grafana/data'; -import { getTemplateSrv, toDataQueryError } from '@grafana/runtime'; +import { config, getTemplateSrv, toDataQueryError } from '@grafana/runtime'; import { ExpressionDatasourceRef } from '@grafana/runtime/src/utils/DataSourceWithBackend'; import { updatePanelDataWithASHFromLoki } from 'app/features/alerting/unified/components/rules/state-history/common'; import { isStreamingDataFrame } from 'app/features/live/data/utils'; @@ -51,7 +51,6 @@ export interface QueryRunnerOptions< queries: TQuery[]; panelId?: number; dashboardUID?: string; - publicDashboardAccessToken?: string; timezone: TimeZone; timeRange: TimeRange; timeInfo?: string; // String description of time range for display @@ -241,7 +240,6 @@ export class PanelQueryRunner { datasource, panelId, dashboardUID, - publicDashboardAccessToken, timeRange, timeInfo, cacheTimeout, @@ -263,7 +261,6 @@ export class PanelQueryRunner { timezone, panelId, dashboardUID, - publicDashboardAccessToken, range: timeRange, timeInfo, interval: '', @@ -278,7 +275,7 @@ export class PanelQueryRunner { }; try { - const ds = await getDataSource(datasource, request.scopedVars, publicDashboardAccessToken); + const ds = await getDataSource(datasource, request.scopedVars); const isMixedDS = ds.meta?.mixed; // Attach the data source to each query @@ -416,15 +413,14 @@ export class PanelQueryRunner { async function getDataSource( datasource: DataSourceRef | string | DataSourceApi | null, - scopedVars: ScopedVars, - publicDashboardAccessToken?: string + scopedVars: ScopedVars ): Promise { - if (!publicDashboardAccessToken && datasource && typeof datasource === 'object' && 'query' in datasource) { + if (!config.publicDashboardAccessToken && datasource && typeof datasource === 'object' && 'query' in datasource) { return datasource; } const ds = await getDatasourceSrv().get(datasource, scopedVars); - if (publicDashboardAccessToken) { + if (config.publicDashboardAccessToken) { return new PublicDashboardDataSource(ds); } diff --git a/public/app/plugins/datasource/opentsdb/specs/datasource.test.ts b/public/app/plugins/datasource/opentsdb/specs/datasource.test.ts index f854e6856e2..fc27d9a3d02 100644 --- a/public/app/plugins/datasource/opentsdb/specs/datasource.test.ts +++ b/public/app/plugins/datasource/opentsdb/specs/datasource.test.ts @@ -190,7 +190,6 @@ describe('opentsdb', () => { timezone: 'browser', panelId: 2, dashboardUID: 'tyzmfPIVz', - publicDashboardAccessToken: '', range: { from: dateTime('2022-10-19T08:55:18.430Z'), to: dateTime('2022-10-19T14:55:18.431Z'), diff --git a/public/app/types/dashboard.ts b/public/app/types/dashboard.ts index 7ac5d3c948f..73540389d23 100644 --- a/public/app/types/dashboard.ts +++ b/public/app/types/dashboard.ts @@ -49,7 +49,6 @@ export interface DashboardMeta { fromFile?: boolean; hasUnsavedFolderChange?: boolean; annotationsPermissions?: AnnotationsPermissions; - publicDashboardAccessToken?: string; publicDashboardUid?: string; publicDashboardEnabled?: boolean; dashboardNotFound?: boolean;