mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-17 03:38:18 +00:00
feat(ui): update global settings page with new roles and policy (#7002)
* feat(ui): update global settings page with new roles and policy * Modify the permission util and remove access prop from create bot and user page * Fix typo * Fix console errors * fix unit tests * Add getEntityPermission to provider * Remove admin and auth disable check from global setting * Add check for edit description. Co-authored-by: Sachin Chaurasiya <sachinchaurasiyachotey87@gmail.com>
This commit is contained in:
parent
15c83e3f2d
commit
cc0449e506
@ -13,9 +13,11 @@
|
|||||||
|
|
||||||
import { AxiosResponse } from 'axios';
|
import { AxiosResponse } from 'axios';
|
||||||
import { Operation } from 'fast-json-patch';
|
import { Operation } from 'fast-json-patch';
|
||||||
|
import { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { CreatePolicy } from '../generated/api/policies/createPolicy';
|
import { CreatePolicy } from '../generated/api/policies/createPolicy';
|
||||||
import { CreateRole } from '../generated/api/teams/createRole';
|
import { CreateRole } from '../generated/api/teams/createRole';
|
||||||
import { ResourceDescriptor } from '../generated/entity/policies/accessControl/resourceDescriptor';
|
import { ResourceDescriptor } from '../generated/entity/policies/accessControl/resourceDescriptor';
|
||||||
|
import { ResourcePermission } from '../generated/entity/policies/accessControl/resourcePermission';
|
||||||
import { Policy } from '../generated/entity/policies/policy';
|
import { Policy } from '../generated/entity/policies/policy';
|
||||||
import { Role } from '../generated/entity/teams/role';
|
import { Role } from '../generated/entity/teams/role';
|
||||||
import { Function } from '../generated/type/function';
|
import { Function } from '../generated/type/function';
|
||||||
@ -154,3 +156,14 @@ export const validateRuleCondition = async (condition: string) => {
|
|||||||
*/
|
*/
|
||||||
return response;
|
return response;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getEntityPermissionById = async (
|
||||||
|
resource: ResourceEntity,
|
||||||
|
entityId: string
|
||||||
|
) => {
|
||||||
|
const response = await APIClient.get<ResourcePermission>(
|
||||||
|
`/permissions/${resource}/${entityId}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
@ -13,12 +13,19 @@
|
|||||||
|
|
||||||
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
|
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { Tooltip } from 'antd';
|
||||||
import { Store } from 'antd/lib/form/interface';
|
import { Store } from 'antd/lib/form/interface';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import cryptoRandomString from 'crypto-random-string-with-promisify-polyfill';
|
import cryptoRandomString from 'crypto-random-string-with-promisify-polyfill';
|
||||||
import { cloneDeep, isEqual, isNil } from 'lodash';
|
import { cloneDeep, isEmpty, isEqual, isNil } from 'lodash';
|
||||||
import { EditorContentRef } from 'Models';
|
import { EditorContentRef } from 'Models';
|
||||||
import React, { FunctionComponent, useCallback, useRef, useState } from 'react';
|
import React, {
|
||||||
|
FunctionComponent,
|
||||||
|
useCallback,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
import { ROUTES, TERM_ALL } from '../../constants/constants';
|
import { ROUTES, TERM_ALL } from '../../constants/constants';
|
||||||
import {
|
import {
|
||||||
GlobalSettingOptions,
|
GlobalSettingOptions,
|
||||||
@ -27,6 +34,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
CONFIGURE_SLACK_TEXT,
|
CONFIGURE_SLACK_TEXT,
|
||||||
CONFIGURE_WEBHOOK_TEXT,
|
CONFIGURE_WEBHOOK_TEXT,
|
||||||
|
NO_PERMISSION_FOR_ACTION,
|
||||||
} from '../../constants/HelperTextUtil';
|
} from '../../constants/HelperTextUtil';
|
||||||
import { UrlEntityCharRegEx } from '../../constants/regex.constants';
|
import { UrlEntityCharRegEx } from '../../constants/regex.constants';
|
||||||
import { FormSubmitType } from '../../enums/form.enum';
|
import { FormSubmitType } from '../../enums/form.enum';
|
||||||
@ -37,12 +45,14 @@ import {
|
|||||||
Filters,
|
Filters,
|
||||||
} from '../../generated/api/events/createWebhook';
|
} from '../../generated/api/events/createWebhook';
|
||||||
import { WebhookType } from '../../generated/entity/events/webhook';
|
import { WebhookType } from '../../generated/entity/events/webhook';
|
||||||
|
import { Operation } from '../../generated/entity/policies/policy';
|
||||||
import {
|
import {
|
||||||
errorMsg,
|
errorMsg,
|
||||||
getSeparator,
|
getSeparator,
|
||||||
isValidUrl,
|
isValidUrl,
|
||||||
requiredField,
|
requiredField,
|
||||||
} from '../../utils/CommonUtils';
|
} from '../../utils/CommonUtils';
|
||||||
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
import { getSettingPath } from '../../utils/RouterUtils';
|
import { getSettingPath } from '../../utils/RouterUtils';
|
||||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||||
import { Button } from '../buttons/Button/Button';
|
import { Button } from '../buttons/Button/Button';
|
||||||
@ -52,6 +62,8 @@ import TitleBreadcrumb from '../common/title-breadcrumb/title-breadcrumb.compone
|
|||||||
import PageLayout from '../containers/PageLayout';
|
import PageLayout from '../containers/PageLayout';
|
||||||
import Loader from '../Loader/Loader';
|
import Loader from '../Loader/Loader';
|
||||||
import ConfirmationModal from '../Modals/ConfirmationModal/ConfirmationModal';
|
import ConfirmationModal from '../Modals/ConfirmationModal/ConfirmationModal';
|
||||||
|
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface';
|
||||||
import { AddWebhookProps } from './AddWebhook.interface';
|
import { AddWebhookProps } from './AddWebhook.interface';
|
||||||
import SelectComponent from './select-component';
|
import SelectComponent from './select-component';
|
||||||
import {
|
import {
|
||||||
@ -163,6 +175,29 @@ const AddWebhook: FunctionComponent<AddWebhookProps> = ({
|
|||||||
const [generatingSecret, setGeneratingSecret] = useState<boolean>(false);
|
const [generatingSecret, setGeneratingSecret] = useState<boolean>(false);
|
||||||
const [isDelete, setIsDelete] = useState<boolean>(false);
|
const [isDelete, setIsDelete] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
|
const editWebhookPermission = useMemo(
|
||||||
|
() =>
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(Operation.EditAll, ResourceEntity.WEBHOOK, permissions),
|
||||||
|
[permissions]
|
||||||
|
);
|
||||||
|
|
||||||
|
const addWebhookPermission = useMemo(
|
||||||
|
() =>
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(Operation.Create, ResourceEntity.WEBHOOK, permissions),
|
||||||
|
[permissions]
|
||||||
|
);
|
||||||
|
|
||||||
|
const deleteWebhookPermission = useMemo(
|
||||||
|
() =>
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(Operation.Delete, ResourceEntity.WEBHOOK, permissions),
|
||||||
|
[permissions]
|
||||||
|
);
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
if (data) {
|
if (data) {
|
||||||
onDelete && onDelete(data.id);
|
onDelete && onDelete(data.id);
|
||||||
@ -259,7 +294,7 @@ const AddWebhook: FunctionComponent<AddWebhookProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getDeleteButton = () => {
|
const getDeleteButton = () => {
|
||||||
return allowAccess ? (
|
return (
|
||||||
<>
|
<>
|
||||||
{deleteState === 'waiting' ? (
|
{deleteState === 'waiting' ? (
|
||||||
<Button
|
<Button
|
||||||
@ -271,24 +306,32 @@ const AddWebhook: FunctionComponent<AddWebhookProps> = ({
|
|||||||
<Loader size="small" type="default" />
|
<Loader size="small" type="default" />
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Tooltip
|
||||||
className={classNames({
|
placement="left"
|
||||||
'tw-opacity-40': !allowAccess,
|
title={
|
||||||
})}
|
deleteWebhookPermission ? 'Delete' : NO_PERMISSION_FOR_ACTION
|
||||||
data-testid="delete-webhook"
|
}>
|
||||||
size="regular"
|
<Button
|
||||||
theme="primary"
|
data-testid="delete-webhook"
|
||||||
variant="text"
|
disabled={!deleteWebhookPermission}
|
||||||
onClick={() => setIsDelete(true)}>
|
size="regular"
|
||||||
Delete
|
theme="primary"
|
||||||
</Button>
|
variant="text"
|
||||||
|
onClick={() => setIsDelete(true)}>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : null;
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSaveButton = () => {
|
const getSaveButton = () => {
|
||||||
return allowAccess ? (
|
const savePermission =
|
||||||
|
(mode === 'add' && addWebhookPermission) ||
|
||||||
|
(mode === 'edit' && editWebhookPermission);
|
||||||
|
|
||||||
|
return (
|
||||||
<>
|
<>
|
||||||
{saveState === 'waiting' ? (
|
{saveState === 'waiting' ? (
|
||||||
<Button
|
<Button
|
||||||
@ -309,20 +352,23 @@ const AddWebhook: FunctionComponent<AddWebhookProps> = ({
|
|||||||
<FontAwesomeIcon icon="check" />
|
<FontAwesomeIcon icon="check" />
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Tooltip
|
||||||
className={classNames('tw-w-16 tw-h-10', {
|
placement="left"
|
||||||
'tw-opacity-40': !allowAccess,
|
title={savePermission ? 'Save' : NO_PERMISSION_FOR_ACTION}>
|
||||||
})}
|
<Button
|
||||||
data-testid="save-webhook"
|
className={classNames('tw-w-16 tw-h-10')}
|
||||||
size="regular"
|
data-testid="save-webhook"
|
||||||
theme="primary"
|
disabled={!savePermission}
|
||||||
variant="contained"
|
size="regular"
|
||||||
onClick={handleSave}>
|
theme="primary"
|
||||||
Save
|
variant="contained"
|
||||||
</Button>
|
onClick={handleSave}>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : null;
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchRightPanel = useCallback(() => {
|
const fetchRightPanel = useCallback(() => {
|
||||||
@ -631,7 +677,7 @@ const AddWebhook: FunctionComponent<AddWebhookProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Field>
|
</Field>
|
||||||
{data && isDelete && (
|
{data && isDelete && deleteWebhookPermission && (
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
bodyText={`You want to delete webhook ${data.name} permanently? This action cannot be reverted.`}
|
bodyText={`You want to delete webhook ${data.name} permanently? This action cannot be reverted.`}
|
||||||
cancelText="Cancel"
|
cancelText="Cancel"
|
||||||
|
@ -34,7 +34,7 @@ import { Operation } from '../../generated/entity/policies/accessControl/rule';
|
|||||||
import { JWTTokenExpiry, User } from '../../generated/entity/teams/user';
|
import { JWTTokenExpiry, User } from '../../generated/entity/teams/user';
|
||||||
import { EntityReference } from '../../generated/type/entityReference';
|
import { EntityReference } from '../../generated/type/entityReference';
|
||||||
import { getEntityName, requiredField } from '../../utils/CommonUtils';
|
import { getEntityName, requiredField } from '../../utils/CommonUtils';
|
||||||
import { checkPemission } from '../../utils/PermissionsUtils';
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
import { getSettingPath } from '../../utils/RouterUtils';
|
import { getSettingPath } from '../../utils/RouterUtils';
|
||||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
@ -77,18 +77,18 @@ const BotDetails: FC<BotsDetailProp> = ({
|
|||||||
const [generateToken, setGenerateToken] = useState<boolean>(false);
|
const [generateToken, setGenerateToken] = useState<boolean>(false);
|
||||||
const [selectedExpiry, setSelectedExpiry] = useState('7');
|
const [selectedExpiry, setSelectedExpiry] = useState('7');
|
||||||
|
|
||||||
const editAllPermission = checkPemission(
|
const editAllPermission = checkPermission(
|
||||||
Operation.EditAll,
|
Operation.EditAll,
|
||||||
ResourceEntity.BOT,
|
ResourceEntity.BOT,
|
||||||
permissions
|
permissions
|
||||||
);
|
);
|
||||||
const displayNamePermission = checkPemission(
|
const displayNamePermission = checkPermission(
|
||||||
Operation.EditDisplayName,
|
Operation.EditDisplayName,
|
||||||
ResourceEntity.BOT,
|
ResourceEntity.BOT,
|
||||||
permissions
|
permissions
|
||||||
);
|
);
|
||||||
|
|
||||||
const descriptionPermission = checkPemission(
|
const descriptionPermission = checkPermission(
|
||||||
Operation.EditDescription,
|
Operation.EditDescription,
|
||||||
ResourceEntity.BOT,
|
ResourceEntity.BOT,
|
||||||
permissions
|
permissions
|
||||||
|
@ -85,7 +85,7 @@ jest.mock('../PermissionProvider/PermissionProvider', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../utils/PermissionsUtils', () => ({
|
jest.mock('../../utils/PermissionsUtils', () => ({
|
||||||
checkPemission: jest.fn().mockReturnValue(true),
|
checkPermission: jest.fn().mockReturnValue(true),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../axiosAPIs/userAPI', () => {
|
jest.mock('../../axiosAPIs/userAPI', () => {
|
||||||
|
@ -22,12 +22,13 @@ import {
|
|||||||
INITIAL_PAGING_VALUE,
|
INITIAL_PAGING_VALUE,
|
||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
} from '../../constants/constants';
|
} from '../../constants/constants';
|
||||||
|
import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
|
||||||
import { EntityType } from '../../enums/entity.enum';
|
import { EntityType } from '../../enums/entity.enum';
|
||||||
import { Bot } from '../../generated/entity/bot';
|
import { Bot } from '../../generated/entity/bot';
|
||||||
import { Operation } from '../../generated/entity/policies/accessControl/rule';
|
import { Operation } from '../../generated/entity/policies/accessControl/rule';
|
||||||
import { Include } from '../../generated/type/include';
|
import { Include } from '../../generated/type/include';
|
||||||
import { Paging } from '../../generated/type/paging';
|
import { Paging } from '../../generated/type/paging';
|
||||||
import { checkPemission } from '../../utils/PermissionsUtils';
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
import SVGIcons, { Icons } from '../../utils/SvgUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
import DeleteWidgetModal from '../common/DeleteWidget/DeleteWidgetModal';
|
import DeleteWidgetModal from '../common/DeleteWidget/DeleteWidgetModal';
|
||||||
@ -45,7 +46,7 @@ const BotListV1 = ({ showDeleted }: BotListV1Props) => {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [currentPage, setCurrentPage] = useState<number>(INITIAL_PAGING_VALUE);
|
const [currentPage, setCurrentPage] = useState<number>(INITIAL_PAGING_VALUE);
|
||||||
|
|
||||||
const deletePermission = checkPemission(
|
const deletePermission = checkPermission(
|
||||||
Operation.Delete,
|
Operation.Delete,
|
||||||
ResourceEntity.BOT,
|
ResourceEntity.BOT,
|
||||||
permissions
|
permissions
|
||||||
@ -103,11 +104,7 @@ const BotListV1 = ({ showDeleted }: BotListV1Props) => {
|
|||||||
<Space align="center" size={8}>
|
<Space align="center" size={8}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
title={
|
title={deletePermission ? 'Delete' : NO_PERMISSION_FOR_ACTION}>
|
||||||
deletePermission
|
|
||||||
? 'Delete'
|
|
||||||
: 'You do not have permissions to perform this action.'
|
|
||||||
}>
|
|
||||||
<Button
|
<Button
|
||||||
disabled={!deletePermission}
|
disabled={!deletePermission}
|
||||||
icon={
|
icon={
|
||||||
|
@ -36,7 +36,6 @@ import TeamsSelectable from '../TeamsSelectable/TeamsSelectable';
|
|||||||
import { CreateUserProps } from './CreateUser.interface';
|
import { CreateUserProps } from './CreateUser.interface';
|
||||||
|
|
||||||
const CreateUser = ({
|
const CreateUser = ({
|
||||||
allowAccess,
|
|
||||||
roles,
|
roles,
|
||||||
saveState = 'initial',
|
saveState = 'initial',
|
||||||
onCancel,
|
onCancel,
|
||||||
@ -81,10 +80,6 @@ const CreateUser = ({
|
|||||||
const handleValidation = (
|
const handleValidation = (
|
||||||
event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
|
event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
|
||||||
) => {
|
) => {
|
||||||
if (!allowAccess) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const value = event.target.value;
|
const value = event.target.value;
|
||||||
const eleName = event.target.name;
|
const eleName = event.target.name;
|
||||||
|
|
||||||
@ -188,7 +183,7 @@ const CreateUser = ({
|
|||||||
* @returns Button
|
* @returns Button
|
||||||
*/
|
*/
|
||||||
const getSaveButton = () => {
|
const getSaveButton = () => {
|
||||||
return allowAccess ? (
|
return (
|
||||||
<>
|
<>
|
||||||
{saveState === 'waiting' ? (
|
{saveState === 'waiting' ? (
|
||||||
<Button
|
<Button
|
||||||
@ -210,9 +205,7 @@ const CreateUser = ({
|
|||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
className={classNames('tw-w-16 tw-h-10', {
|
className={classNames('tw-w-16 tw-h-10')}
|
||||||
'tw-opacity-40': !allowAccess,
|
|
||||||
})}
|
|
||||||
data-testid="save-user"
|
data-testid="save-user"
|
||||||
size="regular"
|
size="regular"
|
||||||
theme="primary"
|
theme="primary"
|
||||||
@ -222,7 +215,7 @@ const CreateUser = ({
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : null;
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -310,10 +303,8 @@ const CreateUser = ({
|
|||||||
className={classNames('toggle-switch', { open: isAdmin })}
|
className={classNames('toggle-switch', { open: isAdmin })}
|
||||||
data-testid="admin"
|
data-testid="admin"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (allowAccess) {
|
setIsAdmin((prev) => !prev);
|
||||||
setIsAdmin((prev) => !prev);
|
setIsBot(false);
|
||||||
setIsBot(false);
|
|
||||||
}
|
|
||||||
}}>
|
}}>
|
||||||
<div className="switch" />
|
<div className="switch" />
|
||||||
</div>
|
</div>
|
||||||
@ -324,10 +315,8 @@ const CreateUser = ({
|
|||||||
className={classNames('toggle-switch', { open: isBot })}
|
className={classNames('toggle-switch', { open: isBot })}
|
||||||
data-testid="bot"
|
data-testid="bot"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (allowAccess) {
|
setIsBot((prev) => !prev);
|
||||||
setIsBot((prev) => !prev);
|
setIsAdmin(false);
|
||||||
setIsAdmin(false);
|
|
||||||
}
|
|
||||||
}}>
|
}}>
|
||||||
<div className="switch" />
|
<div className="switch" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,7 +16,6 @@ import { CreateUser } from '../../generated/api/teams/createUser';
|
|||||||
import { Role } from '../../generated/entity/teams/role';
|
import { Role } from '../../generated/entity/teams/role';
|
||||||
|
|
||||||
export interface CreateUserProps {
|
export interface CreateUserProps {
|
||||||
allowAccess: boolean;
|
|
||||||
saveState?: LoadingState;
|
saveState?: LoadingState;
|
||||||
roles: Array<Role>;
|
roles: Array<Role>;
|
||||||
onSave: (data: CreateUser) => void;
|
onSave: (data: CreateUser) => void;
|
||||||
|
@ -37,7 +37,6 @@ jest.mock('../common/rich-text-editor/RichTextEditor', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const propsValue: CreateUserProps = {
|
const propsValue: CreateUserProps = {
|
||||||
allowAccess: true,
|
|
||||||
saveState: 'initial',
|
saveState: 'initial',
|
||||||
roles: [],
|
roles: [],
|
||||||
forceBot: false,
|
forceBot: false,
|
||||||
|
@ -16,23 +16,29 @@ import { ItemType } from 'antd/lib/menu/hooks/useItems';
|
|||||||
import { camelCase } from 'lodash';
|
import { camelCase } from 'lodash';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useHistory, useParams } from 'react-router-dom';
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
|
||||||
import { GLOBAL_SETTINGS_MENU } from '../../constants/globalSettings.constants';
|
import { GLOBAL_SETTINGS_MENU } from '../../constants/globalSettings.constants';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { Operation } from '../../generated/entity/policies/accessControl/rule';
|
||||||
import { getGlobalSettingMenus } from '../../utils/GlobalSettingsUtils';
|
import { getGlobalSettingMenus } from '../../utils/GlobalSettingsUtils';
|
||||||
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
import { getSettingPath } from '../../utils/RouterUtils';
|
import { getSettingPath } from '../../utils/RouterUtils';
|
||||||
|
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface';
|
||||||
|
|
||||||
const GlobalSettingLeftPanel = () => {
|
const GlobalSettingLeftPanel = () => {
|
||||||
const { tab, settingCategory } = useParams<{ [key: string]: string }>();
|
const { tab, settingCategory } = useParams<{ [key: string]: string }>();
|
||||||
const { isAdminUser } = useAuth();
|
|
||||||
const { isAuthDisabled } = useAuthContext();
|
|
||||||
|
|
||||||
const isHasAccess = isAdminUser || isAuthDisabled;
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
|
const viewAllPermission = checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.ALL,
|
||||||
|
permissions
|
||||||
|
);
|
||||||
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const items: ItemType[] = GLOBAL_SETTINGS_MENU.filter(({ isProtected }) => {
|
const items: ItemType[] = GLOBAL_SETTINGS_MENU.filter(({ isProtected }) => {
|
||||||
if (isHasAccess) {
|
if (viewAllPermission) {
|
||||||
return isHasAccess;
|
return viewAllPermission;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !isProtected;
|
return !isProtected;
|
||||||
@ -44,7 +50,7 @@ const GlobalSettingLeftPanel = () => {
|
|||||||
'',
|
'',
|
||||||
items,
|
items,
|
||||||
'group',
|
'group',
|
||||||
isHasAccess
|
viewAllPermission
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,3 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 Collate
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { AxiosError } from 'axios';
|
||||||
import { Operation } from '../../generated/entity/policies/accessControl/resourcePermission';
|
import { Operation } from '../../generated/entity/policies/accessControl/resourcePermission';
|
||||||
|
|
||||||
export type UIPermission = {
|
export type UIPermission = {
|
||||||
@ -13,35 +27,47 @@ export enum ResourceEntity {
|
|||||||
BOT = 'bot',
|
BOT = 'bot',
|
||||||
CHART = 'chart',
|
CHART = 'chart',
|
||||||
DASHBOARD = 'dashboard',
|
DASHBOARD = 'dashboard',
|
||||||
DASHBOARDSERVICE = 'dashboardService',
|
DASHBOARD_SERVICE = 'dashboardService',
|
||||||
DATABASE = 'database',
|
DATABASE = 'database',
|
||||||
DATABASESCHEMA = 'databaseSchema',
|
DATABASE_SCHEMA = 'databaseSchema',
|
||||||
DATABASESERVICE = 'databaseService',
|
DATABASE_SERVICE = 'databaseService',
|
||||||
EVENTS = 'events',
|
EVENTS = 'events',
|
||||||
FEED = 'feed',
|
FEED = 'feed',
|
||||||
GLOSSARY = 'glossary',
|
GLOSSARY = 'glossary',
|
||||||
GLOSSARYTERM = 'glossaryTerm',
|
GLOSSARY_TERM = 'glossaryTerm',
|
||||||
INGESTIONPIPELINE = 'ingestionPipeline',
|
INGESTION_PIPELINE = 'ingestionPipeline',
|
||||||
LOCATION = 'location',
|
LOCATION = 'location',
|
||||||
MESSAGINGSERVICE = 'messagingService',
|
MESSAGING_SERVICE = 'messagingService',
|
||||||
METRICS = 'metrics',
|
METRICS = 'metrics',
|
||||||
MLMODEL = 'mlmodel',
|
ML_MODEL = 'mlmodel',
|
||||||
MLMODELSERVICE = 'mlmodelService',
|
ML_MODEL_SERVICE = 'mlmodelService',
|
||||||
PIPELINE = 'pipeline',
|
PIPELINE = 'pipeline',
|
||||||
PIPELINESERVICE = 'pipelineService',
|
PIPELINE_SERVICE = 'pipelineService',
|
||||||
POLICY = 'policy',
|
POLICY = 'policy',
|
||||||
REPORT = 'report',
|
REPORT = 'report',
|
||||||
ROLE = 'role',
|
ROLE = 'role',
|
||||||
STORAGESERVICE = 'storageService',
|
STORAGE_SERVICE = 'storageService',
|
||||||
TABLE = 'table',
|
TABLE = 'table',
|
||||||
TAG = 'tag',
|
TAG = 'tag',
|
||||||
TAGCATEGORY = 'tagCategory',
|
TAG_CATEGORY = 'tagCategory',
|
||||||
TEAM = 'team',
|
TEAM = 'team',
|
||||||
TESTCASE = 'testCase',
|
TEST_CASE = 'testCase',
|
||||||
TESTDEFINITION = 'testDefinition',
|
TEST_DEFINITION = 'testDefinition',
|
||||||
TESTSUITE = 'testSuite',
|
TEST_SUITE = 'testSuite',
|
||||||
TOPIC = 'topic',
|
TOPIC = 'topic',
|
||||||
TYPE = 'type',
|
TYPE = 'type',
|
||||||
USER = 'user',
|
USER = 'user',
|
||||||
WEBHOOK = 'webhook',
|
WEBHOOK = 'webhook',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PermissionContextType {
|
||||||
|
permissions: UIPermission;
|
||||||
|
getEntityPermission: (
|
||||||
|
resource: ResourceEntity,
|
||||||
|
entityId: string
|
||||||
|
) => Promise<OperationPermission | AxiosError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EntityPermissionMap {
|
||||||
|
[key: string]: OperationPermission;
|
||||||
|
}
|
||||||
|
@ -24,18 +24,27 @@ import React, {
|
|||||||
} from 'react';
|
} from 'react';
|
||||||
import AppState from '../../AppState';
|
import AppState from '../../AppState';
|
||||||
import { getLoggedInUserPermissions } from '../../axiosAPIs/miscAPI';
|
import { getLoggedInUserPermissions } from '../../axiosAPIs/miscAPI';
|
||||||
import { getUIPermission } from '../../utils/PermissionsUtils';
|
import { getEntityPermissionById } from '../../axiosAPIs/rolesAPIV1';
|
||||||
|
import {
|
||||||
|
getOperationPermissions,
|
||||||
|
getUIPermission,
|
||||||
|
} from '../../utils/PermissionsUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
import { UIPermission } from './PermissionProvider.interface';
|
import {
|
||||||
|
EntityPermissionMap,
|
||||||
|
PermissionContextType,
|
||||||
|
ResourceEntity,
|
||||||
|
UIPermission,
|
||||||
|
} from './PermissionProvider.interface';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission Context
|
* Permission Context
|
||||||
* Returns ResourcePermission List for loggedIn User
|
* Returns ResourcePermission List for loggedIn User
|
||||||
* @returns PermissionMap
|
* @returns PermissionMap
|
||||||
*/
|
*/
|
||||||
export const PermissionContext = createContext<{
|
export const PermissionContext = createContext<PermissionContextType>(
|
||||||
permissions: UIPermission;
|
{} as PermissionContextType
|
||||||
}>({ permissions: {} as UIPermission });
|
);
|
||||||
|
|
||||||
interface PermissionProviderProps {
|
interface PermissionProviderProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
@ -51,6 +60,9 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
|||||||
{} as UIPermission
|
{} as UIPermission
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [entitiesPermission, setEntitiesPermission] =
|
||||||
|
useState<EntityPermissionMap>({} as EntityPermissionMap);
|
||||||
|
|
||||||
// Update current user details of AppState change
|
// Update current user details of AppState change
|
||||||
const currentUser = useMemo(() => {
|
const currentUser = useMemo(() => {
|
||||||
return AppState.getCurrentUserDetails();
|
return AppState.getCurrentUserDetails();
|
||||||
@ -68,6 +80,29 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetchEntityPermission = async (
|
||||||
|
resource: ResourceEntity,
|
||||||
|
entityId: string
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const entityPermission = entitiesPermission[entityId];
|
||||||
|
if (entityPermission) {
|
||||||
|
return entityPermission;
|
||||||
|
} else {
|
||||||
|
const response = await getEntityPermissionById(resource, entityId);
|
||||||
|
const operationPermission = getOperationPermissions(response);
|
||||||
|
setEntitiesPermission((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[entityId]: operationPermission,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return operationPermission;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return error as AxiosError;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
/**
|
/**
|
||||||
* Only fetch permission if user is logged In
|
* Only fetch permission if user is logged In
|
||||||
@ -78,7 +113,11 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
|||||||
}, [currentUser]);
|
}, [currentUser]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PermissionContext.Provider value={{ permissions }}>
|
<PermissionContext.Provider
|
||||||
|
value={{
|
||||||
|
permissions,
|
||||||
|
getEntityPermission: fetchEntityPermission,
|
||||||
|
}}>
|
||||||
{children}
|
{children}
|
||||||
</PermissionContext.Provider>
|
</PermissionContext.Provider>
|
||||||
);
|
);
|
||||||
|
@ -11,8 +11,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Card, Col, Row } from 'antd';
|
import { Card, Col, Row, Tooltip } from 'antd';
|
||||||
import React, { Fragment } from 'react';
|
import { isEmpty } from 'lodash';
|
||||||
|
import React, { Fragment, useMemo } from 'react';
|
||||||
import { Link, useHistory } from 'react-router-dom';
|
import { Link, useHistory } from 'react-router-dom';
|
||||||
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
||||||
import {
|
import {
|
||||||
@ -20,26 +21,32 @@ import {
|
|||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
TITLE_FOR_NON_ADMIN_ACTION,
|
TITLE_FOR_NON_ADMIN_ACTION,
|
||||||
} from '../../constants/constants';
|
} from '../../constants/constants';
|
||||||
|
import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
|
||||||
import {
|
import {
|
||||||
NoDataFoundPlaceHolder,
|
NoDataFoundPlaceHolder,
|
||||||
servicesDisplayName,
|
servicesDisplayName,
|
||||||
} from '../../constants/services.const';
|
} from '../../constants/services.const';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
|
import { Operation } from '../../generated/entity/policies/policy';
|
||||||
import { Paging } from '../../generated/type/paging';
|
import { Paging } from '../../generated/type/paging';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
|
||||||
import { ServicesType } from '../../interface/service.interface';
|
import { ServicesType } from '../../interface/service.interface';
|
||||||
import {
|
import {
|
||||||
getEntityName,
|
getEntityName,
|
||||||
getServiceLogo,
|
getServiceLogo,
|
||||||
showPagination,
|
showPagination,
|
||||||
} from '../../utils/CommonUtils';
|
} from '../../utils/CommonUtils';
|
||||||
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
import { getAddServicePath } from '../../utils/RouterUtils';
|
import { getAddServicePath } from '../../utils/RouterUtils';
|
||||||
import { getOptionalFields } from '../../utils/ServiceUtils';
|
import {
|
||||||
|
getOptionalFields,
|
||||||
|
getResourceEntityFromServiceCategory,
|
||||||
|
} from '../../utils/ServiceUtils';
|
||||||
import { Button } from '../buttons/Button/Button';
|
import { Button } from '../buttons/Button/Button';
|
||||||
import NextPrevious from '../common/next-previous/NextPrevious';
|
import NextPrevious from '../common/next-previous/NextPrevious';
|
||||||
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
||||||
import RichTextEditorPreviewer from '../common/rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../common/rich-text-editor/RichTextEditorPreviewer';
|
||||||
import { leftPanelAntCardStyle } from '../containers/PageLayout';
|
import { leftPanelAntCardStyle } from '../containers/PageLayout';
|
||||||
|
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
||||||
|
|
||||||
interface ServicesProps {
|
interface ServicesProps {
|
||||||
serviceData: ServicesType[];
|
serviceData: ServicesType[];
|
||||||
@ -56,33 +63,49 @@ const Services = ({
|
|||||||
currentPage,
|
currentPage,
|
||||||
onPageChange,
|
onPageChange,
|
||||||
}: ServicesProps) => {
|
}: ServicesProps) => {
|
||||||
const { isAdminUser } = useAuth();
|
|
||||||
const { isAuthDisabled } = useAuthContext();
|
const { isAuthDisabled } = useAuthContext();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const handleAddServiceClick = () => {
|
const handleAddServiceClick = () => {
|
||||||
history.push(getAddServicePath(serviceName));
|
history.push(getAddServicePath(serviceName));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
|
const addServicePermission = useMemo(
|
||||||
|
() =>
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
getResourceEntityFromServiceCategory(serviceName),
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
[permissions, serviceName]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row data-testid="services-container">
|
<Row data-testid="services-container">
|
||||||
{serviceData.length ? (
|
{serviceData.length ? (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<div className="tw-flex tw-justify-end" data-testid="header">
|
<div className="tw-flex tw-justify-end" data-testid="header">
|
||||||
<NonAdminAction
|
<Tooltip
|
||||||
position="bottom"
|
placement="left"
|
||||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
title={
|
||||||
|
addServicePermission
|
||||||
|
? 'Add Service'
|
||||||
|
: NO_PERMISSION_FOR_ACTION
|
||||||
|
}>
|
||||||
<Button
|
<Button
|
||||||
className="tw-h-8 tw-rounded tw-mb-2"
|
className="tw-h-8 tw-rounded tw-mb-2"
|
||||||
data-testid="add-new-service-button"
|
data-testid="add-new-service-button"
|
||||||
disabled={!isAdminUser && !isAuthDisabled}
|
disabled={!addServicePermission && !isAuthDisabled}
|
||||||
size="small"
|
size="small"
|
||||||
theme="primary"
|
theme="primary"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={handleAddServiceClick}>
|
onClick={handleAddServiceClick}>
|
||||||
Add New Service
|
Add New Service
|
||||||
</Button>
|
</Button>
|
||||||
</NonAdminAction>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
@ -11,28 +11,28 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Card, Col, Row, Select, Space } from 'antd';
|
import { Card, Col, Row, Select, Space, Tooltip } from 'antd';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { isNil } from 'lodash';
|
import { isEmpty, isNil } from 'lodash';
|
||||||
import React, { FC, useEffect, useMemo, useState } from 'react';
|
import React, { FC, useEffect, useMemo, useState } from 'react';
|
||||||
|
import { PAGE_SIZE } from '../../constants/constants';
|
||||||
import {
|
import {
|
||||||
PAGE_SIZE,
|
NO_PERMISSION_FOR_ACTION,
|
||||||
TITLE_FOR_NON_ADMIN_ACTION,
|
|
||||||
} from '../../constants/constants';
|
|
||||||
import {
|
|
||||||
SLACK_LISTING_TEXT,
|
SLACK_LISTING_TEXT,
|
||||||
WEBHOOK_LISTING_TEXT,
|
WEBHOOK_LISTING_TEXT,
|
||||||
} from '../../constants/HelperTextUtil';
|
} from '../../constants/HelperTextUtil';
|
||||||
import { WebhookType } from '../../generated/api/events/createWebhook';
|
import { WebhookType } from '../../generated/api/events/createWebhook';
|
||||||
import { Webhook } from '../../generated/entity/events/webhook';
|
import { Webhook } from '../../generated/entity/events/webhook';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { Operation } from '../../generated/entity/policies/policy';
|
||||||
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
import { statuses } from '../AddWebhook/WebhookConstants';
|
import { statuses } from '../AddWebhook/WebhookConstants';
|
||||||
import { Button } from '../buttons/Button/Button';
|
import { Button } from '../buttons/Button/Button';
|
||||||
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
|
import ErrorPlaceHolder from '../common/error-with-placeholder/ErrorPlaceHolder';
|
||||||
import NextPrevious from '../common/next-previous/NextPrevious';
|
import NextPrevious from '../common/next-previous/NextPrevious';
|
||||||
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
|
||||||
import WebhookDataCard from '../common/webhook-data-card/WebhookDataCard';
|
import WebhookDataCard from '../common/webhook-data-card/WebhookDataCard';
|
||||||
import { leftPanelAntCardStyle } from '../containers/PageLayout';
|
import { leftPanelAntCardStyle } from '../containers/PageLayout';
|
||||||
|
import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface';
|
||||||
import { WebhooksV1Props } from './WebhooksV1.interface';
|
import { WebhooksV1Props } from './WebhooksV1.interface';
|
||||||
import './webhookV1.less';
|
import './webhookV1.less';
|
||||||
|
|
||||||
@ -47,9 +47,17 @@ const WebhooksV1: FC<WebhooksV1Props> = ({
|
|||||||
onStatusFilter,
|
onStatusFilter,
|
||||||
currentPage,
|
currentPage,
|
||||||
}) => {
|
}) => {
|
||||||
const { isAuthDisabled, isAdminUser } = useAuth();
|
|
||||||
const [filteredData, setFilteredData] = useState<Array<Webhook>>(data);
|
const [filteredData, setFilteredData] = useState<Array<Webhook>>(data);
|
||||||
|
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
|
const addWebhookPermission = useMemo(
|
||||||
|
() =>
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(Operation.Create, ResourceEntity.WEBHOOK, permissions),
|
||||||
|
[permissions]
|
||||||
|
);
|
||||||
|
|
||||||
const getFilteredWebhooks = () => {
|
const getFilteredWebhooks = () => {
|
||||||
return selectedStatus.length
|
return selectedStatus.length
|
||||||
? data.filter(
|
? data.filter(
|
||||||
@ -79,21 +87,22 @@ const WebhooksV1: FC<WebhooksV1Props> = ({
|
|||||||
<ErrorPlaceHolder>
|
<ErrorPlaceHolder>
|
||||||
<p className="tw-text-center">{message}</p>
|
<p className="tw-text-center">{message}</p>
|
||||||
<p className="tw-text-center">
|
<p className="tw-text-center">
|
||||||
<NonAdminAction
|
<Tooltip
|
||||||
position="bottom"
|
placement="left"
|
||||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
title={
|
||||||
|
addWebhookPermission ? 'Add Webhook' : NO_PERMISSION_FOR_ACTION
|
||||||
|
}>
|
||||||
<Button
|
<Button
|
||||||
className={classNames('tw-h-8 tw-rounded tw-my-3', {
|
className={classNames('tw-h-8 tw-rounded tw-my-3')}
|
||||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
|
||||||
})}
|
|
||||||
data-testid="add-webhook-button"
|
data-testid="add-webhook-button"
|
||||||
|
disabled={!addWebhookPermission}
|
||||||
size="small"
|
size="small"
|
||||||
theme="primary"
|
theme="primary"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={onAddWebhook}>
|
onClick={onAddWebhook}>
|
||||||
Add {webhookType === WebhookType.Slack ? 'Slack' : 'Webhook'}
|
Add {webhookType === WebhookType.Slack ? 'Slack' : 'Webhook'}
|
||||||
</Button>
|
</Button>
|
||||||
</NonAdminAction>
|
</Tooltip>
|
||||||
</p>
|
</p>
|
||||||
</ErrorPlaceHolder>
|
</ErrorPlaceHolder>
|
||||||
);
|
);
|
||||||
@ -131,14 +140,17 @@ const WebhooksV1: FC<WebhooksV1Props> = ({
|
|||||||
className="tw-w-full tw-justify-end"
|
className="tw-w-full tw-justify-end"
|
||||||
size={16}>
|
size={16}>
|
||||||
{filteredData.length > 0 && (
|
{filteredData.length > 0 && (
|
||||||
<NonAdminAction
|
<Tooltip
|
||||||
position="bottom"
|
placement="left"
|
||||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
title={
|
||||||
|
addWebhookPermission
|
||||||
|
? 'Add Webhook'
|
||||||
|
: NO_PERMISSION_FOR_ACTION
|
||||||
|
}>
|
||||||
<Button
|
<Button
|
||||||
className={classNames('tw-h-8 tw-rounded ', {
|
className={classNames('tw-h-8 tw-rounded ')}
|
||||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
|
||||||
})}
|
|
||||||
data-testid="add-webhook-button"
|
data-testid="add-webhook-button"
|
||||||
|
disabled={!addWebhookPermission}
|
||||||
size="small"
|
size="small"
|
||||||
theme="primary"
|
theme="primary"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
@ -146,7 +158,7 @@ const WebhooksV1: FC<WebhooksV1Props> = ({
|
|||||||
Add{' '}
|
Add{' '}
|
||||||
{webhookType === WebhookType.Slack ? 'Slack' : 'Webhook'}
|
{webhookType === WebhookType.Slack ? 'Slack' : 'Webhook'}
|
||||||
</Button>
|
</Button>
|
||||||
</NonAdminAction>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -36,3 +36,8 @@ export const ADD_POLICY_TEXT = `
|
|||||||
Policies are assigned to Teams. In OpenMetadata, a Policy is a collection of Rules, which define access based on certain conditions. We support rich SpEL (Spring Expression Language) based conditions. All the operations supported by an Entity are published. Use these fine grained operations to define the conditional Rules for each Policy.
|
Policies are assigned to Teams. In OpenMetadata, a Policy is a collection of Rules, which define access based on certain conditions. We support rich SpEL (Spring Expression Language) based conditions. All the operations supported by an Entity are published. Use these fine grained operations to define the conditional Rules for each Policy.
|
||||||
Create well-defined policies based on conditional rules to build rich access control roles.
|
Create well-defined policies based on conditional rules to build rich access control roles.
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const NO_PERMISSION_FOR_ACTION =
|
||||||
|
'You do not have permissions to perform this action.';
|
||||||
|
|
||||||
|
export const NO_PERMISSION_TO_VIEW = 'You do not have permission to view data';
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button, Col, Empty, Row, Space, Switch } from 'antd';
|
import { Button, Col, Row, Space, Switch } from 'antd';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import BotListV1 from '../../components/BotListV1/BotListV1.component';
|
import BotListV1 from '../../components/BotListV1/BotListV1.component';
|
||||||
@ -19,7 +19,7 @@ import { usePermissionProvider } from '../../components/PermissionProvider/Permi
|
|||||||
import { ResourceEntity } from '../../components/PermissionProvider/PermissionProvider.interface';
|
import { ResourceEntity } from '../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { getCreateUserPath } from '../../constants/constants';
|
import { getCreateUserPath } from '../../constants/constants';
|
||||||
import { Operation } from '../../generated/entity/policies/accessControl/rule';
|
import { Operation } from '../../generated/entity/policies/accessControl/rule';
|
||||||
import { checkPemission } from '../../utils/PermissionsUtils';
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
|
|
||||||
export const BotsPageV1 = () => {
|
export const BotsPageV1 = () => {
|
||||||
const { permissions } = usePermissionProvider();
|
const { permissions } = usePermissionProvider();
|
||||||
@ -34,13 +34,7 @@ export const BotsPageV1 = () => {
|
|||||||
setShowDeleted(checked);
|
setShowDeleted(checked);
|
||||||
};
|
};
|
||||||
|
|
||||||
const viewAllPermission = checkPemission(
|
const createPermission = checkPermission(
|
||||||
Operation.ViewAll,
|
|
||||||
ResourceEntity.BOT,
|
|
||||||
permissions
|
|
||||||
);
|
|
||||||
|
|
||||||
const createPermission = checkPemission(
|
|
||||||
Operation.Create,
|
Operation.Create,
|
||||||
ResourceEntity.BOT,
|
ResourceEntity.BOT,
|
||||||
permissions
|
permissions
|
||||||
@ -48,35 +42,29 @@ export const BotsPageV1 = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
{viewAllPermission ? (
|
<Col flex={1} />
|
||||||
<>
|
<Col>
|
||||||
<Col flex={1} />
|
<Space size={16}>
|
||||||
<Col>
|
<Space align="end" size={5}>
|
||||||
<Space size={16}>
|
<Switch
|
||||||
<Space align="end" size={5}>
|
checked={showDeleted}
|
||||||
<Switch
|
id="switch-deleted"
|
||||||
checked={showDeleted}
|
size="small"
|
||||||
id="switch-deleted"
|
onClick={handleShowDeleted}
|
||||||
size="small"
|
/>
|
||||||
onClick={handleShowDeleted}
|
<label htmlFor="switch-deleted">Show deleted</label>
|
||||||
/>
|
</Space>
|
||||||
<label htmlFor="switch-deleted">Show deleted</label>
|
|
||||||
</Space>
|
|
||||||
|
|
||||||
{createPermission && (
|
{createPermission && (
|
||||||
<Button type="primary" onClick={handleAddBotClick}>
|
<Button type="primary" onClick={handleAddBotClick}>
|
||||||
Add Bot
|
Add Bot
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<BotListV1 showDeleted={showDeleted} />
|
<BotListV1 showDeleted={showDeleted} />
|
||||||
</Col>
|
</Col>
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Empty description="You do not have permission to view data" />
|
|
||||||
)}
|
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,6 @@ import { LoadingState } from 'Models';
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useHistory, useParams } from 'react-router-dom';
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
import AppState from '../../AppState';
|
import AppState from '../../AppState';
|
||||||
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
|
||||||
import { createBot } from '../../axiosAPIs/botsAPI';
|
import { createBot } from '../../axiosAPIs/botsAPI';
|
||||||
import { createUser } from '../../axiosAPIs/userAPI';
|
import { createUser } from '../../axiosAPIs/userAPI';
|
||||||
import PageContainerV1 from '../../components/containers/PageContainerV1';
|
import PageContainerV1 from '../../components/containers/PageContainerV1';
|
||||||
@ -30,14 +29,11 @@ import { EntityType } from '../../enums/entity.enum';
|
|||||||
import { CreateUser } from '../../generated/api/teams/createUser';
|
import { CreateUser } from '../../generated/api/teams/createUser';
|
||||||
import { Bot } from '../../generated/entity/bot';
|
import { Bot } from '../../generated/entity/bot';
|
||||||
import { Role } from '../../generated/entity/teams/role';
|
import { Role } from '../../generated/entity/teams/role';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
|
||||||
import jsonData from '../../jsons/en';
|
import jsonData from '../../jsons/en';
|
||||||
import { getSettingPath } from '../../utils/RouterUtils';
|
import { getSettingPath } from '../../utils/RouterUtils';
|
||||||
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
||||||
|
|
||||||
const CreateUserPage = () => {
|
const CreateUserPage = () => {
|
||||||
const { isAdminUser } = useAuth();
|
|
||||||
const { isAuthDisabled } = useAuthContext();
|
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
const [roles, setRoles] = useState<Array<Role>>([]);
|
const [roles, setRoles] = useState<Array<Role>>([]);
|
||||||
@ -128,7 +124,6 @@ const CreateUserPage = () => {
|
|||||||
<PageContainerV1>
|
<PageContainerV1>
|
||||||
<div className="tw-self-center">
|
<div className="tw-self-center">
|
||||||
<CreateUserComponent
|
<CreateUserComponent
|
||||||
allowAccess={isAdminUser || isAuthDisabled}
|
|
||||||
forceBot={Boolean(bot)}
|
forceBot={Boolean(bot)}
|
||||||
roles={roles}
|
roles={roles}
|
||||||
saveState={status}
|
saveState={status}
|
||||||
|
@ -11,10 +11,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Col, Row } from 'antd';
|
import { Col, Empty, Row } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { compare } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
import { isUndefined } from 'lodash';
|
import { isEmpty, isUndefined } from 'lodash';
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { useHistory, useParams } from 'react-router-dom';
|
import { useHistory, useParams } from 'react-router-dom';
|
||||||
import { getTypeByFQN, updateType } from '../../axiosAPIs/metadataTypeAPI';
|
import { getTypeByFQN, updateType } from '../../axiosAPIs/metadataTypeAPI';
|
||||||
@ -23,11 +23,16 @@ import ErrorPlaceHolder from '../../components/common/error-with-placeholder/Err
|
|||||||
import TabsPane from '../../components/common/TabsPane/TabsPane';
|
import TabsPane from '../../components/common/TabsPane/TabsPane';
|
||||||
import { CustomPropertyTable } from '../../components/CustomEntityDetail/CustomPropertyTable';
|
import { CustomPropertyTable } from '../../components/CustomEntityDetail/CustomPropertyTable';
|
||||||
import Loader from '../../components/Loader/Loader';
|
import Loader from '../../components/Loader/Loader';
|
||||||
|
import { usePermissionProvider } from '../../components/PermissionProvider/PermissionProvider';
|
||||||
import SchemaEditor from '../../components/schema-editor/SchemaEditor';
|
import SchemaEditor from '../../components/schema-editor/SchemaEditor';
|
||||||
import { getAddCustomPropertyPath } from '../../constants/constants';
|
import { getAddCustomPropertyPath } from '../../constants/constants';
|
||||||
import { customAttributesPath } from '../../constants/globalSettings.constants';
|
import { customAttributesPath } from '../../constants/globalSettings.constants';
|
||||||
|
import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil';
|
||||||
|
import { Operation } from '../../generated/entity/policies/policy';
|
||||||
import { Type } from '../../generated/entity/type';
|
import { Type } from '../../generated/entity/type';
|
||||||
import jsonData from '../../jsons/en';
|
import jsonData from '../../jsons/en';
|
||||||
|
import { getResourceEntityFromCustomProperty } from '../../utils/CustomPropertyUtils';
|
||||||
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
import './CustomPropertiesPageV1.less';
|
import './CustomPropertiesPageV1.less';
|
||||||
|
|
||||||
@ -44,6 +49,19 @@ const CustomEntityDetailV1 = () => {
|
|||||||
const tabAttributePath =
|
const tabAttributePath =
|
||||||
customAttributesPath[tab as keyof typeof customAttributesPath];
|
customAttributesPath[tab as keyof typeof customAttributesPath];
|
||||||
|
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
|
const viewPermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
getResourceEntityFromCustomProperty(tab),
|
||||||
|
permissions
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, [permissions, tab]);
|
||||||
|
|
||||||
const fetchTypeDetail = async (typeFQN: string) => {
|
const fetchTypeDetail = async (typeFQN: string) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
@ -120,7 +138,7 @@ const CustomEntityDetailV1 = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return viewPermission ? (
|
||||||
<Row
|
<Row
|
||||||
className="tw-my-2"
|
className="tw-my-2"
|
||||||
data-testid="custom-entity-container"
|
data-testid="custom-entity-container"
|
||||||
@ -162,6 +180,12 @@ const CustomEntityDetailV1 = () => {
|
|||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
) : (
|
||||||
|
<Row>
|
||||||
|
<Col span={24}>
|
||||||
|
<Empty description={NO_PERMISSION_TO_VIEW} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,15 +41,18 @@ import Description from '../../../components/common/description/Description';
|
|||||||
import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
||||||
import TitleBreadcrumb from '../../../components/common/title-breadcrumb/title-breadcrumb.component';
|
import TitleBreadcrumb from '../../../components/common/title-breadcrumb/title-breadcrumb.component';
|
||||||
import Loader from '../../../components/Loader/Loader';
|
import Loader from '../../../components/Loader/Loader';
|
||||||
|
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import {
|
import {
|
||||||
GlobalSettingOptions,
|
GlobalSettingOptions,
|
||||||
GlobalSettingsMenuCategory,
|
GlobalSettingsMenuCategory,
|
||||||
} from '../../../constants/globalSettings.constants';
|
} from '../../../constants/globalSettings.constants';
|
||||||
import { EntityType } from '../../../enums/entity.enum';
|
import { EntityType } from '../../../enums/entity.enum';
|
||||||
import { Rule } from '../../../generated/api/policies/createPolicy';
|
import { Rule } from '../../../generated/api/policies/createPolicy';
|
||||||
import { Policy } from '../../../generated/entity/policies/policy';
|
import { Operation, Policy } from '../../../generated/entity/policies/policy';
|
||||||
import { EntityReference } from '../../../generated/type/entityReference';
|
import { EntityReference } from '../../../generated/type/entityReference';
|
||||||
import { getEntityName } from '../../../utils/CommonUtils';
|
import { getEntityName } from '../../../utils/CommonUtils';
|
||||||
|
import { checkPermission } from '../../../utils/PermissionsUtils';
|
||||||
import {
|
import {
|
||||||
getAddPolicyRulePath,
|
getAddPolicyRulePath,
|
||||||
getEditPolicyRulePath,
|
getEditPolicyRulePath,
|
||||||
@ -147,6 +150,7 @@ const List = ({
|
|||||||
const PoliciesDetailPage = () => {
|
const PoliciesDetailPage = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { fqn } = useParams<{ fqn: string }>();
|
const { fqn } = useParams<{ fqn: string }>();
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
const [policy, setPolicy] = useState<Policy>({} as Policy);
|
const [policy, setPolicy] = useState<Policy>({} as Policy);
|
||||||
const [isLoading, setLoading] = useState<boolean>(false);
|
const [isLoading, setLoading] = useState<boolean>(false);
|
||||||
@ -159,6 +163,17 @@ const PoliciesDetailPage = () => {
|
|||||||
GlobalSettingOptions.POLICIES
|
GlobalSettingOptions.POLICIES
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const editDescriptionPermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(
|
||||||
|
Operation.EditDescription,
|
||||||
|
ResourceEntity.ROLE,
|
||||||
|
permissions
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
const breadcrumb = useMemo(
|
const breadcrumb = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@ -393,6 +408,7 @@ const PoliciesDetailPage = () => {
|
|||||||
entityFqn={policy.fullyQualifiedName}
|
entityFqn={policy.fullyQualifiedName}
|
||||||
entityName={getEntityName(policy)}
|
entityName={getEntityName(policy)}
|
||||||
entityType={EntityType.POLICY}
|
entityType={EntityType.POLICY}
|
||||||
|
hasEditAccess={editDescriptionPermission}
|
||||||
isEdit={editDescription}
|
isEdit={editDescription}
|
||||||
onCancel={() => setEditDescription(false)}
|
onCancel={() => setEditDescription(false)}
|
||||||
onDescriptionEdit={() => setEditDescription(true)}
|
onDescriptionEdit={() => setEditDescription(true)}
|
||||||
|
@ -11,18 +11,24 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button, Popover, Space, Table, Tag } from 'antd';
|
import { Button, Popover, Space, Table, Tag, Tooltip } from 'antd';
|
||||||
import { ColumnsType } from 'antd/lib/table';
|
import { ColumnsType } from 'antd/lib/table';
|
||||||
import { isUndefined, uniqueId } from 'lodash';
|
import { isEmpty, isUndefined, uniqueId } from 'lodash';
|
||||||
import React, { FC, useMemo, useState } from 'react';
|
import React, { FC, useMemo, useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import DeleteWidgetModal from '../../../components/common/DeleteWidget/DeleteWidgetModal';
|
import DeleteWidgetModal from '../../../components/common/DeleteWidget/DeleteWidgetModal';
|
||||||
import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
||||||
|
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
|
import {
|
||||||
|
NO_PERMISSION_FOR_ACTION,
|
||||||
|
NO_PERMISSION_TO_VIEW,
|
||||||
|
} from '../../../constants/HelperTextUtil';
|
||||||
import { EntityType } from '../../../enums/entity.enum';
|
import { EntityType } from '../../../enums/entity.enum';
|
||||||
import { Policy } from '../../../generated/entity/policies/policy';
|
import { Operation, Policy } from '../../../generated/entity/policies/policy';
|
||||||
import { Paging } from '../../../generated/type/paging';
|
import { Paging } from '../../../generated/type/paging';
|
||||||
import { getEntityName } from '../../../utils/CommonUtils';
|
import { getEntityName } from '../../../utils/CommonUtils';
|
||||||
import { LIST_CAP } from '../../../utils/PermissionsUtils';
|
import { checkPermission, LIST_CAP } from '../../../utils/PermissionsUtils';
|
||||||
import {
|
import {
|
||||||
getPolicyWithFqnPath,
|
getPolicyWithFqnPath,
|
||||||
getRoleWithFqnPath,
|
getRoleWithFqnPath,
|
||||||
@ -36,6 +42,23 @@ interface PolicyListProps {
|
|||||||
|
|
||||||
const PoliciesList: FC<PolicyListProps> = ({ policies, fetchPolicies }) => {
|
const PoliciesList: FC<PolicyListProps> = ({ policies, fetchPolicies }) => {
|
||||||
const [selectedPolicy, setSelectedPolicy] = useState<Policy>();
|
const [selectedPolicy, setSelectedPolicy] = useState<Policy>();
|
||||||
|
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
|
const deletePolicyPermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(Operation.Delete, ResourceEntity.POLICY, permissions)
|
||||||
|
);
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
|
const viewRolePermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(Operation.ViewAll, ResourceEntity.ROLE, permissions)
|
||||||
|
);
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
const columns: ColumnsType<Policy> = useMemo(() => {
|
const columns: ColumnsType<Policy> = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -71,27 +94,39 @@ const PoliciesList: FC<PolicyListProps> = ({ policies, fetchPolicies }) => {
|
|||||||
|
|
||||||
return record.roles?.length ? (
|
return record.roles?.length ? (
|
||||||
<Space wrap data-testid="role-link" size={4}>
|
<Space wrap data-testid="role-link" size={4}>
|
||||||
{record.roles.slice(0, LIST_CAP).map((role) => (
|
{record.roles.slice(0, LIST_CAP).map((role) =>
|
||||||
<Link
|
viewRolePermission ? (
|
||||||
key={uniqueId()}
|
<Link
|
||||||
to={getRoleWithFqnPath(role.fullyQualifiedName || '')}>
|
key={uniqueId()}
|
||||||
{getEntityName(role)}
|
to={getRoleWithFqnPath(role.fullyQualifiedName || '')}>
|
||||||
</Link>
|
{getEntityName(role)}
|
||||||
))}
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Tooltip title={NO_PERMISSION_TO_VIEW}>
|
||||||
|
{getEntityName(role)}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
)}
|
||||||
{hasMore && (
|
{hasMore && (
|
||||||
<Popover
|
<Popover
|
||||||
className="tw-cursor-pointer"
|
className="tw-cursor-pointer"
|
||||||
content={
|
content={
|
||||||
<Space wrap size={4}>
|
<Space wrap size={4}>
|
||||||
{record.roles.slice(LIST_CAP).map((role) => (
|
{record.roles.slice(LIST_CAP).map((role) =>
|
||||||
<Link
|
viewRolePermission ? (
|
||||||
key={uniqueId()}
|
<Link
|
||||||
to={getRoleWithFqnPath(
|
key={uniqueId()}
|
||||||
role.fullyQualifiedName || ''
|
to={getRoleWithFqnPath(
|
||||||
)}>
|
role.fullyQualifiedName || ''
|
||||||
{getEntityName(role)}
|
)}>
|
||||||
</Link>
|
{getEntityName(role)}
|
||||||
))}
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Tooltip title={NO_PERMISSION_TO_VIEW}>
|
||||||
|
{getEntityName(role)}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
overlayClassName="tw-w-40 tw-text-center"
|
overlayClassName="tw-w-40 tw-text-center"
|
||||||
@ -114,12 +149,19 @@ const PoliciesList: FC<PolicyListProps> = ({ policies, fetchPolicies }) => {
|
|||||||
key: 'actions',
|
key: 'actions',
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Tooltip
|
||||||
data-testid={`delete-action-${getEntityName(record)}`}
|
placement="left"
|
||||||
type="text"
|
title={
|
||||||
onClick={() => setSelectedPolicy(record)}>
|
deletePolicyPermission ? 'Delete' : NO_PERMISSION_FOR_ACTION
|
||||||
<SVGIcons alt="delete" icon={Icons.DELETE} width="18px" />
|
}>
|
||||||
</Button>
|
<Button
|
||||||
|
data-testid={`delete-action-${getEntityName(record)}`}
|
||||||
|
disabled={!deletePolicyPermission}
|
||||||
|
type="text"
|
||||||
|
onClick={() => setSelectedPolicy(record)}>
|
||||||
|
<SVGIcons alt="delete" icon={Icons.DELETE} width="18px" />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -135,7 +177,7 @@ const PoliciesList: FC<PolicyListProps> = ({ policies, fetchPolicies }) => {
|
|||||||
pagination={false}
|
pagination={false}
|
||||||
size="middle"
|
size="middle"
|
||||||
/>
|
/>
|
||||||
{selectedPolicy && (
|
{selectedPolicy && deletePolicyPermission && (
|
||||||
<DeleteWidgetModal
|
<DeleteWidgetModal
|
||||||
afterDeleteAction={fetchPolicies}
|
afterDeleteAction={fetchPolicies}
|
||||||
allowSoftDelete={false}
|
allowSoftDelete={false}
|
||||||
|
@ -11,20 +11,25 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button, Col, Row, Space } from 'antd';
|
import { Button, Col, Row, Space, Tooltip } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import React, { useEffect, useState } from 'react';
|
import { isEmpty } from 'lodash';
|
||||||
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { getPolicies } from '../../../axiosAPIs/rolesAPIV1';
|
import { getPolicies } from '../../../axiosAPIs/rolesAPIV1';
|
||||||
import NextPrevious from '../../../components/common/next-previous/NextPrevious';
|
import NextPrevious from '../../../components/common/next-previous/NextPrevious';
|
||||||
import Loader from '../../../components/Loader/Loader';
|
import Loader from '../../../components/Loader/Loader';
|
||||||
|
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import {
|
import {
|
||||||
INITIAL_PAGING_VALUE,
|
INITIAL_PAGING_VALUE,
|
||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
ROUTES,
|
ROUTES,
|
||||||
} from '../../../constants/constants';
|
} from '../../../constants/constants';
|
||||||
import { Policy } from '../../../generated/entity/policies/policy';
|
import { NO_PERMISSION_FOR_ACTION } from '../../../constants/HelperTextUtil';
|
||||||
|
import { Operation, Policy } from '../../../generated/entity/policies/policy';
|
||||||
import { Paging } from '../../../generated/type/paging';
|
import { Paging } from '../../../generated/type/paging';
|
||||||
|
import { checkPermission } from '../../../utils/PermissionsUtils';
|
||||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||||
import PoliciesList from './PoliciesList';
|
import PoliciesList from './PoliciesList';
|
||||||
import './PoliciesList.less';
|
import './PoliciesList.less';
|
||||||
@ -36,6 +41,15 @@ const PoliciesListPage = () => {
|
|||||||
const [paging, setPaging] = useState<Paging>();
|
const [paging, setPaging] = useState<Paging>();
|
||||||
const [currentPage, setCurrentPage] = useState<number>(INITIAL_PAGING_VALUE);
|
const [currentPage, setCurrentPage] = useState<number>(INITIAL_PAGING_VALUE);
|
||||||
|
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
|
const addPolicyPermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(Operation.Create, ResourceEntity.POLICY, permissions)
|
||||||
|
);
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
const fetchPolicies = async (paging?: Paging) => {
|
const fetchPolicies = async (paging?: Paging) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
@ -73,12 +87,19 @@ const PoliciesListPage = () => {
|
|||||||
<Row className="policies-list-container" gutter={[16, 16]}>
|
<Row className="policies-list-container" gutter={[16, 16]}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Space align="center" className="tw-w-full tw-justify-end" size={16}>
|
<Space align="center" className="tw-w-full tw-justify-end" size={16}>
|
||||||
<Button
|
<Tooltip
|
||||||
data-testid="add-policy"
|
placement="left"
|
||||||
type="primary"
|
title={
|
||||||
onClick={handleAddPolicy}>
|
addPolicyPermission ? 'Add Policy' : NO_PERMISSION_FOR_ACTION
|
||||||
Add Policy
|
}>
|
||||||
</Button>
|
<Button
|
||||||
|
data-testid="add-policy"
|
||||||
|
disabled={!addPolicyPermission}
|
||||||
|
type="primary"
|
||||||
|
onClick={handleAddPolicy}>
|
||||||
|
Add Policy
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
</Space>
|
</Space>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
@ -26,14 +26,18 @@ import Description from '../../../components/common/description/Description';
|
|||||||
import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
||||||
import TitleBreadcrumb from '../../../components/common/title-breadcrumb/title-breadcrumb.component';
|
import TitleBreadcrumb from '../../../components/common/title-breadcrumb/title-breadcrumb.component';
|
||||||
import Loader from '../../../components/Loader/Loader';
|
import Loader from '../../../components/Loader/Loader';
|
||||||
|
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { getUserPath } from '../../../constants/constants';
|
import { getUserPath } from '../../../constants/constants';
|
||||||
import {
|
import {
|
||||||
GlobalSettingOptions,
|
GlobalSettingOptions,
|
||||||
GlobalSettingsMenuCategory,
|
GlobalSettingsMenuCategory,
|
||||||
} from '../../../constants/globalSettings.constants';
|
} from '../../../constants/globalSettings.constants';
|
||||||
import { EntityType } from '../../../enums/entity.enum';
|
import { EntityType } from '../../../enums/entity.enum';
|
||||||
|
import { Operation } from '../../../generated/entity/policies/policy';
|
||||||
import { Role } from '../../../generated/entity/teams/role';
|
import { Role } from '../../../generated/entity/teams/role';
|
||||||
import { getEntityName } from '../../../utils/CommonUtils';
|
import { getEntityName } from '../../../utils/CommonUtils';
|
||||||
|
import { checkPermission } from '../../../utils/PermissionsUtils';
|
||||||
import {
|
import {
|
||||||
getPolicyWithFqnPath,
|
getPolicyWithFqnPath,
|
||||||
getSettingPath,
|
getSettingPath,
|
||||||
@ -139,6 +143,7 @@ const List = ({
|
|||||||
|
|
||||||
const RolesDetailPage = () => {
|
const RolesDetailPage = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
const { fqn } = useParams<{ fqn: string }>();
|
const { fqn } = useParams<{ fqn: string }>();
|
||||||
|
|
||||||
const [role, setRole] = useState<Role>({} as Role);
|
const [role, setRole] = useState<Role>({} as Role);
|
||||||
@ -154,6 +159,17 @@ const RolesDetailPage = () => {
|
|||||||
GlobalSettingOptions.ROLES
|
GlobalSettingOptions.ROLES
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const editDescriptionPermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(
|
||||||
|
Operation.EditDescription,
|
||||||
|
ResourceEntity.ROLE,
|
||||||
|
permissions
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
const breadcrumb = useMemo(
|
const breadcrumb = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@ -319,6 +335,7 @@ const RolesDetailPage = () => {
|
|||||||
entityFqn={role.fullyQualifiedName}
|
entityFqn={role.fullyQualifiedName}
|
||||||
entityName={getEntityName(role)}
|
entityName={getEntityName(role)}
|
||||||
entityType={EntityType.ROLE}
|
entityType={EntityType.ROLE}
|
||||||
|
hasEditAccess={editDescriptionPermission}
|
||||||
isEdit={editDescription}
|
isEdit={editDescription}
|
||||||
onCancel={() => setEditDescription(false)}
|
onCancel={() => setEditDescription(false)}
|
||||||
onDescriptionEdit={() => setEditDescription(true)}
|
onDescriptionEdit={() => setEditDescription(true)}
|
||||||
|
@ -11,18 +11,25 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button, Popover, Space, Table, Tag } from 'antd';
|
import { Button, Popover, Space, Table, Tag, Tooltip } from 'antd';
|
||||||
import { ColumnsType } from 'antd/lib/table';
|
import { ColumnsType } from 'antd/lib/table';
|
||||||
import { isUndefined, uniqueId } from 'lodash';
|
import { isEmpty, isUndefined, uniqueId } from 'lodash';
|
||||||
import React, { FC, useMemo, useState } from 'react';
|
import React, { FC, useMemo, useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import DeleteWidgetModal from '../../../components/common/DeleteWidget/DeleteWidgetModal';
|
import DeleteWidgetModal from '../../../components/common/DeleteWidget/DeleteWidgetModal';
|
||||||
import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
|
||||||
|
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
|
import {
|
||||||
|
NO_PERMISSION_FOR_ACTION,
|
||||||
|
NO_PERMISSION_TO_VIEW,
|
||||||
|
} from '../../../constants/HelperTextUtil';
|
||||||
import { EntityType } from '../../../enums/entity.enum';
|
import { EntityType } from '../../../enums/entity.enum';
|
||||||
|
import { Operation } from '../../../generated/entity/policies/policy';
|
||||||
import { Role } from '../../../generated/entity/teams/role';
|
import { Role } from '../../../generated/entity/teams/role';
|
||||||
import { Paging } from '../../../generated/type/paging';
|
import { Paging } from '../../../generated/type/paging';
|
||||||
import { getEntityName } from '../../../utils/CommonUtils';
|
import { getEntityName } from '../../../utils/CommonUtils';
|
||||||
import { LIST_CAP } from '../../../utils/PermissionsUtils';
|
import { checkPermission, LIST_CAP } from '../../../utils/PermissionsUtils';
|
||||||
import {
|
import {
|
||||||
getPolicyWithFqnPath,
|
getPolicyWithFqnPath,
|
||||||
getRoleWithFqnPath,
|
getRoleWithFqnPath,
|
||||||
@ -37,6 +44,22 @@ interface RolesListProps {
|
|||||||
const RolesList: FC<RolesListProps> = ({ roles, fetchRoles }) => {
|
const RolesList: FC<RolesListProps> = ({ roles, fetchRoles }) => {
|
||||||
const [selectedRole, setSelectedRole] = useState<Role>();
|
const [selectedRole, setSelectedRole] = useState<Role>();
|
||||||
|
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
|
const viewPolicyPermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(Operation.ViewAll, ResourceEntity.POLICY, permissions)
|
||||||
|
);
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
|
const deleteRolePermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(Operation.Delete, ResourceEntity.ROLE, permissions)
|
||||||
|
);
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
const columns: ColumnsType<Role> = useMemo(() => {
|
const columns: ColumnsType<Role> = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -72,27 +95,39 @@ const RolesList: FC<RolesListProps> = ({ roles, fetchRoles }) => {
|
|||||||
|
|
||||||
return record.policies?.length ? (
|
return record.policies?.length ? (
|
||||||
<Space wrap data-testid="policy-link" size={4}>
|
<Space wrap data-testid="policy-link" size={4}>
|
||||||
{record.policies.slice(0, LIST_CAP).map((policy) => (
|
{record.policies.slice(0, LIST_CAP).map((policy) =>
|
||||||
<Link
|
viewPolicyPermission ? (
|
||||||
key={uniqueId()}
|
<Link
|
||||||
to={getPolicyWithFqnPath(policy.fullyQualifiedName || '')}>
|
key={uniqueId()}
|
||||||
{getEntityName(policy)}
|
to={getPolicyWithFqnPath(policy.fullyQualifiedName || '')}>
|
||||||
</Link>
|
{getEntityName(policy)}
|
||||||
))}
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Tooltip title={NO_PERMISSION_TO_VIEW}>
|
||||||
|
{getEntityName(policy)}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
)}
|
||||||
{hasMore && (
|
{hasMore && (
|
||||||
<Popover
|
<Popover
|
||||||
className="tw-cursor-pointer"
|
className="tw-cursor-pointer"
|
||||||
content={
|
content={
|
||||||
<Space wrap size={4}>
|
<Space wrap size={4}>
|
||||||
{record.policies.slice(LIST_CAP).map((policy) => (
|
{record.policies.slice(LIST_CAP).map((policy) =>
|
||||||
<Link
|
viewPolicyPermission ? (
|
||||||
key={uniqueId()}
|
<Link
|
||||||
to={getPolicyWithFqnPath(
|
key={uniqueId()}
|
||||||
policy.fullyQualifiedName || ''
|
to={getPolicyWithFqnPath(
|
||||||
)}>
|
policy.fullyQualifiedName || ''
|
||||||
{getEntityName(policy)}
|
)}>
|
||||||
</Link>
|
{getEntityName(policy)}
|
||||||
))}
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Tooltip title={NO_PERMISSION_TO_VIEW}>
|
||||||
|
{getEntityName(policy)}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
overlayClassName="tw-w-40 tw-text-center"
|
overlayClassName="tw-w-40 tw-text-center"
|
||||||
@ -115,12 +150,21 @@ const RolesList: FC<RolesListProps> = ({ roles, fetchRoles }) => {
|
|||||||
key: 'actions',
|
key: 'actions',
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Tooltip
|
||||||
data-testid={`delete-action-${getEntityName(record)}`}
|
placement="left"
|
||||||
type="text"
|
title={
|
||||||
onClick={() => setSelectedRole(record)}>
|
deleteRolePermission ? 'Delete' : NO_PERMISSION_FOR_ACTION
|
||||||
<SVGIcons alt="delete" icon={Icons.DELETE} width="18px" />
|
}>
|
||||||
</Button>
|
<Button
|
||||||
|
data-testid={`delete-action-${getEntityName(record)}`}
|
||||||
|
disabled={!deleteRolePermission}
|
||||||
|
icon={
|
||||||
|
<SVGIcons alt="delete" icon={Icons.DELETE} width="18px" />
|
||||||
|
}
|
||||||
|
type="text"
|
||||||
|
onClick={() => setSelectedRole(record)}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -42,7 +42,27 @@ jest.mock('./RolesList', () =>
|
|||||||
jest.fn().mockReturnValue(<div data-testid="roles-list">RolesList</div>)
|
jest.fn().mockReturnValue(<div data-testid="roles-list">RolesList</div>)
|
||||||
);
|
);
|
||||||
|
|
||||||
describe('Test Roled List Page', () => {
|
jest.mock('../../../utils/PermissionsUtils', () => ({
|
||||||
|
checkPermission: jest.fn().mockReturnValue(true),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../../components/PermissionProvider/PermissionProvider', () => ({
|
||||||
|
usePermissionProvider: jest.fn().mockReturnValue({
|
||||||
|
permissions: {
|
||||||
|
role: {
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
ViewAll: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
EditCustomFields: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('Test Roles List Page', () => {
|
||||||
it('Should render the list component', async () => {
|
it('Should render the list component', async () => {
|
||||||
render(<RolesListPage />);
|
render(<RolesListPage />);
|
||||||
|
|
||||||
|
@ -11,20 +11,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button, Col, Row, Space } from 'antd';
|
import { Button, Col, Row, Space, Tooltip } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import React, { useEffect, useState } from 'react';
|
import { isEmpty } from 'lodash';
|
||||||
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { getRoles } from '../../../axiosAPIs/rolesAPIV1';
|
import { getRoles } from '../../../axiosAPIs/rolesAPIV1';
|
||||||
import NextPrevious from '../../../components/common/next-previous/NextPrevious';
|
import NextPrevious from '../../../components/common/next-previous/NextPrevious';
|
||||||
import Loader from '../../../components/Loader/Loader';
|
import Loader from '../../../components/Loader/Loader';
|
||||||
|
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import {
|
import {
|
||||||
INITIAL_PAGING_VALUE,
|
INITIAL_PAGING_VALUE,
|
||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
ROUTES,
|
ROUTES,
|
||||||
} from '../../../constants/constants';
|
} from '../../../constants/constants';
|
||||||
|
import { NO_PERMISSION_FOR_ACTION } from '../../../constants/HelperTextUtil';
|
||||||
|
import { Operation } from '../../../generated/entity/policies/policy';
|
||||||
import { Role } from '../../../generated/entity/teams/role';
|
import { Role } from '../../../generated/entity/teams/role';
|
||||||
import { Paging } from '../../../generated/type/paging';
|
import { Paging } from '../../../generated/type/paging';
|
||||||
|
import { checkPermission } from '../../../utils/PermissionsUtils';
|
||||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||||
import RolesList from './RolesList';
|
import RolesList from './RolesList';
|
||||||
import './RolesList.less';
|
import './RolesList.less';
|
||||||
@ -37,6 +43,15 @@ const RolesListPage = () => {
|
|||||||
const [paging, setPaging] = useState<Paging>();
|
const [paging, setPaging] = useState<Paging>();
|
||||||
const [currentPage, setCurrentPage] = useState<number>(INITIAL_PAGING_VALUE);
|
const [currentPage, setCurrentPage] = useState<number>(INITIAL_PAGING_VALUE);
|
||||||
|
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
|
const addRolePermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(Operation.Create, ResourceEntity.ROLE, permissions)
|
||||||
|
);
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
const fetchRoles = async (paging?: Paging) => {
|
const fetchRoles = async (paging?: Paging) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
@ -77,9 +92,17 @@ const RolesListPage = () => {
|
|||||||
gutter={[16, 16]}>
|
gutter={[16, 16]}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Space align="center" className="tw-w-full tw-justify-end" size={16}>
|
<Space align="center" className="tw-w-full tw-justify-end" size={16}>
|
||||||
<Button data-testid="add-role" type="primary" onClick={handleAddRole}>
|
<Tooltip
|
||||||
Add Role
|
placement="left"
|
||||||
</Button>
|
title={addRolePermission ? 'Add Role' : NO_PERMISSION_FOR_ACTION}>
|
||||||
|
<Button
|
||||||
|
data-testid="add-role"
|
||||||
|
disabled={!addRolePermission}
|
||||||
|
type="primary"
|
||||||
|
onClick={handleAddRole}>
|
||||||
|
Add Role
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
</Space>
|
</Space>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
@ -887,7 +887,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row>
|
<Row className="tw-my-4" gutter={[16, 16]}>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Loader />
|
<Loader />
|
||||||
) : isError ? (
|
) : isError ? (
|
||||||
|
@ -11,19 +11,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Col, Empty, Row } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
import { ServiceCategory } from 'Models';
|
import { ServiceCategory } from 'Models';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { getServices } from '../../axiosAPIs/serviceAPI';
|
import { getServices } from '../../axiosAPIs/serviceAPI';
|
||||||
import Loader from '../../components/Loader/Loader';
|
import Loader from '../../components/Loader/Loader';
|
||||||
|
import { usePermissionProvider } from '../../components/PermissionProvider/PermissionProvider';
|
||||||
import Services from '../../components/Services/Services';
|
import Services from '../../components/Services/Services';
|
||||||
import { pagingObject } from '../../constants/constants';
|
import { pagingObject } from '../../constants/constants';
|
||||||
|
import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil';
|
||||||
import { SERVICE_CATEGORY } from '../../constants/services.const';
|
import { SERVICE_CATEGORY } from '../../constants/services.const';
|
||||||
import { ServiceCategory as Category } from '../../enums/service.enum';
|
import { ServiceCategory as Category } from '../../enums/service.enum';
|
||||||
|
import { Operation } from '../../generated/entity/policies/policy';
|
||||||
import { Paging } from '../../generated/type/paging';
|
import { Paging } from '../../generated/type/paging';
|
||||||
import { ServicesType } from '../../interface/service.interface';
|
import { ServicesType } from '../../interface/service.interface';
|
||||||
import jsonData from '../../jsons/en';
|
import jsonData from '../../jsons/en';
|
||||||
|
import { checkPermission } from '../../utils/PermissionsUtils';
|
||||||
|
import { getResourceEntityFromServiceCategory } from '../../utils/ServiceUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
|
|
||||||
const ServicesPage = () => {
|
const ServicesPage = () => {
|
||||||
@ -37,6 +44,19 @@ const ServicesPage = () => {
|
|||||||
);
|
);
|
||||||
const [currentPage, setCurrentPage] = useState<number>(1);
|
const [currentPage, setCurrentPage] = useState<number>(1);
|
||||||
|
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
|
const viewAllPermission = useMemo(() => {
|
||||||
|
return (
|
||||||
|
!isEmpty(permissions) &&
|
||||||
|
checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
getResourceEntityFromServiceCategory(tab),
|
||||||
|
permissions
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
const getServiceDetails = async (type: string) => {
|
const getServiceDetails = async (type: string) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
@ -78,7 +98,7 @@ const ServicesPage = () => {
|
|||||||
return <Loader />;
|
return <Loader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return viewAllPermission ? (
|
||||||
<Services
|
<Services
|
||||||
currentPage={currentPage}
|
currentPage={currentPage}
|
||||||
paging={paging}
|
paging={paging}
|
||||||
@ -86,6 +106,12 @@ const ServicesPage = () => {
|
|||||||
serviceName={serviceName}
|
serviceName={serviceName}
|
||||||
onPageChange={handlePageChange}
|
onPageChange={handlePageChange}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<Row>
|
||||||
|
<Col span={24}>
|
||||||
|
<Empty description={NO_PERMISSION_TO_VIEW} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,7 +15,12 @@ import { isEmpty } from 'lodash';
|
|||||||
import React, { FunctionComponent } from 'react';
|
import React, { FunctionComponent } from 'react';
|
||||||
import { Redirect, Route, Switch } from 'react-router-dom';
|
import { Redirect, Route, Switch } from 'react-router-dom';
|
||||||
import AppState from '../AppState';
|
import AppState from '../AppState';
|
||||||
|
import { usePermissionProvider } from '../components/PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { ROUTES } from '../constants/constants';
|
import { ROUTES } from '../constants/constants';
|
||||||
|
import { Operation } from '../generated/entity/policies/policy';
|
||||||
|
import { checkPermission } from '../utils/PermissionsUtils';
|
||||||
|
import AdminProtectedRoute from './AdminProtectedRoute';
|
||||||
import withSuspenseFallback from './withSuspenseFallback';
|
import withSuspenseFallback from './withSuspenseFallback';
|
||||||
|
|
||||||
const GlobalSettingPage = withSuspenseFallback(
|
const GlobalSettingPage = withSuspenseFallback(
|
||||||
@ -70,9 +75,6 @@ const TourPageComponent = withSuspenseFallback(
|
|||||||
const UserPage = withSuspenseFallback(
|
const UserPage = withSuspenseFallback(
|
||||||
React.lazy(() => import('../pages/UserPage/UserPage.component'))
|
React.lazy(() => import('../pages/UserPage/UserPage.component'))
|
||||||
);
|
);
|
||||||
const AdminProtectedRoute = withSuspenseFallback(
|
|
||||||
React.lazy(() => import('./AdminProtectedRoute'))
|
|
||||||
);
|
|
||||||
|
|
||||||
const AddGlossaryPage = withSuspenseFallback(
|
const AddGlossaryPage = withSuspenseFallback(
|
||||||
React.lazy(() => import('../pages/AddGlossary/AddGlossaryPage.component'))
|
React.lazy(() => import('../pages/AddGlossary/AddGlossaryPage.component'))
|
||||||
@ -190,6 +192,8 @@ const EditRulePage = withSuspenseFallback(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const AuthenticatedAppRouter: FunctionComponent = () => {
|
const AuthenticatedAppRouter: FunctionComponent = () => {
|
||||||
|
const { permissions } = usePermissionProvider();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact component={MyDataPage} path={ROUTES.MY_DATA} />
|
<Route exact component={MyDataPage} path={ROUTES.MY_DATA} />
|
||||||
@ -208,11 +212,21 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={AddIngestionPage}
|
component={AddIngestionPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.INGESTION_PIPELINE,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.ADD_INGESTION}
|
path={ROUTES.ADD_INGESTION}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={EditIngestionPage}
|
component={EditIngestionPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.EditAll,
|
||||||
|
ResourceEntity.INGESTION_PIPELINE,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.EDIT_INGESTION}
|
path={ROUTES.EDIT_INGESTION}
|
||||||
/>
|
/>
|
||||||
<Route exact component={SignupPage} path={ROUTES.SIGNUP}>
|
<Route exact component={SignupPage} path={ROUTES.SIGNUP}>
|
||||||
@ -290,47 +304,92 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={AddGlossaryPage}
|
component={AddGlossaryPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.GLOSSARY,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.ADD_GLOSSARY}
|
path={ROUTES.ADD_GLOSSARY}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={AddGlossaryTermPage}
|
component={AddGlossaryTermPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.GLOSSARY_TERM,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.ADD_GLOSSARY_TERMS_CHILD}
|
path={ROUTES.ADD_GLOSSARY_TERMS_CHILD}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={AddGlossaryTermPage}
|
component={AddGlossaryTermPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.GLOSSARY_TERM,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.ADD_GLOSSARY_TERMS}
|
path={ROUTES.ADD_GLOSSARY_TERMS}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={AddWebhookPage}
|
component={AddWebhookPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.WEBHOOK,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.ADD_WEBHOOK_WITH_TYPE}
|
path={ROUTES.ADD_WEBHOOK_WITH_TYPE}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={AddWebhookPage}
|
component={AddWebhookPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.WEBHOOK,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.ADD_WEBHOOK}
|
path={ROUTES.ADD_WEBHOOK}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={CreateUserPage}
|
component={CreateUserPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.USER,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.CREATE_USER}
|
path={ROUTES.CREATE_USER}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={CreateUserPage}
|
component={CreateUserPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.BOT,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.CREATE_USER_WITH_BOT}
|
path={ROUTES.CREATE_USER_WITH_BOT}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={BotDetailsPage}
|
component={BotDetailsPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.ViewAll,
|
||||||
|
ResourceEntity.BOT,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.BOTS_PROFILE}
|
path={ROUTES.BOTS_PROFILE}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={AddCustomProperty}
|
component={AddCustomProperty}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.TYPE,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.ADD_CUSTOM_PROPERTY}
|
path={ROUTES.ADD_CUSTOM_PROPERTY}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
@ -352,21 +411,41 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={AddRolePage}
|
component={AddRolePage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.ROLE,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.ADD_ROLE}
|
path={ROUTES.ADD_ROLE}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={AddPolicyPage}
|
component={AddPolicyPage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.POLICY,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.ADD_POLICY}
|
path={ROUTES.ADD_POLICY}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={AddRulePage}
|
component={AddRulePage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.Create,
|
||||||
|
ResourceEntity.POLICY,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.ADD_POLICY_RULE}
|
path={ROUTES.ADD_POLICY_RULE}
|
||||||
/>
|
/>
|
||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={EditRulePage}
|
component={EditRulePage}
|
||||||
|
hasPermission={checkPermission(
|
||||||
|
Operation.EditAll,
|
||||||
|
ResourceEntity.POLICY,
|
||||||
|
permissions
|
||||||
|
)}
|
||||||
path={ROUTES.EDIT_POLICY_RULE}
|
path={ROUTES.EDIT_POLICY_RULE}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
} from '../constants/globalSettings.constants';
|
} from '../constants/globalSettings.constants';
|
||||||
import { Operation } from '../generated/entity/policies/policy';
|
import { Operation } from '../generated/entity/policies/policy';
|
||||||
import TeamsPage from '../pages/teams/TeamsPage';
|
import TeamsPage from '../pages/teams/TeamsPage';
|
||||||
import { checkPemission } from '../utils/PermissionsUtils';
|
import { checkPermission } from '../utils/PermissionsUtils';
|
||||||
import { getSettingCategoryPath, getSettingPath } from '../utils/RouterUtils';
|
import { getSettingCategoryPath, getSettingPath } from '../utils/RouterUtils';
|
||||||
import AdminProtectedRoute from './AdminProtectedRoute';
|
import AdminProtectedRoute from './AdminProtectedRoute';
|
||||||
import withSuspenseFallback from './withSuspenseFallback';
|
import withSuspenseFallback from './withSuspenseFallback';
|
||||||
@ -103,7 +103,7 @@ const GlobalSettingRouter = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={RolesListPage}
|
component={RolesListPage}
|
||||||
hasPermission={checkPemission(
|
hasPermission={checkPermission(
|
||||||
Operation.ViewAll,
|
Operation.ViewAll,
|
||||||
ResourceEntity.ROLE,
|
ResourceEntity.ROLE,
|
||||||
permissions
|
permissions
|
||||||
@ -117,7 +117,7 @@ const GlobalSettingRouter = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={RolesDetailPage}
|
component={RolesDetailPage}
|
||||||
hasPermission={checkPemission(
|
hasPermission={checkPermission(
|
||||||
Operation.ViewAll,
|
Operation.ViewAll,
|
||||||
ResourceEntity.ROLE,
|
ResourceEntity.ROLE,
|
||||||
permissions
|
permissions
|
||||||
@ -135,7 +135,7 @@ const GlobalSettingRouter = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={PoliciesListPage}
|
component={PoliciesListPage}
|
||||||
hasPermission={checkPemission(
|
hasPermission={checkPermission(
|
||||||
Operation.ViewAll,
|
Operation.ViewAll,
|
||||||
ResourceEntity.POLICY,
|
ResourceEntity.POLICY,
|
||||||
permissions
|
permissions
|
||||||
@ -148,7 +148,7 @@ const GlobalSettingRouter = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={PoliciesDetailPage}
|
component={PoliciesDetailPage}
|
||||||
hasPermission={checkPemission(
|
hasPermission={checkPermission(
|
||||||
Operation.ViewAll,
|
Operation.ViewAll,
|
||||||
ResourceEntity.POLICY,
|
ResourceEntity.POLICY,
|
||||||
permissions
|
permissions
|
||||||
@ -162,7 +162,7 @@ const GlobalSettingRouter = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={UserListPageV1}
|
component={UserListPageV1}
|
||||||
hasPermission={checkPemission(
|
hasPermission={checkPermission(
|
||||||
Operation.ViewAll,
|
Operation.ViewAll,
|
||||||
ResourceEntity.USER,
|
ResourceEntity.USER,
|
||||||
permissions
|
permissions
|
||||||
@ -173,7 +173,7 @@ const GlobalSettingRouter = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={WebhooksPageV1}
|
component={WebhooksPageV1}
|
||||||
hasPermission={checkPemission(
|
hasPermission={checkPermission(
|
||||||
Operation.ViewAll,
|
Operation.ViewAll,
|
||||||
ResourceEntity.WEBHOOK,
|
ResourceEntity.WEBHOOK,
|
||||||
permissions
|
permissions
|
||||||
@ -186,7 +186,7 @@ const GlobalSettingRouter = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={BotsPageV1}
|
component={BotsPageV1}
|
||||||
hasPermission={checkPemission(
|
hasPermission={checkPermission(
|
||||||
Operation.ViewAll,
|
Operation.ViewAll,
|
||||||
ResourceEntity.BOT,
|
ResourceEntity.BOT,
|
||||||
permissions
|
permissions
|
||||||
@ -200,7 +200,7 @@ const GlobalSettingRouter = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={SlackSettingsPage}
|
component={SlackSettingsPage}
|
||||||
hasPermission={checkPemission(
|
hasPermission={checkPermission(
|
||||||
Operation.ViewAll,
|
Operation.ViewAll,
|
||||||
ResourceEntity.WEBHOOK,
|
ResourceEntity.WEBHOOK,
|
||||||
permissions
|
permissions
|
||||||
@ -220,7 +220,7 @@ const GlobalSettingRouter = () => {
|
|||||||
<AdminProtectedRoute
|
<AdminProtectedRoute
|
||||||
exact
|
exact
|
||||||
component={CustomPropertiesPageV1}
|
component={CustomPropertiesPageV1}
|
||||||
hasPermission={checkPemission(
|
hasPermission={checkPermission(
|
||||||
Operation.ViewAll,
|
Operation.ViewAll,
|
||||||
ResourceEntity.ALL,
|
ResourceEntity.ALL,
|
||||||
permissions
|
permissions
|
||||||
|
@ -29,3 +29,4 @@
|
|||||||
|
|
||||||
@import url('./components/table.less');
|
@import url('./components/table.less');
|
||||||
@import url('./components/toggle-switch.less');
|
@import url('./components/toggle-switch.less');
|
||||||
|
@import url('./components/button.less');
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
.ant-btn {
|
||||||
|
&:disabled {
|
||||||
|
img {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
import { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
|
||||||
|
|
||||||
|
export const getResourceEntityFromCustomProperty = (property: string) => {
|
||||||
|
switch (property) {
|
||||||
|
case 'tables':
|
||||||
|
return ResourceEntity.TABLE;
|
||||||
|
|
||||||
|
case 'topics':
|
||||||
|
return ResourceEntity.TOPIC;
|
||||||
|
|
||||||
|
case 'dashboards':
|
||||||
|
return ResourceEntity.DASHBOARD;
|
||||||
|
|
||||||
|
case 'pipelines':
|
||||||
|
return ResourceEntity.PIPELINE;
|
||||||
|
|
||||||
|
case 'mlModels':
|
||||||
|
return ResourceEntity.ML_MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResourceEntity.TABLE;
|
||||||
|
};
|
@ -11,6 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import AppState from '../AppState';
|
||||||
import {
|
import {
|
||||||
OperationPermission,
|
OperationPermission,
|
||||||
ResourceEntity,
|
ResourceEntity,
|
||||||
@ -25,6 +26,7 @@ import {
|
|||||||
import { Operation } from '../generated/entity/policies/policy';
|
import { Operation } from '../generated/entity/policies/policy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @deprecated
|
||||||
* TODO: Remove this method once we have new permission structure everywhere
|
* TODO: Remove this method once we have new permission structure everywhere
|
||||||
*/
|
*/
|
||||||
export const hasPemission = (
|
export const hasPemission = (
|
||||||
@ -50,22 +52,26 @@ export const hasPemission = (
|
|||||||
* @param permissions UIPermission
|
* @param permissions UIPermission
|
||||||
* @returns boolean - true/false
|
* @returns boolean - true/false
|
||||||
*/
|
*/
|
||||||
export const checkPemission = (
|
export const checkPermission = (
|
||||||
operation: Operation,
|
operation: Operation,
|
||||||
resourceType: ResourceEntity,
|
resourceType: ResourceEntity,
|
||||||
permissions: UIPermission
|
permissions: UIPermission
|
||||||
) => {
|
) => {
|
||||||
const allResource = permissions.all;
|
const isAuthDisabled = AppState.authDisabled;
|
||||||
const entityResource = permissions[resourceType];
|
const allResource = permissions?.all;
|
||||||
|
const entityResource = permissions?.[resourceType];
|
||||||
|
let hasPemission = isAuthDisabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If allresource is present then check for permission and return it
|
* If allresource is present then check for permission and return it
|
||||||
*/
|
*/
|
||||||
if (allResource) {
|
if (allResource && !hasPemission) {
|
||||||
return allResource.All || allResource[operation];
|
hasPemission = allResource.All || allResource[operation];
|
||||||
}
|
}
|
||||||
|
|
||||||
return entityResource[operation];
|
hasPemission = hasPemission || (entityResource && entityResource[operation]);
|
||||||
|
|
||||||
|
return hasPemission;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,6 +22,7 @@ import {
|
|||||||
} from 'Models';
|
} from 'Models';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { getEntityCount } from '../axiosAPIs/miscAPI';
|
import { getEntityCount } from '../axiosAPIs/miscAPI';
|
||||||
|
import { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { GlobalSettingOptions } from '../constants/globalSettings.constants';
|
import { GlobalSettingOptions } from '../constants/globalSettings.constants';
|
||||||
import {
|
import {
|
||||||
addLineageIngestionGuide,
|
addLineageIngestionGuide,
|
||||||
@ -743,3 +744,31 @@ export const getServiceRouteFromServiceType = (type: ServiceTypes) => {
|
|||||||
|
|
||||||
return GlobalSettingOptions.DATABASES;
|
return GlobalSettingOptions.DATABASES;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getResourceEntityFromServiceCategory = (
|
||||||
|
category: string | ServiceCategory
|
||||||
|
) => {
|
||||||
|
switch (category) {
|
||||||
|
case 'dashboards':
|
||||||
|
case ServiceCategory.DASHBOARD_SERVICES:
|
||||||
|
return ResourceEntity.DASHBOARD_SERVICE;
|
||||||
|
|
||||||
|
case 'databases':
|
||||||
|
case ServiceCategory.DATABASE_SERVICES:
|
||||||
|
return ResourceEntity.DATABASE_SERVICE;
|
||||||
|
|
||||||
|
case 'mlModels':
|
||||||
|
case ServiceCategory.ML_MODAL_SERVICES:
|
||||||
|
return ResourceEntity.ML_MODEL_SERVICE;
|
||||||
|
|
||||||
|
case 'messaging':
|
||||||
|
case ServiceCategory.MESSAGING_SERVICES:
|
||||||
|
return ResourceEntity.MESSAGING_SERVICE;
|
||||||
|
|
||||||
|
case 'pipelines':
|
||||||
|
case ServiceCategory.PIPELINE_SERVICES:
|
||||||
|
return ResourceEntity.PIPELINE_SERVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResourceEntity.DATABASE_SERVICE;
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user