2023-01-09 11:54:33 +03:00
|
|
|
import React, { useEffect, useState } from 'react';
|
2022-04-22 14:33:13 +01:00
|
|
|
|
2020-04-15 16:49:20 +02:00
|
|
|
import { OrgRole } from '@grafana/data';
|
2022-04-22 14:33:13 +01:00
|
|
|
import { Button, ConfirmModal } from '@grafana/ui';
|
2022-01-17 18:04:54 +03:00
|
|
|
import { UserRolePicker } from 'app/core/components/RolePicker/UserRolePicker';
|
2022-08-18 12:25:37 +02:00
|
|
|
import { fetchRoleOptions } from 'app/core/components/RolePicker/api';
|
2022-11-29 15:20:28 +01:00
|
|
|
import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
|
2023-03-22 17:41:59 +00:00
|
|
|
import config from 'app/core/config';
|
2022-04-22 14:33:13 +01:00
|
|
|
import { contextSrv } from 'app/core/core';
|
|
|
|
|
import { AccessControlAction, OrgUser, Role } from 'app/types';
|
|
|
|
|
|
|
|
|
|
import { OrgRolePicker } from '../admin/OrgRolePicker';
|
2018-10-03 09:43:10 +02:00
|
|
|
|
|
|
|
|
export interface Props {
|
|
|
|
|
users: OrgUser[];
|
2021-11-19 09:50:01 +01:00
|
|
|
orgId?: number;
|
2020-04-15 16:49:20 +02:00
|
|
|
onRoleChange: (role: OrgRole, user: OrgUser) => void;
|
2018-10-03 09:43:10 +02:00
|
|
|
onRemoveUser: (user: OrgUser) => void;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-09 11:54:33 +03:00
|
|
|
export const UsersTable = ({ users, orgId, onRoleChange, onRemoveUser }: Props) => {
|
2022-01-11 07:27:48 -08:00
|
|
|
const [userToRemove, setUserToRemove] = useState<OrgUser | null>(null);
|
2021-11-17 18:22:40 +03:00
|
|
|
const [roleOptions, setRoleOptions] = useState<Role[]>([]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
async function fetchOptions() {
|
|
|
|
|
try {
|
2022-01-19 16:15:52 +03:00
|
|
|
if (contextSrv.hasPermission(AccessControlAction.ActionRolesList)) {
|
|
|
|
|
let options = await fetchRoleOptions(orgId);
|
|
|
|
|
setRoleOptions(options);
|
|
|
|
|
}
|
2021-11-17 18:22:40 +03:00
|
|
|
} catch (e) {
|
|
|
|
|
console.error('Error loading options');
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-02-03 16:27:53 +01:00
|
|
|
if (contextSrv.licensedAccessControlEnabled()) {
|
2021-11-17 18:22:40 +03:00
|
|
|
fetchOptions();
|
|
|
|
|
}
|
2021-11-19 09:50:01 +01:00
|
|
|
}, [orgId]);
|
2021-11-17 18:22:40 +03:00
|
|
|
|
2018-10-03 09:43:10 +02:00
|
|
|
return (
|
2022-01-11 07:27:48 -08:00
|
|
|
<>
|
|
|
|
|
<table className="filter-table form-inline">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th />
|
|
|
|
|
<th>Login</th>
|
|
|
|
|
<th>Email</th>
|
|
|
|
|
<th>Name</th>
|
|
|
|
|
<th>Seen</th>
|
|
|
|
|
<th>Role</th>
|
|
|
|
|
<th style={{ width: '34px' }} />
|
2023-03-22 17:41:59 +00:00
|
|
|
<th>Origin</th>
|
2022-11-29 15:20:28 +01:00
|
|
|
<th></th>
|
2022-01-11 07:27:48 -08:00
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
{users.map((user, index) => {
|
2023-03-22 17:41:59 +00:00
|
|
|
let basicRoleDisabled = !contextSrv.hasPermissionInMetadata(AccessControlAction.OrgUsersWrite, user);
|
|
|
|
|
if (config.featureToggles.onlyExternalOrgRoleSync) {
|
|
|
|
|
const isUserSynced = user?.isExternallySynced;
|
|
|
|
|
basicRoleDisabled = isUserSynced || basicRoleDisabled;
|
|
|
|
|
}
|
2022-01-11 07:27:48 -08:00
|
|
|
return (
|
|
|
|
|
<tr key={`${user.userId}-${index}`}>
|
|
|
|
|
<td className="width-2 text-center">
|
|
|
|
|
<img className="filter-table__avatar" src={user.avatarUrl} alt="User avatar" />
|
|
|
|
|
</td>
|
|
|
|
|
<td className="max-width-6">
|
|
|
|
|
<span className="ellipsis" title={user.login}>
|
|
|
|
|
{user.login}
|
|
|
|
|
</span>
|
|
|
|
|
</td>
|
2020-04-15 16:49:20 +02:00
|
|
|
|
2022-01-11 07:27:48 -08:00
|
|
|
<td className="max-width-5">
|
|
|
|
|
<span className="ellipsis" title={user.email}>
|
|
|
|
|
{user.email}
|
|
|
|
|
</span>
|
|
|
|
|
</td>
|
|
|
|
|
<td className="max-width-5">
|
|
|
|
|
<span className="ellipsis" title={user.name}>
|
|
|
|
|
{user.name}
|
|
|
|
|
</span>
|
|
|
|
|
</td>
|
|
|
|
|
<td className="width-1">{user.lastSeenAtAge}</td>
|
2021-04-22 13:19:41 +03:00
|
|
|
|
2022-01-11 07:27:48 -08:00
|
|
|
<td className="width-8">
|
2022-02-03 16:27:53 +01:00
|
|
|
{contextSrv.licensedAccessControlEnabled() ? (
|
2022-01-11 07:27:48 -08:00
|
|
|
<UserRolePicker
|
|
|
|
|
userId={user.userId}
|
|
|
|
|
orgId={orgId}
|
2022-02-04 14:54:42 +01:00
|
|
|
roleOptions={roleOptions}
|
2022-08-18 12:25:37 +02:00
|
|
|
basicRole={user.role}
|
|
|
|
|
onBasicRoleChange={(newRole) => onRoleChange(newRole, user)}
|
2023-03-22 17:41:59 +00:00
|
|
|
basicRoleDisabled={basicRoleDisabled}
|
2022-01-11 07:27:48 -08:00
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
<OrgRolePicker
|
|
|
|
|
aria-label="Role"
|
|
|
|
|
value={user.role}
|
2023-03-22 17:41:59 +00:00
|
|
|
disabled={basicRoleDisabled}
|
2022-01-11 07:27:48 -08:00
|
|
|
onChange={(newRole) => onRoleChange(newRole, user)}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2021-04-22 13:19:41 +03:00
|
|
|
</td>
|
2022-01-11 07:27:48 -08:00
|
|
|
|
2022-08-15 10:58:58 +02:00
|
|
|
<td className="width-1 text-center">
|
|
|
|
|
{user.isDisabled && <span className="label label-tag label-tag--gray">Disabled</span>}
|
|
|
|
|
</td>
|
|
|
|
|
|
2022-11-29 15:20:28 +01:00
|
|
|
<td className="width-1">
|
|
|
|
|
{Array.isArray(user.authLabels) && user.authLabels.length > 0 && (
|
|
|
|
|
<TagBadge label={user.authLabels[0]} removeIcon={false} count={0} />
|
|
|
|
|
)}
|
|
|
|
|
</td>
|
|
|
|
|
|
2022-01-11 07:27:48 -08:00
|
|
|
{contextSrv.hasPermissionInMetadata(AccessControlAction.OrgUsersRemove, user) && (
|
2022-08-15 10:58:58 +02:00
|
|
|
<td className="text-right">
|
2022-01-11 07:27:48 -08:00
|
|
|
<Button
|
|
|
|
|
size="sm"
|
|
|
|
|
variant="destructive"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setUserToRemove(user);
|
|
|
|
|
}}
|
|
|
|
|
icon="times"
|
|
|
|
|
aria-label="Delete user"
|
|
|
|
|
/>
|
|
|
|
|
</td>
|
|
|
|
|
)}
|
|
|
|
|
</tr>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
{Boolean(userToRemove) && (
|
|
|
|
|
<ConfirmModal
|
|
|
|
|
body={`Are you sure you want to delete user ${userToRemove?.login}?`}
|
|
|
|
|
confirmText="Delete"
|
|
|
|
|
title="Delete"
|
|
|
|
|
onDismiss={() => {
|
|
|
|
|
setUserToRemove(null);
|
|
|
|
|
}}
|
|
|
|
|
isOpen={true}
|
|
|
|
|
onConfirm={() => {
|
|
|
|
|
if (!userToRemove) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
onRemoveUser(userToRemove);
|
|
|
|
|
setUserToRemove(null);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</>
|
2018-10-03 09:43:10 +02:00
|
|
|
);
|
|
|
|
|
};
|