Disable external user's change role in admin (#39172)

* Disable external user's change role in admin

* Missing part of the tooltip text

* Disable change button with the tooltip instead dropdown

* Missing refactor

* Apply suggestion
This commit is contained in:
Selene 2021-09-21 17:47:35 +02:00 committed by GitHub
parent 1910d85ae0
commit b31316753a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 14 deletions

View File

@ -129,6 +129,7 @@ export class UserAdminPage extends PureComponent<Props> {
{orgs && (
<UserOrgs
orgs={orgs}
isExternalUser={user?.isExternal}
onOrgRemove={this.onOrgRemove}
onOrgRoleChange={this.onOrgRoleChange}
onOrgAdd={this.onOrgAdd}

View File

@ -1,7 +1,19 @@
import React, { PureComponent } from 'react';
import React, { PureComponent, ReactElement } from 'react';
import { css, cx } from '@emotion/css';
import { Button, ConfirmButton, Field, HorizontalGroup, Modal, stylesFactory, Themeable, withTheme } from '@grafana/ui';
import { GrafanaTheme } from '@grafana/data';
import {
Button,
ConfirmButton,
Field,
HorizontalGroup,
Icon,
Modal,
stylesFactory,
Themeable,
Tooltip,
useStyles2,
withTheme,
} from '@grafana/ui';
import { GrafanaTheme, GrafanaTheme2 } from '@grafana/data';
import { AccessControlAction, Organization, OrgRole, UserOrg } from 'app/types';
import { OrgPicker, OrgSelectItem } from 'app/core/components/Select/OrgPicker';
import { OrgRolePicker } from './OrgRolePicker';
@ -9,6 +21,7 @@ import { contextSrv } from 'app/core/core';
interface Props {
orgs: UserOrg[];
isExternalUser?: boolean;
onOrgRemove: (orgId: number) => void;
onOrgRoleChange: (orgId: number, newRole: OrgRole) => void;
@ -29,13 +42,12 @@ export class UserOrgs extends PureComponent<Props, State> {
};
render() {
const { orgs, onOrgRoleChange, onOrgRemove, onOrgAdd } = this.props;
const { orgs, isExternalUser, onOrgRoleChange, onOrgRemove, onOrgAdd } = this.props;
const { showAddOrgModal } = this.state;
const addToOrgContainerClass = css`
margin-top: 0.8rem;
`;
const canAddToOrg = contextSrv.hasPermission(AccessControlAction.OrgUsersAdd);
return (
<>
<h3 className="page-heading">Organizations</h3>
@ -46,6 +58,7 @@ export class UserOrgs extends PureComponent<Props, State> {
{orgs.map((org, index) => (
<OrgRow
key={`${org.orgId}-${index}`}
isExternalUser={isExternalUser}
org={org}
onOrgRoleChange={onOrgRoleChange}
onOrgRemove={onOrgRemove}
@ -78,11 +91,21 @@ const getOrgRowStyles = stylesFactory((theme: GrafanaTheme) => {
label: css`
font-weight: 500;
`,
disabledTooltip: css`
display: flex;
`,
tooltipItem: css`
margin-left: 5px;
`,
tooltipItemLink: css`
color: ${theme.palette.blue95};
`,
};
});
interface OrgRowProps extends Themeable {
org: UserOrg;
isExternalUser?: boolean;
onOrgRemove: (orgId: number) => void;
onOrgRoleChange: (orgId: number, newRole: OrgRole) => void;
}
@ -121,7 +144,7 @@ class UnThemedOrgRow extends PureComponent<OrgRowProps, OrgRowState> {
};
render() {
const { org, theme } = this.props;
const { org, isExternalUser, theme } = this.props;
const { currentRole, isChangingRole } = this.state;
const styles = getOrgRowStyles(theme);
const labelClass = cx('width-16', styles.label);
@ -141,14 +164,12 @@ class UnThemedOrgRow extends PureComponent<OrgRowProps, OrgRowState> {
<td colSpan={1}>
<div className="pull-right">
{canChangeRole && (
<ConfirmButton
confirmText="Save"
onClick={this.onChangeRoleClick}
onCancel={this.onCancelClick}
onConfirm={this.onOrgRoleSave}
>
Change role
</ConfirmButton>
<ChangeOrgButton
isExternalUser={isExternalUser}
onChangeRoleClick={this.onChangeRoleClick}
onCancelClick={this.onCancelClick}
onOrgRoleSave={this.onOrgRoleSave}
/>
)}
</div>
</td>
@ -255,3 +276,63 @@ export class AddToOrgModal extends PureComponent<AddToOrgModalProps, AddToOrgMod
);
}
}
interface ChangeOrgButtonProps {
isExternalUser?: boolean;
onChangeRoleClick: () => void;
onCancelClick: () => void;
onOrgRoleSave: () => void;
}
const getChangeOrgButtonTheme = (theme: GrafanaTheme2) => ({
disabledTooltip: css`
display: flex;
`,
tooltipItemLink: css`
color: ${theme.v1.palette.blue95};
`,
});
export function ChangeOrgButton({
onChangeRoleClick,
isExternalUser,
onOrgRoleSave,
onCancelClick,
}: ChangeOrgButtonProps): ReactElement {
const styles = useStyles2(getChangeOrgButtonTheme);
return (
<div className={styles.disabledTooltip}>
<ConfirmButton
confirmText="Save"
onClick={onChangeRoleClick}
onCancel={onCancelClick}
onConfirm={onOrgRoleSave}
disabled={isExternalUser}
>
Change role
</ConfirmButton>
{isExternalUser && (
<Tooltip
placement="right-end"
content={
<div>
This user&apos;s role is not editable because it is synchronized from your auth provider. Refer to
the&nbsp;
<a
className={styles.tooltipItemLink}
href={'https://grafana.com/docs/grafana/latest/auth'}
rel="noreferrer"
target="_blank"
>
Grafana authentication docs
</a>
&nbsp;for details.
</div>
}
>
<Icon name="question-circle" />
</Tooltip>
)}
</div>
);
}