Files
grafana/public/app/features/alerting/unified/components/receivers/TemplatesTable.tsx
Nathan Rodman 49505b9a3b Alerting: fgac for notification policies and contact points (#46939)
* add FGAC actions for silences table

* redirect users without permissions

* add permissions checks to routes

* add fgac to notifications and contact points

* fgac for notification policies

* fix mute timing authorization

* use consistent naming for checking grafana alertmanager

* tests for fgac in contact points and notification policies

* bump up timeout on rule editor test

* use new permissions util

* break out route evaluation into util

* Remove test timeout

* Change permissions for the alert-notifiers endpoint

* Use signed in handler for alert-notifiers when unified alerting enabled

Co-authored-by: Konrad Lalik <konrad.lalik@grafana.com>
2022-04-06 18:24:33 +02:00

129 lines
4.9 KiB
TypeScript

import { ConfirmModal, useStyles2 } from '@grafana/ui';
import { AlertManagerCortexConfig } from 'app/plugins/datasource/alertmanager/types';
import React, { FC, Fragment, useMemo, useState } from 'react';
import { getAlertTableStyles } from '../../styles/table';
import { CollapseToggle } from '../CollapseToggle';
import { DetailsField } from '../DetailsField';
import { ActionIcon } from '../rules/ActionIcon';
import { ReceiversSection } from './ReceiversSection';
import { makeAMLink } from '../../utils/misc';
import { useDispatch } from 'react-redux';
import { deleteTemplateAction } from '../../state/actions';
import { contextSrv } from 'app/core/services/context_srv';
import { Authorize } from '../../components/Authorize';
import { getNotificationsPermissions } from '../../utils/access-control';
interface Props {
config: AlertManagerCortexConfig;
alertManagerName: string;
}
export const TemplatesTable: FC<Props> = ({ config, alertManagerName }) => {
const dispatch = useDispatch();
const [expandedTemplates, setExpandedTemplates] = useState<Record<string, boolean>>({});
const tableStyles = useStyles2(getAlertTableStyles);
const permissions = getNotificationsPermissions(alertManagerName);
const templateRows = useMemo(() => Object.entries(config.template_files), [config]);
const [templateToDelete, setTemplateToDelete] = useState<string>();
const deleteTemplate = () => {
if (templateToDelete) {
dispatch(deleteTemplateAction(templateToDelete, alertManagerName));
}
setTemplateToDelete(undefined);
};
return (
<ReceiversSection
title="Message templates"
description="Templates construct the messages that get sent to the contact points."
addButtonLabel="New template"
addButtonTo={makeAMLink('/alerting/notifications/templates/new', alertManagerName)}
showButton={contextSrv.hasPermission(permissions.create)}
>
<table className={tableStyles.table} data-testid="templates-table">
<colgroup>
<col className={tableStyles.colExpand} />
<col />
<col />
</colgroup>
<thead>
<tr>
<th></th>
<th>Template</th>
<Authorize actions={[permissions.update, permissions.delete]}>
<th>Actions</th>
</Authorize>
</tr>
</thead>
<tbody>
{!templateRows.length && (
<tr className={tableStyles.evenRow}>
<td colSpan={3}>No templates defined.</td>
</tr>
)}
{templateRows.map(([name, content], idx) => {
const isExpanded = !!expandedTemplates[name];
return (
<Fragment key={name}>
<tr key={name} className={idx % 2 === 0 ? tableStyles.evenRow : undefined}>
<td>
<CollapseToggle
isCollapsed={!expandedTemplates[name]}
onToggle={() => setExpandedTemplates({ ...expandedTemplates, [name]: !isExpanded })}
/>
</td>
<td>{name}</td>
<Authorize actions={[permissions.update, permissions.delete]}>
<td className={tableStyles.actionsCell}>
<Authorize actions={[permissions.update]}>
<ActionIcon
to={makeAMLink(
`/alerting/notifications/templates/${encodeURIComponent(name)}/edit`,
alertManagerName
)}
tooltip="edit template"
icon="pen"
/>
</Authorize>
<Authorize actions={[permissions.delete]}>
<ActionIcon
onClick={() => setTemplateToDelete(name)}
tooltip="delete template"
icon="trash-alt"
/>
</Authorize>
</td>
</Authorize>
</tr>
{isExpanded && (
<tr className={idx % 2 === 0 ? tableStyles.evenRow : undefined}>
<td></td>
<td colSpan={2}>
<DetailsField label="Description" horizontal={true}>
<pre>{content}</pre>
</DetailsField>
</td>
</tr>
)}
</Fragment>
);
})}
</tbody>
</table>
{!!templateToDelete && (
<ConfirmModal
isOpen={true}
title="Delete template"
body={`Are you sure you want to delete template "${templateToDelete}"?`}
confirmText="Yes, delete"
onConfirm={deleteTemplate}
onDismiss={() => setTemplateToDelete(undefined)}
/>
)}
</ReceiversSection>
);
};