mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2026-01-06 04:26:57 +00:00
* FIx UI : Only allow admins to create and update bot and user entities. #8467 * Add helper text for ADMIN_ONLY_ACTION
This commit is contained in:
parent
370288f1ff
commit
f3b9e2c59c
@ -16,6 +16,7 @@ import { ColumnsType } from 'antd/lib/table';
|
||||
import { AxiosError } from 'axios';
|
||||
import { isEmpty, lowerCase } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { getBots } from '../../axiosAPIs/botsAPI';
|
||||
import {
|
||||
@ -25,16 +26,15 @@ import {
|
||||
} from '../../constants/constants';
|
||||
import { BOTS_DOCS } from '../../constants/docs.constants';
|
||||
import {
|
||||
ADMIN_ONLY_ACTION,
|
||||
INGESTION_BOT_CANT_BE_DELETED,
|
||||
NO_PERMISSION_FOR_ACTION,
|
||||
} from '../../constants/HelperTextUtil';
|
||||
import { EntityType } from '../../enums/entity.enum';
|
||||
import { Bot, ProviderType } from '../../generated/entity/bot';
|
||||
import { Operation } from '../../generated/entity/policies/accessControl/rule';
|
||||
import { Include } from '../../generated/type/include';
|
||||
import { Paging } from '../../generated/type/paging';
|
||||
import { useAuth } from '../../hooks/authHooks';
|
||||
import { getEntityName } from '../../utils/CommonUtils';
|
||||
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
import DeleteWidgetModal from '../common/DeleteWidget/DeleteWidgetModal';
|
||||
@ -43,8 +43,6 @@ import NextPrevious from '../common/next-previous/NextPrevious';
|
||||
import RichTextEditorPreviewer from '../common/rich-text-editor/RichTextEditorPreviewer';
|
||||
import Searchbar from '../common/searchbar/Searchbar';
|
||||
import Loader from '../Loader/Loader';
|
||||
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
||||
import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface';
|
||||
import { BotListV1Props } from './BotListV1.interfaces';
|
||||
|
||||
const BotListV1 = ({
|
||||
@ -52,7 +50,8 @@ const BotListV1 = ({
|
||||
handleAddBotClick,
|
||||
handleShowDeleted,
|
||||
}: BotListV1Props) => {
|
||||
const { permissions } = usePermissionProvider();
|
||||
const { isAdminUser } = useAuth();
|
||||
const { t } = useTranslation();
|
||||
const [botUsers, setBotUsers] = useState<Bot[]>([]);
|
||||
const [paging, setPaging] = useState<Paging>({} as Paging);
|
||||
const [selectedUser, setSelectedUser] = useState<Bot>();
|
||||
@ -62,22 +61,6 @@ const BotListV1 = ({
|
||||
const [handleErrorPlaceholder, setHandleErrorPlaceholder] = useState(false);
|
||||
const [searchedData, setSearchedData] = useState<Bot[]>([]);
|
||||
|
||||
/**
|
||||
* Bot creation is two step process so here we should check for
|
||||
* Create User and Create Bot both permissions
|
||||
*/
|
||||
const createPermission = useMemo(
|
||||
() =>
|
||||
checkPermission(Operation.Create, ResourceEntity.BOT, permissions) &&
|
||||
checkPermission(Operation.Create, ResourceEntity.USER, permissions),
|
||||
[permissions]
|
||||
);
|
||||
|
||||
const deletePermission = useMemo(
|
||||
() => checkPermission(Operation.Delete, ResourceEntity.BOT, permissions),
|
||||
[permissions]
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param after - Pagination value if passed data will be fetched post cursor value
|
||||
@ -111,7 +94,7 @@ const BotListV1 = ({
|
||||
const columns: ColumnsType<Bot> = useMemo(
|
||||
() => [
|
||||
{
|
||||
title: 'Name',
|
||||
title: t('label.name'),
|
||||
dataIndex: 'displayName',
|
||||
key: 'displayName',
|
||||
render: (_, record) => (
|
||||
@ -124,18 +107,20 @@ const BotListV1 = ({
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Description',
|
||||
title: t('label.description'),
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
render: (_, record) =>
|
||||
record?.description ? (
|
||||
<RichTextEditorPreviewer markdown={record?.description || ''} />
|
||||
) : (
|
||||
<span data-testid="no-description">No Description</span>
|
||||
<span data-testid="no-description">
|
||||
{t('label.no-description')}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Actions',
|
||||
title: t('label.actions'),
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 90,
|
||||
@ -143,10 +128,10 @@ const BotListV1 = ({
|
||||
const isSystemBot = record.provider === ProviderType.System;
|
||||
const title = isSystemBot
|
||||
? INGESTION_BOT_CANT_BE_DELETED
|
||||
: deletePermission
|
||||
? 'Delete'
|
||||
: NO_PERMISSION_FOR_ACTION;
|
||||
const isDisabled = !deletePermission || isSystemBot;
|
||||
: isAdminUser
|
||||
? t('label.delete')
|
||||
: ADMIN_ONLY_ACTION;
|
||||
const isDisabled = !isAdminUser || isSystemBot;
|
||||
|
||||
return (
|
||||
<Space align="center" size={8}>
|
||||
@ -220,7 +205,7 @@ const BotListV1 = ({
|
||||
size="small"
|
||||
onClick={handleShowDeleted}
|
||||
/>
|
||||
<label htmlFor="switch-deleted">Show deleted</label>
|
||||
<label htmlFor="switch-deleted">{t('label.show-deleted')}</label>
|
||||
</Space>
|
||||
</Col>
|
||||
<Col className="w-full">
|
||||
@ -229,14 +214,14 @@ const BotListV1 = ({
|
||||
<div className="tw-text-lg tw-text-center">
|
||||
<Tooltip
|
||||
placement="left"
|
||||
title={createPermission ? 'Add Bot' : NO_PERMISSION_FOR_ACTION}>
|
||||
title={isAdminUser ? t('label.add-bot') : ADMIN_ONLY_ACTION}>
|
||||
<Button
|
||||
ghost
|
||||
data-testid="add-bot"
|
||||
disabled={!createPermission}
|
||||
disabled={!isAdminUser}
|
||||
type="primary"
|
||||
onClick={handleAddBotClick}>
|
||||
Add Bot
|
||||
{t('label.add-bot')}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
@ -252,7 +237,7 @@ const BotListV1 = ({
|
||||
<Col span={8}>
|
||||
<Searchbar
|
||||
removeMargin
|
||||
placeholder="Search for bots..."
|
||||
placeholder={t('label.search-for-bots')}
|
||||
typingInterval={500}
|
||||
onSearch={handleSearch}
|
||||
/>
|
||||
@ -265,17 +250,16 @@ const BotListV1 = ({
|
||||
id="switch-deleted"
|
||||
onClick={handleShowDeleted}
|
||||
/>
|
||||
<label htmlFor="switch-deleted">Show deleted</label>
|
||||
<label htmlFor="switch-deleted">{t('label.show-deleted')}</label>
|
||||
</Space>
|
||||
|
||||
<Tooltip
|
||||
title={createPermission ? 'Add Bot' : NO_PERMISSION_FOR_ACTION}>
|
||||
<Tooltip title={isAdminUser ? t('label.add-bot') : ADMIN_ONLY_ACTION}>
|
||||
<Button
|
||||
data-testid="add-bot"
|
||||
disabled={!createPermission}
|
||||
disabled={!isAdminUser}
|
||||
type="primary"
|
||||
onClick={handleAddBotClick}>
|
||||
Add Bot
|
||||
{t('label.add-bot')}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</Space>
|
||||
|
||||
@ -20,17 +20,16 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { updateUser } from '../../axiosAPIs/userAPI';
|
||||
import { PAGE_SIZE_MEDIUM, ROUTES } from '../../constants/constants';
|
||||
import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
|
||||
import { ADMIN_ONLY_ACTION } from '../../constants/HelperTextUtil';
|
||||
import { CreateUser } from '../../generated/api/teams/createUser';
|
||||
import { Operation } from '../../generated/entity/policies/policy';
|
||||
import { User } from '../../generated/entity/teams/user';
|
||||
import { Paging } from '../../generated/type/paging';
|
||||
import { useAuth } from '../../hooks/authHooks';
|
||||
import jsonData from '../../jsons/en';
|
||||
import {
|
||||
commonUserDetailColumns,
|
||||
getEntityName,
|
||||
} from '../../utils/CommonUtils';
|
||||
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
||||
import DeleteWidgetModal from '../common/DeleteWidget/DeleteWidgetModal';
|
||||
@ -38,8 +37,6 @@ import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder'
|
||||
import NextPrevious from '../common/next-previous/NextPrevious';
|
||||
import Searchbar from '../common/searchbar/Searchbar';
|
||||
import Loader from '../Loader/Loader';
|
||||
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
||||
import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface';
|
||||
import './usersList.less';
|
||||
|
||||
interface UserListV1Props {
|
||||
@ -67,8 +64,8 @@ const UserListV1: FC<UserListV1Props> = ({
|
||||
onPagingChange,
|
||||
afterDeleteAction,
|
||||
}) => {
|
||||
const { isAdminUser } = useAuth();
|
||||
const { t } = useTranslation();
|
||||
const { permissions } = usePermissionProvider();
|
||||
const history = useHistory();
|
||||
const [selectedUser, setSelectedUser] = useState<User>();
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||
@ -76,16 +73,6 @@ const UserListV1: FC<UserListV1Props> = ({
|
||||
const showRestore = showDeletedUser && !isDataLoading;
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const createPermission = useMemo(
|
||||
() => checkPermission(Operation.Create, ResourceEntity.USER, permissions),
|
||||
[permissions]
|
||||
);
|
||||
|
||||
const deletePermission = useMemo(
|
||||
() => checkPermission(Operation.Delete, ResourceEntity.USER, permissions),
|
||||
[permissions]
|
||||
);
|
||||
|
||||
const handleAddNewUser = () => {
|
||||
history.push(ROUTES.CREATE_USER);
|
||||
};
|
||||
@ -164,11 +151,9 @@ const UserListV1: FC<UserListV1Props> = ({
|
||||
)}
|
||||
<Tooltip
|
||||
placement="bottom"
|
||||
title={
|
||||
deletePermission ? t('label.delete') : NO_PERMISSION_FOR_ACTION
|
||||
}>
|
||||
title={isAdminUser ? t('label.delete') : ADMIN_ONLY_ACTION}>
|
||||
<Button
|
||||
disabled={!deletePermission}
|
||||
disabled={!isAdminUser}
|
||||
icon={
|
||||
<SVGIcons
|
||||
alt="Delete"
|
||||
@ -212,7 +197,7 @@ const UserListV1: FC<UserListV1Props> = ({
|
||||
<Button
|
||||
ghost
|
||||
data-testid="add-user"
|
||||
disabled={!createPermission}
|
||||
disabled={!isAdminUser}
|
||||
type="primary"
|
||||
onClick={handleAddNewUser}>
|
||||
{t('label.add-user')}
|
||||
@ -253,12 +238,10 @@ const UserListV1: FC<UserListV1Props> = ({
|
||||
<span className="tw-ml-2">{t('label.deleted-users')}</span>
|
||||
</span>
|
||||
<Tooltip
|
||||
title={
|
||||
createPermission ? t('label.add-user') : NO_PERMISSION_FOR_ACTION
|
||||
}>
|
||||
title={isAdminUser ? t('label.add-user') : ADMIN_ONLY_ACTION}>
|
||||
<Button
|
||||
data-testid="add-user"
|
||||
disabled={!createPermission}
|
||||
disabled={!isAdminUser}
|
||||
type="primary"
|
||||
onClick={handleAddNewUser}>
|
||||
{t('label.add-user')}
|
||||
|
||||
@ -57,3 +57,5 @@ export const INGESTION_BOT_CANT_BE_DELETED =
|
||||
|
||||
export const BOT_ACCOUNT_EMAIL_CHANGE_CONFIRMATION =
|
||||
'Changing account email will update or create a new bot user';
|
||||
|
||||
export const ADMIN_ONLY_ACTION = 'Only admin can perform this action.';
|
||||
|
||||
@ -195,7 +195,10 @@
|
||||
"unpause": "UnPause",
|
||||
"execution-date": "Execution Date",
|
||||
"start-date": "Start Date",
|
||||
"end-date": "End Date"
|
||||
"end-date": "End Date",
|
||||
"show-deleted": "Show deleted",
|
||||
"add-bot": "Add Bot",
|
||||
"search-for-bots": "Search for bots..."
|
||||
},
|
||||
"message": {
|
||||
"service-email-required": "Service account Email is required",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user