Public Dashboards Bug: Permissions error on panel when using mixed datasource with Enterprise (#51930)

Fixes pubdash bug for enterprise when pubdash panel uses a mixed datasource
This commit is contained in:
owensmallwood 2022-07-07 15:58:11 -06:00 committed by GitHub
parent e1d36754a1
commit 2aff83d4e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 139 additions and 5 deletions

View File

@ -7,6 +7,7 @@ import {
PUBLIC_DATASOURCE,
PublicDashboardDataSource,
} from '../../../../public/app/features/dashboard/services/PublicDashboardDataSource';
import { MIXED_DATASOURCE_NAME } from '../../../../public/app/plugins/datasource/mixed/MixedDataSource';
import { DataSourceWithBackend } from './DataSourceWithBackend';
@ -75,4 +76,26 @@ describe('PublicDashboardDatasource', () => {
let ds = new PublicDashboardDataSource(datasource);
expect(ds.uid).toBe('abc123');
});
test('isMixedDatasource returns true when datasource is mixed', () => {
const datasource = new DataSourceWithBackend({ id: 1, uid: MIXED_DATASOURCE_NAME } as DataSourceInstanceSettings);
let ds = new PublicDashboardDataSource(datasource);
expect(ds.meta.mixed).toBeTruthy();
});
test('isMixedDatasource returns false when datasource is not mixed', () => {
const datasource = new DataSourceWithBackend({ id: 1, uid: 'abc123' } as DataSourceInstanceSettings);
let ds = new PublicDashboardDataSource(datasource);
expect(ds.meta.mixed).toBeFalsy();
});
test('isMixedDatasource returns false when datasource is a string', () => {
let ds = new PublicDashboardDataSource('abc123');
expect(ds.meta.mixed).toBeFalsy();
});
test('isMixedDatasource returns false when datasource is null', () => {
let ds = new PublicDashboardDataSource(null);
expect(ds.meta.mixed).toBeFalsy();
});
});

View File

@ -11,9 +11,22 @@ func GetUniqueDashboardDatasourceUids(dashboard *simplejson.Json) []string {
for _, panelObj := range dashboard.Get("panels").MustArray() {
panel := simplejson.NewFromAny(panelObj)
uid := panel.Get("datasource").Get("uid").MustString()
if _, ok := exists[uid]; !ok {
datasourceUids = append(datasourceUids, uid)
exists[uid] = true
// if uid is for a mixed datasource, get the datasource uids from the targets
if uid == "-- Mixed --" {
for _, target := range panel.Get("targets").MustArray() {
target := simplejson.NewFromAny(target)
datasourceUid := target.Get("datasource").Get("uid").MustString()
if _, ok := exists[datasourceUid]; !ok {
datasourceUids = append(datasourceUids, datasourceUid)
exists[datasourceUid] = true
}
}
} else {
if _, ok := exists[uid]; !ok {
datasourceUids = append(datasourceUids, uid)
exists[uid] = true
}
}
}

View File

@ -56,6 +56,79 @@ const (
"schemaVersion": 35
}`
dashboardWithMixedDatasource = `
{
"panels": [
{
"datasource": {
"type": "datasource",
"uid": "-- Mixed --"
},
"id": 1,
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "abc123"
},
"exemplar": true,
"expr": "go_goroutines{job=\"$job\"}",
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"title": "Panel Title",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "_yxMP8Ynk"
},
"id": 2,
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "_yxMP8Ynk"
},
"exemplar": true,
"expr": "go_goroutines{job=\"$job\"}",
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"title": "Panel Title",
"type": "timeseries"
},
{
"datasource": {
"type": "prometheus",
"uid": "_yxMP8Ynk"
},
"id": 3,
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "_yxMP8Ynk"
},
"exemplar": true,
"expr": "go_goroutines{job=\"$job\"}",
"interval": "",
"legendFormat": "",
"refId": "A"
}
],
"title": "Panel Title",
"type": "timeseries"
}
],
"schemaVersion": 35
}`
dashboardWithDuplicateDatasources = `
{
"panels": [
@ -163,6 +236,16 @@ func TestGetUniqueDashboardDatasourceUids(t *testing.T) {
require.Equal(t, "_yxMP8Ynk", uids[1])
})
t.Run("can get unique datasource ids from dashboard with a mixed datasource", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(dashboardWithMixedDatasource))
require.NoError(t, err)
uids := GetUniqueDashboardDatasourceUids(json)
require.Len(t, uids, 2)
require.Equal(t, "abc123", uids[0])
require.Equal(t, "_yxMP8Ynk", uids[1])
})
t.Run("can get no datasource uids from empty dashboard", func(t *testing.T) {
json, err := simplejson.NewJson([]byte(`{"panels": {}}`))
require.NoError(t, err)

View File

@ -5,20 +5,27 @@ import {
DataQueryRequest,
DataQueryResponse,
DataSourceApi,
DataSourcePluginMeta,
DataSourceRef,
PluginMeta,
} from '@grafana/data';
import { BackendDataSourceResponse, getBackendSrv, toDataQueryResponse } from '@grafana/runtime';
import { MIXED_DATASOURCE_NAME } from '../../../plugins/datasource/mixed/MixedDataSource';
export const PUBLIC_DATASOURCE = '-- Public --';
export class PublicDashboardDataSource extends DataSourceApi<any> {
constructor(datasource: DataSourceRef | string | DataSourceApi | null) {
let meta = {} as DataSourcePluginMeta;
if (PublicDashboardDataSource.isMixedDatasource(datasource)) {
meta.mixed = true;
}
super({
name: 'public-ds',
id: 0,
type: 'public-ds',
meta: {} as PluginMeta,
meta,
uid: PublicDashboardDataSource.resolveUid(datasource),
jsonData: {},
access: 'proxy',
@ -38,6 +45,14 @@ export class PublicDashboardDataSource extends DataSourceApi<any> {
return datasource?.uid ?? PUBLIC_DATASOURCE;
}
private static isMixedDatasource(datasource: DataSourceRef | string | DataSourceApi | null): boolean {
if (typeof datasource === 'string' || datasource === null) {
return false;
}
return datasource?.uid === MIXED_DATASOURCE_NAME;
}
/**
* Ideally final -- any other implementation may not work as expected
*/