AccessControl: add one-dimensional permissions to datasources (#38070)

* AccessControl: add one-dimensional permissions to datasources in the backend

* AccessControl: add one-dimensional permissions to datasources in the frontend (#38080)

Co-authored-by: Hugo Häggmark <hugo.haggmark@grafana.com>
This commit is contained in:
Gabriel MABILLE
2021-09-01 15:18:17 +02:00
committed by GitHub
parent 4e8ab0512c
commit 9f29241a0c
19 changed files with 506 additions and 40 deletions

View File

@@ -2,6 +2,14 @@ import React from 'react';
import { shallow } from 'enzyme';
import ButtonRow, { Props } from './ButtonRow';
jest.mock('app/core/core', () => {
return {
contextSrv: {
hasPermission: () => true,
},
};
});
const setup = (propOverrides?: object) => {
const props: Props = {
isReadOnly: true,

View File

@@ -4,6 +4,9 @@ import { selectors } from '@grafana/e2e-selectors';
import config from 'app/core/config';
import { Button, LinkButton } from '@grafana/ui';
import { AccessControlAction } from 'app/types/';
import { contextSrv } from 'app/core/core';
export interface Props {
exploreUrl: string;
isReadOnly: boolean;
@@ -13,35 +16,39 @@ export interface Props {
}
const ButtonRow: FC<Props> = ({ isReadOnly, onDelete, onSubmit, onTest, exploreUrl }) => {
const canEditDataSources = !isReadOnly && contextSrv.hasPermission(AccessControlAction.DataSourcesWrite);
const canDeleteDataSources = !isReadOnly && contextSrv.hasPermission(AccessControlAction.DataSourcesDelete);
const canExploreDataSources = contextSrv.hasPermission(AccessControlAction.DataSourcesExplore);
return (
<div className="gf-form-button-row">
<LinkButton variant="secondary" fill="solid" href={`${config.appSubUrl}/datasources`}>
Back
</LinkButton>
<LinkButton variant="secondary" fill="solid" href={exploreUrl}>
<LinkButton variant="secondary" fill="solid" href={exploreUrl} disabled={!canExploreDataSources}>
Explore
</LinkButton>
<Button
type="button"
variant="destructive"
disabled={isReadOnly}
disabled={!canDeleteDataSources}
onClick={onDelete}
aria-label={selectors.pages.DataSource.delete}
>
Delete
</Button>
{!isReadOnly && (
{canEditDataSources && (
<Button
type="submit"
variant="primary"
disabled={isReadOnly}
disabled={!canEditDataSources}
onClick={(event) => onSubmit(event)}
aria-label={selectors.pages.DataSource.saveAndTest}
>
Save &amp; test
</Button>
)}
{isReadOnly && (
{!canEditDataSources && (
<Button type="submit" variant="primary" onClick={onTest}>
Test
</Button>

View File

@@ -9,6 +9,14 @@ import { screen, render } from '@testing-library/react';
import { selectors } from '@grafana/e2e-selectors';
import { PluginState } from '@grafana/data';
jest.mock('app/core/core', () => {
return {
contextSrv: {
hasPermission: () => true,
},
};
});
const getMockNode = () => ({
text: 'text',
subTitle: 'subtitle',

View File

@@ -7,6 +7,8 @@ import BasicSettings from './BasicSettings';
import ButtonRow from './ButtonRow';
// Services & Utils
import appEvents from 'app/core/app_events';
import { contextSrv } from 'app/core/core';
// Actions & selectors
import { getDataSource, getDataSourceMeta } from '../state/selectors';
import {
@@ -19,7 +21,7 @@ import {
import { getNavModel } from 'app/core/selectors/navModel';
// Types
import { StoreState } from 'app/types/';
import { StoreState, AccessControlAction } from 'app/types/';
import { DataSourceSettings, urlUtil } from '@grafana/data';
import { Alert, Button, LinkButton } from '@grafana/ui';
import { getDataSourceLoadingNav, buildNavModel, getDataSourceNav } from '../state/navModel';
@@ -140,6 +142,14 @@ export class DataSourceSettingsPage extends PureComponent<Props> {
);
}
renderMissingEditRightsMessage() {
return (
<Alert severity="info" title="Missing rights">
You are not allowed to modify this data source. Please contact your server admin to update this data source.
</Alert>
);
}
testDataSource() {
const { dataSource, testDataSource } = this.props;
testDataSource(dataSource.name);
@@ -228,9 +238,11 @@ export class DataSourceSettingsPage extends PureComponent<Props> {
renderSettings() {
const { dataSourceMeta, setDataSourceName, setIsDefault, dataSource, plugin, testingStatus } = this.props;
const canEditDataSources = contextSrv.hasPermission(AccessControlAction.DataSourcesWrite);
return (
<form onSubmit={this.onSubmit}>
{!canEditDataSources && this.renderMissingEditRightsMessage()}
{this.isReadOnly() && this.renderIsReadOnlyMessage()}
{dataSourceMeta.state && (
<div className="gf-form">

View File

@@ -12,6 +12,7 @@ exports[`Render should render component 1`] = `
Back
</LinkButton>
<LinkButton
disabled={false}
fill="solid"
href="/explore"
variant="secondary"
@@ -49,6 +50,7 @@ exports[`Render should render with buttons enabled 1`] = `
Back
</LinkButton>
<LinkButton
disabled={false}
fill="solid"
href="/explore"
variant="secondary"