mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Service Accounts: Fix issue in UserTable and ServiceAccountsTable (#43865)
* fix issue where ServiceAccountsTable rendere delete modal for every item in list Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
This commit is contained in:
parent
1966eba796
commit
e2de1c1ec4
@ -45,7 +45,7 @@ export class ServiceAccountsListPage extends PureComponent<Props, State> {
|
|||||||
<ServiceAccountsTable
|
<ServiceAccountsTable
|
||||||
serviceAccounts={paginatedServiceAccounts}
|
serviceAccounts={paginatedServiceAccounts}
|
||||||
onRoleChange={(role, serviceAccount) => this.onRoleChange(role, serviceAccount)}
|
onRoleChange={(role, serviceAccount) => this.onRoleChange(role, serviceAccount)}
|
||||||
onRemoveServiceaccount={(serviceAccount) => this.props.removeServiceAccount(serviceAccount.serviceAccountId)}
|
onRemoveServiceAccount={(serviceAccount) => this.props.removeServiceAccount(serviceAccount.serviceAccountId)}
|
||||||
/>
|
/>
|
||||||
<HorizontalGroup justify="flex-end">
|
<HorizontalGroup justify="flex-end">
|
||||||
<Pagination
|
<Pagination
|
||||||
|
@ -9,19 +9,20 @@ import { fetchBuiltinRoles, fetchRoleOptions, UserRolePicker } from 'app/core/co
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
serviceAccounts: OrgServiceAccount[];
|
serviceAccounts: OrgServiceAccount[];
|
||||||
orgId?: number;
|
orgId?: number;
|
||||||
onRoleChange: (role: OrgRole, serviceaccount: OrgServiceAccount) => void;
|
onRoleChange: (role: OrgRole, serviceAccount: OrgServiceAccount) => void;
|
||||||
onRemoveServiceaccount: (serviceaccount: OrgServiceAccount) => void;
|
onRemoveServiceAccount: (serviceAccount: OrgServiceAccount) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ServiceaccountsTable: FC<Props> = (props) => {
|
const ServiceAccountsTable: FC<Props> = (props) => {
|
||||||
const { serviceAccounts, orgId, onRoleChange, onRemoveServiceaccount: onRemoveserviceaccount } = props;
|
const { serviceAccounts, orgId, onRoleChange, onRemoveServiceAccount } = props;
|
||||||
const canUpdateRole = contextSrv.hasPermission(AccessControlAction.OrgUsersRoleUpdate);
|
const canUpdateRole = contextSrv.hasPermission(AccessControlAction.OrgUsersRoleUpdate);
|
||||||
const canRemoveFromOrg = contextSrv.hasPermission(AccessControlAction.OrgUsersRemove);
|
const canRemoveFromOrg = contextSrv.hasPermission(AccessControlAction.OrgUsersRemove);
|
||||||
const rolePickerDisabled = !canUpdateRole;
|
const rolePickerDisabled = !canUpdateRole;
|
||||||
|
|
||||||
const [showRemoveModal, setShowRemoveModal] = useState(false);
|
|
||||||
const [roleOptions, setRoleOptions] = useState<Role[]>([]);
|
const [roleOptions, setRoleOptions] = useState<Role[]>([]);
|
||||||
|
const [toRemove, setToRemove] = useState<OrgServiceAccount | null>(null);
|
||||||
const [builtinRoles, setBuiltinRoles] = useState<Record<string, Role[]>>({});
|
const [builtinRoles, setBuiltinRoles] = useState<Record<string, Role[]>>({});
|
||||||
|
const [showRemoveModal, setShowRemoveModal] = useState<boolean | string>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchOptions() {
|
async function fetchOptions() {
|
||||||
@ -43,91 +44,92 @@ const ServiceaccountsTable: FC<Props> = (props) => {
|
|||||||
const getBuiltinRoles = async () => builtinRoles;
|
const getBuiltinRoles = async () => builtinRoles;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<table className="filter-table form-inline">
|
<>
|
||||||
<thead>
|
<table className="filter-table form-inline">
|
||||||
<tr>
|
<thead>
|
||||||
<th />
|
<tr>
|
||||||
<th>Login</th>
|
<th />
|
||||||
<th>Email</th>
|
<th>Login</th>
|
||||||
<th>Name</th>
|
<th>Email</th>
|
||||||
<th>Seen</th>
|
<th>Name</th>
|
||||||
<th>Role</th>
|
<th>Seen</th>
|
||||||
<th style={{ width: '34px' }} />
|
<th>Role</th>
|
||||||
</tr>
|
<th style={{ width: '34px' }} />
|
||||||
</thead>
|
</tr>
|
||||||
<tbody>
|
</thead>
|
||||||
{serviceAccounts.map((serviceAccount, index) => {
|
<tbody>
|
||||||
return (
|
{serviceAccounts.map((serviceAccount, index) => {
|
||||||
<tr key={`${serviceAccount.serviceAccountId}-${index}`}>
|
return (
|
||||||
<td className="width-2 text-center">
|
<tr key={`${serviceAccount.serviceAccountId}-${index}`}>
|
||||||
<img className="filter-table__avatar" src={serviceAccount.avatarUrl} alt="serviceaccount avatar" />
|
<td className="width-2 text-center">
|
||||||
</td>
|
<img className="filter-table__avatar" src={serviceAccount.avatarUrl} alt="serviceaccount avatar" />
|
||||||
<td className="max-width-6">
|
|
||||||
<span className="ellipsis" title={serviceAccount.login}>
|
|
||||||
{serviceAccount.login}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td className="max-width-5">
|
|
||||||
<span className="ellipsis" title={serviceAccount.email}>
|
|
||||||
{serviceAccount.email}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td className="max-width-5">
|
|
||||||
<span className="ellipsis" title={serviceAccount.name}>
|
|
||||||
{serviceAccount.name}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td className="width-1">{serviceAccount.lastSeenAtAge}</td>
|
|
||||||
|
|
||||||
<td className="width-8">
|
|
||||||
{contextSrv.accessControlEnabled() ? (
|
|
||||||
<UserRolePicker
|
|
||||||
userId={serviceAccount.serviceAccountId}
|
|
||||||
orgId={orgId}
|
|
||||||
builtInRole={serviceAccount.role}
|
|
||||||
onBuiltinRoleChange={(newRole) => onRoleChange(newRole, serviceAccount)}
|
|
||||||
getRoleOptions={getRoleOptions}
|
|
||||||
getBuiltinRoles={getBuiltinRoles}
|
|
||||||
disabled={rolePickerDisabled}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<OrgRolePicker
|
|
||||||
aria-label="Role"
|
|
||||||
value={serviceAccount.role}
|
|
||||||
disabled={!canUpdateRole}
|
|
||||||
onChange={(newRole) => onRoleChange(newRole, serviceAccount)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{canRemoveFromOrg && (
|
|
||||||
<td>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="destructive"
|
|
||||||
onClick={() => setShowRemoveModal(Boolean(serviceAccount.login))}
|
|
||||||
icon="times"
|
|
||||||
aria-label="Delete serviceaccount"
|
|
||||||
/>
|
|
||||||
<ConfirmModal
|
|
||||||
body={`Are you sure you want to delete serviceaccount ${serviceAccount.login}?`}
|
|
||||||
confirmText="Delete"
|
|
||||||
title="Delete"
|
|
||||||
onDismiss={() => setShowRemoveModal(false)}
|
|
||||||
isOpen={Boolean(serviceAccount.login) === showRemoveModal}
|
|
||||||
onConfirm={() => {
|
|
||||||
onRemoveserviceaccount(serviceAccount);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</td>
|
</td>
|
||||||
)}
|
<td className="max-width-6">
|
||||||
</tr>
|
<span className="ellipsis" title={serviceAccount.login}>
|
||||||
);
|
{serviceAccount.login}
|
||||||
})}
|
</span>
|
||||||
</tbody>
|
</td>
|
||||||
</table>
|
|
||||||
|
<td className="max-width-5">
|
||||||
|
<span className="ellipsis" title={serviceAccount.email}>
|
||||||
|
{serviceAccount.email}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="max-width-5">
|
||||||
|
<span className="ellipsis" title={serviceAccount.name}>
|
||||||
|
{serviceAccount.name}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="width-1">{serviceAccount.lastSeenAtAge}</td>
|
||||||
|
|
||||||
|
<td className="width-8">
|
||||||
|
{contextSrv.accessControlEnabled() ? (
|
||||||
|
<UserRolePicker
|
||||||
|
userId={serviceAccount.serviceAccountId}
|
||||||
|
orgId={orgId}
|
||||||
|
builtInRole={serviceAccount.role}
|
||||||
|
onBuiltinRoleChange={(newRole) => onRoleChange(newRole, serviceAccount)}
|
||||||
|
getRoleOptions={getRoleOptions}
|
||||||
|
getBuiltinRoles={getBuiltinRoles}
|
||||||
|
disabled={rolePickerDisabled}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<OrgRolePicker
|
||||||
|
aria-label="Role"
|
||||||
|
value={serviceAccount.role}
|
||||||
|
disabled={!canUpdateRole}
|
||||||
|
onChange={(newRole) => onRoleChange(newRole, serviceAccount)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
{canRemoveFromOrg && (
|
||||||
|
<td>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="destructive"
|
||||||
|
onClick={() => setShowRemoveModal(serviceAccount.login)}
|
||||||
|
icon="times"
|
||||||
|
aria-label="Delete serviceaccount"
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{toRemove !== null && (
|
||||||
|
<ConfirmModal
|
||||||
|
body={`Are you sure you want to delete ${toRemove.login} service account?`}
|
||||||
|
confirmText="Delete"
|
||||||
|
title="Delete"
|
||||||
|
onDismiss={() => setToRemove(null)}
|
||||||
|
isOpen={toRemove.login === showRemoveModal}
|
||||||
|
onConfirm={() => onRemoveServiceAccount(toRemove)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ServiceaccountsTable;
|
export default ServiceAccountsTable;
|
||||||
|
Loading…
Reference in New Issue
Block a user