mirror of https://github.com/grafana/grafana.git
Alerting: Fix permission checks for the Import to GMA (#109950)
Fix permission checks for the Import rules buttons and import to GMA page
This commit is contained in:
parent
6b67b394fd
commit
6a050ff551
|
|
@ -226,7 +226,10 @@ export function getAlertingRoutes(cfg = config): RouteDescriptor[] {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/alerting/import-datasource-managed-rules',
|
path: '/alerting/import-datasource-managed-rules',
|
||||||
roles: () => ['Admin'],
|
roles: evaluateAccess([
|
||||||
|
AccessControlAction.AlertingRuleCreate,
|
||||||
|
AccessControlAction.AlertingProvisioningSetStatus,
|
||||||
|
]),
|
||||||
component: config.featureToggles.alertingMigrationUI
|
component: config.featureToggles.alertingMigrationUI
|
||||||
? importAlertingComponent(
|
? importAlertingComponent(
|
||||||
() =>
|
() =>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import { GrafanaTheme2, urlUtil } from '@grafana/data';
|
||||||
import { Trans, t } from '@grafana/i18n';
|
import { Trans, t } from '@grafana/i18n';
|
||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
import { Badge, LinkButton, LoadingPlaceholder, Pagination, Spinner, Stack, Text, useStyles2 } from '@grafana/ui';
|
import { Badge, LinkButton, LoadingPlaceholder, Pagination, Spinner, Stack, Text, useStyles2 } from '@grafana/ui';
|
||||||
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
|
import { AccessControlAction } from 'app/types/accessControl';
|
||||||
import { CombinedRuleNamespace } from 'app/types/unified-alerting';
|
import { CombinedRuleNamespace } from 'app/types/unified-alerting';
|
||||||
|
|
||||||
import { DEFAULT_PER_PAGE_PAGINATION } from '../../../../../core/constants';
|
import { DEFAULT_PER_PAGE_PAGINATION } from '../../../../../core/constants';
|
||||||
|
|
@ -14,7 +16,6 @@ import { usePagination } from '../../hooks/usePagination';
|
||||||
import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector';
|
import { useUnifiedAlertingSelector } from '../../hooks/useUnifiedAlertingSelector';
|
||||||
import { getPaginationStyles } from '../../styles/pagination';
|
import { getPaginationStyles } from '../../styles/pagination';
|
||||||
import { getRulesDataSources, getRulesSourceUid } from '../../utils/datasource';
|
import { getRulesDataSources, getRulesSourceUid } from '../../utils/datasource';
|
||||||
import { isAdmin } from '../../utils/misc';
|
|
||||||
import { isAsyncRequestStatePending } from '../../utils/redux';
|
import { isAsyncRequestStatePending } from '../../utils/redux';
|
||||||
import { createRelativeUrl } from '../../utils/url';
|
import { createRelativeUrl } from '../../utils/url';
|
||||||
|
|
||||||
|
|
@ -49,7 +50,11 @@ export const CloudRules = ({ namespaces, expandAll }: Props) => {
|
||||||
DEFAULT_PER_PAGE_PAGINATION
|
DEFAULT_PER_PAGE_PAGINATION
|
||||||
);
|
);
|
||||||
|
|
||||||
const canMigrateToGMA = hasDataSourcesConfigured && isAdmin() && config.featureToggles.alertingMigrationUI;
|
const canMigrateToGMA =
|
||||||
|
hasDataSourcesConfigured &&
|
||||||
|
config.featureToggles.alertingMigrationUI &&
|
||||||
|
contextSrv.hasPermission(AccessControlAction.AlertingRuleCreate) &&
|
||||||
|
contextSrv.hasPermission(AccessControlAction.AlertingProvisioningSetStatus);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.wrapper}>
|
<section className={styles.wrapper}>
|
||||||
|
|
|
||||||
|
|
@ -255,9 +255,12 @@ describe('RuleListActions', () => {
|
||||||
describe('Import Alert Rules', () => {
|
describe('Import Alert Rules', () => {
|
||||||
testWithFeatureToggles(['alertingMigrationUI']);
|
testWithFeatureToggles(['alertingMigrationUI']);
|
||||||
|
|
||||||
it('should show "Import alert rules" option when user is admin and feature toggle is enabled', async () => {
|
it('should show "Import alert rules" option when user has required permissions and feature toggle is enabled', async () => {
|
||||||
grantUserRole(OrgRole.Admin);
|
grantUserPermissions([
|
||||||
grantUserPermissions([AccessControlAction.AlertingRuleRead]);
|
AccessControlAction.AlertingRuleRead,
|
||||||
|
AccessControlAction.AlertingRuleCreate,
|
||||||
|
AccessControlAction.AlertingProvisioningSetStatus,
|
||||||
|
]);
|
||||||
|
|
||||||
const { user } = render(<RuleListActions />);
|
const { user } = render(<RuleListActions />);
|
||||||
|
|
||||||
|
|
@ -267,8 +270,8 @@ describe('RuleListActions', () => {
|
||||||
expect(ui.menuOptions.importAlertRules.query(menu)).toBeInTheDocument();
|
expect(ui.menuOptions.importAlertRules.query(menu)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show "Import alert rules" option when user is not admin', async () => {
|
it('should not show "Import alert rules" option when user lacks required permissions', async () => {
|
||||||
// Keep default Viewer role
|
// Keep default Viewer role and only read permissions
|
||||||
grantUserPermissions([AccessControlAction.AlertingRuleRead]);
|
grantUserPermissions([AccessControlAction.AlertingRuleRead]);
|
||||||
|
|
||||||
const { user } = render(<RuleListActions />);
|
const { user } = render(<RuleListActions />);
|
||||||
|
|
@ -280,8 +283,11 @@ describe('RuleListActions', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have correct URL for "Import alert rules" menu item', async () => {
|
it('should have correct URL for "Import alert rules" menu item', async () => {
|
||||||
grantUserRole(OrgRole.Admin);
|
grantUserPermissions([
|
||||||
grantUserPermissions([AccessControlAction.AlertingRuleRead]);
|
AccessControlAction.AlertingRuleRead,
|
||||||
|
AccessControlAction.AlertingRuleCreate,
|
||||||
|
AccessControlAction.AlertingProvisioningSetStatus,
|
||||||
|
]);
|
||||||
|
|
||||||
const { user } = render(<RuleListActions />);
|
const { user } = render(<RuleListActions />);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import { useToggle } from 'react-use';
|
||||||
import { Trans, t } from '@grafana/i18n';
|
import { Trans, t } from '@grafana/i18n';
|
||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
import { Button, Dropdown, Icon, LinkButton, Menu, Stack } from '@grafana/ui';
|
import { Button, Dropdown, Icon, LinkButton, Menu, Stack } from '@grafana/ui';
|
||||||
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
|
import { AccessControlAction } from 'app/types/accessControl';
|
||||||
|
|
||||||
import { AlertingPageWrapper } from '../components/AlertingPageWrapper';
|
import { AlertingPageWrapper } from '../components/AlertingPageWrapper';
|
||||||
import { GrafanaRulesExporter } from '../components/export/GrafanaRulesExporter';
|
import { GrafanaRulesExporter } from '../components/export/GrafanaRulesExporter';
|
||||||
|
|
@ -11,7 +13,6 @@ import { useListViewMode } from '../components/rules/Filter/RulesViewModeSelecto
|
||||||
import { AIAlertRuleButtonComponent } from '../enterprise-components/AI/AIGenAlertRuleButton/addAIAlertRuleButton';
|
import { AIAlertRuleButtonComponent } from '../enterprise-components/AI/AIGenAlertRuleButton/addAIAlertRuleButton';
|
||||||
import { AlertingAction, useAlertingAbility } from '../hooks/useAbilities';
|
import { AlertingAction, useAlertingAbility } from '../hooks/useAbilities';
|
||||||
import { useRulesFilter } from '../hooks/useFilteredRules';
|
import { useRulesFilter } from '../hooks/useFilteredRules';
|
||||||
import { isAdmin } from '../utils/misc';
|
|
||||||
|
|
||||||
import { FilterView } from './FilterView';
|
import { FilterView } from './FilterView';
|
||||||
import { GroupedView } from './GroupedView';
|
import { GroupedView } from './GroupedView';
|
||||||
|
|
@ -44,7 +45,11 @@ export function RuleListActions() {
|
||||||
const canExportRules = exportRulesSupported && exportRulesAllowed;
|
const canExportRules = exportRulesSupported && exportRulesAllowed;
|
||||||
|
|
||||||
const canCreateRules = canCreateGrafanaRules || canCreateCloudRules;
|
const canCreateRules = canCreateGrafanaRules || canCreateCloudRules;
|
||||||
const canImportRulesToGMA = isAdmin() && config.featureToggles.alertingMigrationUI;
|
// Align import UI permission with convert endpoint requirements: rule create + provisioning set status
|
||||||
|
const canImportRulesToGMA =
|
||||||
|
config.featureToggles.alertingMigrationUI &&
|
||||||
|
contextSrv.hasPermission(AccessControlAction.AlertingRuleCreate) &&
|
||||||
|
contextSrv.hasPermission(AccessControlAction.AlertingProvisioningSetStatus);
|
||||||
|
|
||||||
const [showExportDrawer, toggleShowExportDrawer] = useToggle(false);
|
const [showExportDrawer, toggleShowExportDrawer] = useToggle(false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,11 @@ export enum AccessControlAction {
|
||||||
AlertingProvisioningReadSecrets = 'alert.provisioning.secrets:read',
|
AlertingProvisioningReadSecrets = 'alert.provisioning.secrets:read',
|
||||||
AlertingProvisioningRead = 'alert.provisioning:read',
|
AlertingProvisioningRead = 'alert.provisioning:read',
|
||||||
AlertingProvisioningWrite = 'alert.provisioning:write',
|
AlertingProvisioningWrite = 'alert.provisioning:write',
|
||||||
|
AlertingRulesProvisioningRead = 'alert.rules.provisioning:read',
|
||||||
|
AlertingRulesProvisioningWrite = 'alert.rules.provisioning:write',
|
||||||
|
AlertingNotificationsProvisioningRead = 'alert.notifications.provisioning:read',
|
||||||
|
AlertingNotificationsProvisioningWrite = 'alert.notifications.provisioning:write',
|
||||||
|
AlertingProvisioningSetStatus = 'alert.provisioning.provenance:write',
|
||||||
|
|
||||||
// Alerting receivers actions
|
// Alerting receivers actions
|
||||||
AlertingReceiversPermissionsRead = 'receivers.permissions:read',
|
AlertingReceiversPermissionsRead = 'receivers.permissions:read',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue