From 9c2f3045b4a74f5ca98302829d16237760434062 Mon Sep 17 00:00:00 2001 From: Guilherme Caulada Date: Wed, 21 Sep 2022 13:29:27 -0300 Subject: [PATCH] PublicDashboards: Resolve interval for public dashboard data source (#55489) * Resolve interval for public dashboard data source * Remove type assertions in favor of 'in' * Add org id to public dashboard requests --- .betterer.results | 14 +++----- .../publicdashboards/api/middleware.go | 7 ++++ .../PublicDashboardDataSource.test.ts | 33 ++++++++++++++++++- .../services/PublicDashboardDataSource.ts | 18 ++++++++-- .../features/query/state/PanelQueryRunner.ts | 13 ++++---- 5 files changed, 65 insertions(+), 20 deletions(-) diff --git a/.betterer.results b/.betterer.results index 5886c801ee6..73297502d33 100644 --- a/.betterer.results +++ b/.betterer.results @@ -3902,11 +3902,9 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "1"] ], "public/app/features/dashboard/services/PublicDashboardDataSource.ts:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Do not use any type assertions.", "1"], - [0, 0, 0, "Unexpected any. Specify a different type.", "2"], - [0, 0, 0, "Unexpected any. Specify a different type.", "3"], - [0, 0, 0, "Unexpected any. Specify a different type.", "4"] + [0, 0, 0, "Do not use any type assertions.", "0"], + [0, 0, 0, "Unexpected any. Specify a different type.", "1"], + [0, 0, 0, "Unexpected any. Specify a different type.", "2"] ], "public/app/features/dashboard/services/TimeSrv.test.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], @@ -5046,11 +5044,7 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "2"], [0, 0, 0, "Unexpected any. Specify a different type.", "3"], [0, 0, 0, "Do not use any type assertions.", "4"], - [0, 0, 0, "Do not use any type assertions.", "5"], - [0, 0, 0, "Do not use any type assertions.", "6"], - [0, 0, 0, "Unexpected any. Specify a different type.", "7"], - [0, 0, 0, "Do not use any type assertions.", "8"], - [0, 0, 0, "Do not use any type assertions.", "9"] + [0, 0, 0, "Do not use any type assertions.", "5"] ], "public/app/features/query/state/runRequest.test.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] diff --git a/pkg/services/publicdashboards/api/middleware.go b/pkg/services/publicdashboards/api/middleware.go index f1792198b11..58fccb6759e 100644 --- a/pkg/services/publicdashboards/api/middleware.go +++ b/pkg/services/publicdashboards/api/middleware.go @@ -2,6 +2,7 @@ package api import ( "net/http" + "strconv" "github.com/grafana/grafana/pkg/infra/metrics" "github.com/grafana/grafana/pkg/models" @@ -11,6 +12,12 @@ import ( func SetPublicDashboardFlag() func(c *models.ReqContext) { return func(c *models.ReqContext) { + // TODO: Find a better place to set this, or rename this function + orgIDValue := c.Req.URL.Query().Get("orgId") + orgID, err := strconv.ParseInt(orgIDValue, 10, 64) + if err == nil && orgID > 0 && orgID != c.OrgID { + c.OrgID = orgID + } c.IsPublicDashboardView = true } } diff --git a/public/app/features/dashboard/services/PublicDashboardDataSource.test.ts b/public/app/features/dashboard/services/PublicDashboardDataSource.test.ts index 817d862ee16..f44931ba773 100644 --- a/public/app/features/dashboard/services/PublicDashboardDataSource.test.ts +++ b/public/app/features/dashboard/services/PublicDashboardDataSource.test.ts @@ -4,7 +4,7 @@ import { DataQueryRequest, DataSourceInstanceSettings, DataSourceRef } from '@gr import { BackendSrvRequest, BackendSrv, DataSourceWithBackend } from '@grafana/runtime'; import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource'; -import { PublicDashboardDataSource, PUBLIC_DATASOURCE } from './PublicDashboardDataSource'; +import { PublicDashboardDataSource, PUBLIC_DATASOURCE, DEFAULT_INTERVAL } from './PublicDashboardDataSource'; const mockDatasourceRequest = jest.fn(); @@ -93,4 +93,35 @@ describe('PublicDashboardDatasource', () => { let ds = new PublicDashboardDataSource(null); expect(ds.meta.mixed).toBeFalsy(); }); + + test('returns default datasource interval when datasource passed in is null', () => { + let ds = new PublicDashboardDataSource(null); + expect(ds.interval).toBe(DEFAULT_INTERVAL); + }); + + test('returns default datasource interval when datasource passed in is a string', () => { + let ds = new PublicDashboardDataSource('theDatasourceUid'); + expect(ds.interval).toBe(DEFAULT_INTERVAL); + }); + + test('returns default datasource interval when datasource passed in is a DataSourceRef implementation', () => { + const datasource = { type: 'datasource', uid: 'abc123' }; + let ds = new PublicDashboardDataSource(datasource); + expect(ds.interval).toBe(DEFAULT_INTERVAL); + }); + + test('returns default datasource interval when datasource passed in is a DatasourceApi instance that has no interval', () => { + const settings: DataSourceInstanceSettings = { id: 1, uid: 'abc123' } as DataSourceInstanceSettings; + const datasource = new DataSourceWithBackend(settings); + let ds = new PublicDashboardDataSource(datasource); + expect(ds.interval).toBe(DEFAULT_INTERVAL); + }); + + test('returns datasource interval when datasource passed in is a DatasourceApi instance that has interval', () => { + const settings: DataSourceInstanceSettings = { id: 1, uid: 'abc123' } as DataSourceInstanceSettings; + const datasource = new DataSourceWithBackend(settings); + datasource.interval = 'abc123'; + let ds = new PublicDashboardDataSource(datasource); + expect(ds.interval).toBe('abc123'); + }); }); diff --git a/public/app/features/dashboard/services/PublicDashboardDataSource.ts b/public/app/features/dashboard/services/PublicDashboardDataSource.ts index f116a76ff21..1ddecb938be 100644 --- a/public/app/features/dashboard/services/PublicDashboardDataSource.ts +++ b/public/app/features/dashboard/services/PublicDashboardDataSource.ts @@ -5,6 +5,7 @@ import { DataQueryRequest, DataQueryResponse, DataSourceApi, + DataSourceJsonData, DataSourcePluginMeta, DataSourceRef, } from '@grafana/data'; @@ -13,8 +14,9 @@ import { BackendDataSourceResponse, getBackendSrv, toDataQueryResponse } from '@ import { MIXED_DATASOURCE_NAME } from '../../../plugins/datasource/mixed/MixedDataSource'; export const PUBLIC_DATASOURCE = '-- Public --'; +export const DEFAULT_INTERVAL = '1min'; -export class PublicDashboardDataSource extends DataSourceApi { +export class PublicDashboardDataSource extends DataSourceApi { constructor(datasource: DataSourceRef | string | DataSourceApi | null) { let meta = {} as DataSourcePluginMeta; if (PublicDashboardDataSource.isMixedDatasource(datasource)) { @@ -32,7 +34,7 @@ export class PublicDashboardDataSource extends DataSourceApi { readOnly: true, }); - this.interval = '1min'; + this.interval = PublicDashboardDataSource.resolveInterval(datasource); } /** @@ -54,10 +56,20 @@ export class PublicDashboardDataSource extends DataSourceApi { return datasource?.uid === MIXED_DATASOURCE_NAME; } + private static resolveInterval(datasource: DataSourceRef | string | DataSourceApi | null): string { + if (typeof datasource === 'string' || datasource === null) { + return DEFAULT_INTERVAL; + } + + const interval = 'interval' in datasource ? datasource.interval : undefined; + + return interval ?? DEFAULT_INTERVAL; + } + /** * Ideally final -- any other implementation may not work as expected */ - query(request: DataQueryRequest): Observable { + query(request: DataQueryRequest): Observable { const { intervalMs, maxDataPoints, requestId, publicDashboardAccessToken, panelId } = request; let queries: DataQuery[]; diff --git a/public/app/features/query/state/PanelQueryRunner.ts b/public/app/features/query/state/PanelQueryRunner.ts index 9202bd227f4..3f3a2c480b8 100644 --- a/public/app/features/query/state/PanelQueryRunner.ts +++ b/public/app/features/query/state/PanelQueryRunner.ts @@ -370,13 +370,14 @@ async function getDataSource( scopedVars: ScopedVars, publicDashboardAccessToken?: string ): Promise { + if (!publicDashboardAccessToken && datasource && typeof datasource === 'object' && 'query' in datasource) { + return datasource; + } + + const ds = await getDatasourceSrv().get(datasource, scopedVars); if (publicDashboardAccessToken) { - return new PublicDashboardDataSource(datasource); + return new PublicDashboardDataSource(ds); } - if (datasource && (datasource as any).query) { - return datasource as DataSourceApi; - } - - return await getDatasourceSrv().get(datasource as string, scopedVars); + return ds; }