grafana/public/app/features/datasources/state/navModel.ts
Karl Persson 6d1bcd9f40
DataSourcePermissions: Handle licensing properly for ds permissions (#59694)
* RBAC: add viewer grand if dspermissions enforcement is not enabled

* RBAC: Change permissions based on role prefix

* RBAC: Add option to for permission service to add a license middleware

* RBAC: Remove actions from query struct
2022-12-02 13:19:14 +01:00

214 lines
6.1 KiB
TypeScript

import { DataSourceSettings, PluginType, PluginInclude, NavModel, NavModelItem } from '@grafana/data';
import { featureEnabled } from '@grafana/runtime';
import { ProBadge } from 'app/core/components/Upgrade/ProBadge';
import config from 'app/core/config';
import { contextSrv } from 'app/core/core';
import { highlightTrial } from 'app/features/admin/utils';
import { AccessControlAction } from 'app/types';
import { GenericDataSourcePlugin } from '../types';
const loadingDSType = 'Loading';
export function buildNavModel(dataSource: DataSourceSettings, plugin: GenericDataSourcePlugin): NavModelItem {
const pluginMeta = plugin.meta;
const highlightsEnabled = config.featureToggles.featureHighlights;
const navModel: NavModelItem = {
img: pluginMeta.info.logos.large,
id: 'datasource-' + dataSource.uid,
subTitle: `Type: ${pluginMeta.name}`,
url: '',
text: dataSource.name,
breadcrumbs: [{ title: 'Data Sources', url: 'datasources' }],
children: [
{
active: false,
icon: 'sliders-v-alt',
id: `datasource-settings-${dataSource.uid}`,
text: 'Settings',
url: `datasources/edit/${dataSource.uid}/`,
},
],
};
if (plugin.configPages) {
for (const page of plugin.configPages) {
navModel.children!.push({
active: false,
text: page.title,
icon: page.icon,
url: `datasources/edit/${dataSource.uid}/?page=${page.id}`,
id: `datasource-page-${page.id}`,
});
}
}
if (pluginMeta.includes && hasDashboards(pluginMeta.includes) && contextSrv.hasRole('Admin')) {
navModel.children!.push({
active: false,
icon: 'apps',
id: `datasource-dashboards-${dataSource.uid}`,
text: 'Dashboards',
url: `datasources/edit/${dataSource.uid}/dashboards`,
});
}
const isLoadingNav = dataSource.type === loadingDSType;
const permissionsExperimentId = 'feature-highlights-data-source-permissions-badge';
const dsPermissions: NavModelItem = {
active: false,
icon: 'lock',
id: `datasource-permissions-${dataSource.uid}`,
text: 'Permissions',
url: `datasources/edit/${dataSource.uid}/permissions`,
};
if (highlightTrial() && !isLoadingNav) {
dsPermissions.tabSuffix = () => ProBadge({ experimentId: permissionsExperimentId, eventVariant: 'trial' });
}
if (featureEnabled('dspermissions.enforcement')) {
if (contextSrv.hasPermission(AccessControlAction.DataSourcesPermissionsRead)) {
navModel.children!.push(dsPermissions);
}
} else if (highlightsEnabled && !isLoadingNav) {
navModel.children!.push({
...dsPermissions,
url: dsPermissions.url + '/upgrade',
tabSuffix: () => ProBadge({ experimentId: permissionsExperimentId }),
});
}
const analyticsExperimentId = 'feature-highlights-data-source-insights-badge';
const analytics: NavModelItem = {
active: false,
icon: 'info-circle',
id: `datasource-insights-${dataSource.uid}`,
text: 'Insights',
url: `datasources/edit/${dataSource.uid}/insights`,
};
if (highlightTrial() && !isLoadingNav) {
analytics.tabSuffix = () => ProBadge({ experimentId: analyticsExperimentId, eventVariant: 'trial' });
}
if (featureEnabled('analytics')) {
if (contextSrv.hasPermission(AccessControlAction.DataSourcesInsightsRead)) {
navModel.children!.push(analytics);
}
} else if (highlightsEnabled && !isLoadingNav) {
navModel.children!.push({
...analytics,
url: analytics.url + '/upgrade',
tabSuffix: () => ProBadge({ experimentId: analyticsExperimentId }),
});
}
const cachingExperimentId = 'feature-highlights-query-caching-badge';
const caching: NavModelItem = {
active: false,
icon: 'database',
id: `datasource-cache-${dataSource.uid}`,
text: 'Cache',
url: `datasources/edit/${dataSource.uid}/cache`,
hideFromTabs: !pluginMeta.isBackend || !config.caching.enabled,
};
if (highlightTrial() && !isLoadingNav) {
caching.tabSuffix = () => ProBadge({ experimentId: cachingExperimentId, eventVariant: 'trial' });
}
if (featureEnabled('caching')) {
if (contextSrv.hasPermissionInMetadata(AccessControlAction.DataSourcesCachingRead, dataSource)) {
navModel.children!.push(caching);
}
} else if (highlightsEnabled && !isLoadingNav) {
navModel.children!.push({
...caching,
url: caching.url + '/upgrade',
tabSuffix: () => ProBadge({ experimentId: cachingExperimentId }),
});
}
return navModel;
}
export function getDataSourceNav(main: NavModelItem, pageName: string): NavModel {
let node: NavModelItem = { text: '' };
// find active page
for (const child of main.children!) {
if (child.id!.indexOf(pageName) > 0) {
child.active = true;
node = child;
break;
}
}
return {
main: main,
node: node!,
};
}
export function getDataSourceLoadingNav(pageName: string): NavModel {
const main = buildNavModel(
{
access: '',
basicAuth: false,
basicAuthUser: '',
withCredentials: false,
database: '',
id: 1,
uid: 'x',
isDefault: false,
jsonData: { authType: 'credentials', defaultRegion: 'eu-west-2' },
name: 'Loading',
orgId: 1,
readOnly: false,
type: loadingDSType,
typeName: loadingDSType,
typeLogoUrl: 'public/img/icn-datasource.svg',
url: '',
user: '',
secureJsonFields: {},
},
{
meta: {
id: '1',
type: PluginType.datasource,
name: '',
info: {
author: {
name: '',
url: '',
},
description: '',
links: [{ name: '', url: '' }],
logos: {
large: '',
small: '',
},
screenshots: [],
updated: '',
version: '',
},
includes: [],
module: '',
baseUrl: '',
},
} as any
);
return getDataSourceNav(main, pageName);
}
function hasDashboards(includes: PluginInclude[]): boolean {
return (
includes.find((include) => {
return include.type === 'dashboard';
}) !== undefined
);
}