Team LBAC: Show permissions warning (#80215)

* Permissions: Add team LBAC warnings

* Replace info with warning if present

* Keep info message

* Update warning message

* Translate permission warning

* Use box component

* Generate translation placeholder

* Use multiple messages

* Move LBAC warnings to enterprise
This commit is contained in:
Alexander Zobnin 2024-01-11 14:48:55 +03:00 committed by GitHub
parent cc5a573ce0
commit bb2156967d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 39 deletions

View File

@ -1,6 +1,8 @@
import { css } from '@emotion/css';
import React from 'react';
import { Button, Icon, Select, Tooltip } from '@grafana/ui';
import { GrafanaTheme2 } from '@grafana/data';
import { Box, Button, Icon, Select, Tooltip, useStyles2 } from '@grafana/ui';
import { ResourcePermission } from './types';
@ -12,42 +14,59 @@ interface Props {
onChange: (item: ResourcePermission, permission: string) => void;
}
export const PermissionListItem = ({ item, permissionLevels, canSet, onRemove, onChange }: Props) => (
<tr>
<td>{getAvatar(item)}</td>
<td>{getDescription(item)}</td>
<td>{item.isInherited && <em className="muted no-wrap">Inherited from folder</em>}</td>
<td>
<Select
disabled={!canSet || !item.isManaged}
onChange={(p) => onChange(item, p.value!)}
value={permissionLevels.find((p) => p === item.permission)}
options={permissionLevels.map((p) => ({ value: p, label: p }))}
/>
</td>
<td>
<Tooltip content={getPermissionInfo(item)}>
<Icon name="info-circle" />
</Tooltip>
</td>
<td>
{item.isManaged ? (
<Button
size="sm"
icon="times"
variant="destructive"
disabled={!canSet}
onClick={() => onRemove(item)}
aria-label={`Remove permission for ${getName(item)}`}
export const PermissionListItem = ({ item, permissionLevels, canSet, onRemove, onChange }: Props) => {
const styles = useStyles2(getStyles);
return (
<tr>
<td>{getAvatar(item)}</td>
<td>{getDescription(item)}</td>
<td>{item.isInherited && <em className="muted no-wrap">Inherited from folder</em>}</td>
<td>
<Select
disabled={!canSet || !item.isManaged}
onChange={(p) => onChange(item, p.value!)}
value={permissionLevels.find((p) => p === item.permission)}
options={permissionLevels.map((p) => ({ value: p, label: p }))}
/>
) : (
<Tooltip content={item.isInherited ? 'Inherited Permission' : 'Provisioned Permission'}>
<Button size="sm" icon="lock" />
</Tooltip>
)}
</td>
</tr>
);
</td>
<td>
{item.warning ? (
<Tooltip
content={
<>
<Box marginBottom={1}>{item.warning}</Box>
{getPermissionInfo(item)}
</>
}
>
<Icon name="exclamation-triangle" className={styles.warning} />
</Tooltip>
) : (
<Tooltip content={getPermissionInfo(item)}>
<Icon name="info-circle" />
</Tooltip>
)}
</td>
<td>
{item.isManaged ? (
<Button
size="sm"
icon="times"
variant="destructive"
disabled={!canSet}
onClick={() => onRemove(item)}
aria-label={`Remove permission for ${getName(item)}`}
/>
) : (
<Tooltip content={item.isInherited ? 'Inherited Permission' : 'Provisioned Permission'}>
<Button size="sm" icon="lock" />
</Tooltip>
)}
</td>
</tr>
);
};
const getAvatar = (item: ResourcePermission) => {
if (item.teamId) {
@ -80,3 +99,9 @@ const getDescription = (item: ResourcePermission) => {
};
const getPermissionInfo = (p: ResourcePermission) => `Actions: ${[...new Set(p.actions)].sort().join(' ')}`;
const getStyles = (theme: GrafanaTheme2) => ({
warning: css({
color: theme.colors.warning.main,
}),
});

View File

@ -37,6 +37,7 @@ export type Props = {
resource: string;
resourceId: ResourceId;
canSetPermissions: boolean;
getWarnings?: (items: ResourcePermission[]) => ResourcePermission[];
};
export const Permissions = ({
@ -47,15 +48,20 @@ export const Permissions = ({
resourceId,
canSetPermissions,
addPermissionTitle,
getWarnings,
}: Props) => {
const styles = useStyles2(getStyles);
const [isAdding, setIsAdding] = useState(false);
const [items, setItems] = useState<ResourcePermission[]>([]);
const [desc, setDesc] = useState(INITIAL_DESCRIPTION);
const fetchItems = useCallback(() => {
return getPermissions(resource, resourceId).then((r) => setItems(r));
}, [resource, resourceId]);
const fetchItems = useCallback(async () => {
let items = await getPermissions(resource, resourceId);
if (getWarnings) {
items = getWarnings(items);
}
setItems(items);
}, [resource, resourceId, getWarnings]);
useEffect(() => {
getDescription(resource).then((r) => {

View File

@ -13,6 +13,7 @@ export type ResourcePermission = {
builtInRole?: string;
actions: string[];
permission: string;
warning?: string;
};
export type SetPermission = {