diff --git a/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/rolesAPIV1.ts b/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/rolesAPIV1.ts
index 7f4b340a166..8b5884ac393 100644
--- a/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/rolesAPIV1.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/axiosAPIs/rolesAPIV1.ts
@@ -13,9 +13,11 @@
import { AxiosResponse } from 'axios';
import { Operation } from 'fast-json-patch';
+import { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
import { CreatePolicy } from '../generated/api/policies/createPolicy';
import { CreateRole } from '../generated/api/teams/createRole';
import { ResourceDescriptor } from '../generated/entity/policies/accessControl/resourceDescriptor';
+import { ResourcePermission } from '../generated/entity/policies/accessControl/resourcePermission';
import { Policy } from '../generated/entity/policies/policy';
import { Role } from '../generated/entity/teams/role';
import { Function } from '../generated/type/function';
@@ -154,3 +156,14 @@ export const validateRuleCondition = async (condition: string) => {
*/
return response;
};
+
+export const getEntityPermissionById = async (
+ resource: ResourceEntity,
+ entityId: string
+) => {
+ const response = await APIClient.get(
+ `/permissions/${resource}/${entityId}`
+ );
+
+ return response.data;
+};
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AddWebhook/AddWebhook.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AddWebhook/AddWebhook.tsx
index 8723e2d05e3..e44fc20b2ad 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/AddWebhook/AddWebhook.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AddWebhook/AddWebhook.tsx
@@ -13,12 +13,19 @@
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Tooltip } from 'antd';
import { Store } from 'antd/lib/form/interface';
import classNames from 'classnames';
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 React, { FunctionComponent, useCallback, useRef, useState } from 'react';
+import React, {
+ FunctionComponent,
+ useCallback,
+ useMemo,
+ useRef,
+ useState,
+} from 'react';
import { ROUTES, TERM_ALL } from '../../constants/constants';
import {
GlobalSettingOptions,
@@ -27,6 +34,7 @@ import {
import {
CONFIGURE_SLACK_TEXT,
CONFIGURE_WEBHOOK_TEXT,
+ NO_PERMISSION_FOR_ACTION,
} from '../../constants/HelperTextUtil';
import { UrlEntityCharRegEx } from '../../constants/regex.constants';
import { FormSubmitType } from '../../enums/form.enum';
@@ -37,12 +45,14 @@ import {
Filters,
} from '../../generated/api/events/createWebhook';
import { WebhookType } from '../../generated/entity/events/webhook';
+import { Operation } from '../../generated/entity/policies/policy';
import {
errorMsg,
getSeparator,
isValidUrl,
requiredField,
} from '../../utils/CommonUtils';
+import { checkPermission } from '../../utils/PermissionsUtils';
import { getSettingPath } from '../../utils/RouterUtils';
import SVGIcons, { Icons } from '../../utils/SvgUtils';
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 Loader from '../Loader/Loader';
import ConfirmationModal from '../Modals/ConfirmationModal/ConfirmationModal';
+import { usePermissionProvider } from '../PermissionProvider/PermissionProvider';
+import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interface';
import { AddWebhookProps } from './AddWebhook.interface';
import SelectComponent from './select-component';
import {
@@ -163,6 +175,29 @@ const AddWebhook: FunctionComponent = ({
const [generatingSecret, setGeneratingSecret] = useState(false);
const [isDelete, setIsDelete] = useState(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 = () => {
if (data) {
onDelete && onDelete(data.id);
@@ -259,7 +294,7 @@ const AddWebhook: FunctionComponent = ({
};
const getDeleteButton = () => {
- return allowAccess ? (
+ return (
<>
{deleteState === 'waiting' ? (
) : (
-
+
+
+
)}
>
- ) : null;
+ );
};
const getSaveButton = () => {
- return allowAccess ? (
+ const savePermission =
+ (mode === 'add' && addWebhookPermission) ||
+ (mode === 'edit' && editWebhookPermission);
+
+ return (
<>
{saveState === 'waiting' ? (
) : (
-
+
+
+
)}
>
- ) : null;
+ );
};
const fetchRightPanel = useCallback(() => {
@@ -631,7 +677,7 @@ const AddWebhook: FunctionComponent = ({
)}
- {data && isDelete && (
+ {data && isDelete && deleteWebhookPermission && (
= ({
const [generateToken, setGenerateToken] = useState(false);
const [selectedExpiry, setSelectedExpiry] = useState('7');
- const editAllPermission = checkPemission(
+ const editAllPermission = checkPermission(
Operation.EditAll,
ResourceEntity.BOT,
permissions
);
- const displayNamePermission = checkPemission(
+ const displayNamePermission = checkPermission(
Operation.EditDisplayName,
ResourceEntity.BOT,
permissions
);
- const descriptionPermission = checkPemission(
+ const descriptionPermission = checkPermission(
Operation.EditDescription,
ResourceEntity.BOT,
permissions
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/BotDetails/BotDetails.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/BotDetails/BotDetails.test.tsx
index 8477198f40e..8373c7ed51b 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/BotDetails/BotDetails.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/BotDetails/BotDetails.test.tsx
@@ -85,7 +85,7 @@ jest.mock('../PermissionProvider/PermissionProvider', () => ({
}));
jest.mock('../../utils/PermissionsUtils', () => ({
- checkPemission: jest.fn().mockReturnValue(true),
+ checkPermission: jest.fn().mockReturnValue(true),
}));
jest.mock('../../axiosAPIs/userAPI', () => {
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/BotListV1/BotListV1.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/BotListV1/BotListV1.component.tsx
index 9ff769a19cc..cf9a25c867b 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/BotListV1/BotListV1.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/BotListV1/BotListV1.component.tsx
@@ -22,12 +22,13 @@ import {
INITIAL_PAGING_VALUE,
PAGE_SIZE,
} from '../../constants/constants';
+import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil';
import { EntityType } from '../../enums/entity.enum';
import { Bot } from '../../generated/entity/bot';
import { Operation } from '../../generated/entity/policies/accessControl/rule';
import { Include } from '../../generated/type/include';
import { Paging } from '../../generated/type/paging';
-import { checkPemission } from '../../utils/PermissionsUtils';
+import { checkPermission } from '../../utils/PermissionsUtils';
import SVGIcons, { Icons } from '../../utils/SvgUtils';
import { showErrorToast } from '../../utils/ToastUtils';
import DeleteWidgetModal from '../common/DeleteWidget/DeleteWidgetModal';
@@ -45,7 +46,7 @@ const BotListV1 = ({ showDeleted }: BotListV1Props) => {
const [loading, setLoading] = useState(true);
const [currentPage, setCurrentPage] = useState(INITIAL_PAGING_VALUE);
- const deletePermission = checkPemission(
+ const deletePermission = checkPermission(
Operation.Delete,
ResourceEntity.BOT,
permissions
@@ -103,11 +104,7 @@ const BotListV1 = ({ showDeleted }: BotListV1Props) => {
+ title={deletePermission ? 'Delete' : NO_PERMISSION_FOR_ACTION}>
);
@@ -131,14 +140,17 @@ const WebhooksV1: FC = ({
className="tw-w-full tw-justify-end"
size={16}>
{filteredData.length > 0 && (
-
+
= ({
Add{' '}
{webhookType === WebhookType.Slack ? 'Slack' : 'Webhook'}
-
+
)}
diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/HelperTextUtil.ts b/openmetadata-ui/src/main/resources/ui/src/constants/HelperTextUtil.ts
index f566285eaaf..c387971fa4c 100644
--- a/openmetadata-ui/src/main/resources/ui/src/constants/HelperTextUtil.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/constants/HelperTextUtil.ts
@@ -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.
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';
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/BotsPageV1/BotsPageV1.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/BotsPageV1/BotsPageV1.component.tsx
index 094cbcee717..b8f7a76c612 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/BotsPageV1/BotsPageV1.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/BotsPageV1/BotsPageV1.component.tsx
@@ -11,7 +11,7 @@
* 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 { useHistory } from 'react-router-dom';
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 { getCreateUserPath } from '../../constants/constants';
import { Operation } from '../../generated/entity/policies/accessControl/rule';
-import { checkPemission } from '../../utils/PermissionsUtils';
+import { checkPermission } from '../../utils/PermissionsUtils';
export const BotsPageV1 = () => {
const { permissions } = usePermissionProvider();
@@ -34,13 +34,7 @@ export const BotsPageV1 = () => {
setShowDeleted(checked);
};
- const viewAllPermission = checkPemission(
- Operation.ViewAll,
- ResourceEntity.BOT,
- permissions
- );
-
- const createPermission = checkPemission(
+ const createPermission = checkPermission(
Operation.Create,
ResourceEntity.BOT,
permissions
@@ -48,35 +42,29 @@ export const BotsPageV1 = () => {
return (
- {viewAllPermission ? (
- <>
-
-
-
-
-
-
-
+
+
+
+
+
+
+
- {createPermission && (
-
- Add Bot
-
- )}
-
-
-
-
-
- >
- ) : (
-
- )}
+ {createPermission && (
+
+ Add Bot
+
+ )}
+
+
+
+
+
);
};
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.component.tsx
index ed8591df879..6da1f00622a 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/CreateUserPage/CreateUserPage.component.tsx
@@ -17,7 +17,6 @@ import { LoadingState } from 'Models';
import React, { useEffect, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom';
import AppState from '../../AppState';
-import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
import { createBot } from '../../axiosAPIs/botsAPI';
import { createUser } from '../../axiosAPIs/userAPI';
import PageContainerV1 from '../../components/containers/PageContainerV1';
@@ -30,14 +29,11 @@ import { EntityType } from '../../enums/entity.enum';
import { CreateUser } from '../../generated/api/teams/createUser';
import { Bot } from '../../generated/entity/bot';
import { Role } from '../../generated/entity/teams/role';
-import { useAuth } from '../../hooks/authHooks';
import jsonData from '../../jsons/en';
import { getSettingPath } from '../../utils/RouterUtils';
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
const CreateUserPage = () => {
- const { isAdminUser } = useAuth();
- const { isAuthDisabled } = useAuthContext();
const history = useHistory();
const [roles, setRoles] = useState>([]);
@@ -128,7 +124,6 @@ const CreateUserPage = () => {
{
const tabAttributePath =
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) => {
setIsLoading(true);
try {
@@ -120,7 +138,7 @@ const CustomEntityDetailV1 = () => {
);
}
- return (
+ return viewPermission ? (
{
)}
+ ) : (
+
+
+
+
+
);
};
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.tsx
index 5e1d37d2683..3b94610f373 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesDetailPage/PoliciesDetailPage.tsx
@@ -41,15 +41,18 @@ import Description from '../../../components/common/description/Description';
import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
import TitleBreadcrumb from '../../../components/common/title-breadcrumb/title-breadcrumb.component';
import Loader from '../../../components/Loader/Loader';
+import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
+import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
import {
GlobalSettingOptions,
GlobalSettingsMenuCategory,
} from '../../../constants/globalSettings.constants';
import { EntityType } from '../../../enums/entity.enum';
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 { getEntityName } from '../../../utils/CommonUtils';
+import { checkPermission } from '../../../utils/PermissionsUtils';
import {
getAddPolicyRulePath,
getEditPolicyRulePath,
@@ -147,6 +150,7 @@ const List = ({
const PoliciesDetailPage = () => {
const history = useHistory();
const { fqn } = useParams<{ fqn: string }>();
+ const { permissions } = usePermissionProvider();
const [policy, setPolicy] = useState({} as Policy);
const [isLoading, setLoading] = useState(false);
@@ -159,6 +163,17 @@ const PoliciesDetailPage = () => {
GlobalSettingOptions.POLICIES
);
+ const editDescriptionPermission = useMemo(() => {
+ return (
+ !isEmpty(permissions) &&
+ checkPermission(
+ Operation.EditDescription,
+ ResourceEntity.ROLE,
+ permissions
+ )
+ );
+ }, [permissions]);
+
const breadcrumb = useMemo(
() => [
{
@@ -393,6 +408,7 @@ const PoliciesDetailPage = () => {
entityFqn={policy.fullyQualifiedName}
entityName={getEntityName(policy)}
entityType={EntityType.POLICY}
+ hasEditAccess={editDescriptionPermission}
isEdit={editDescription}
onCancel={() => setEditDescription(false)}
onDescriptionEdit={() => setEditDescription(true)}
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesList.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesList.tsx
index 6bcf295550a..a2ac00a245a 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesList.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesList.tsx
@@ -11,18 +11,24 @@
* 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 { isUndefined, uniqueId } from 'lodash';
+import { isEmpty, isUndefined, uniqueId } from 'lodash';
import React, { FC, useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
import DeleteWidgetModal from '../../../components/common/DeleteWidget/DeleteWidgetModal';
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 { Policy } from '../../../generated/entity/policies/policy';
+import { Operation, Policy } from '../../../generated/entity/policies/policy';
import { Paging } from '../../../generated/type/paging';
import { getEntityName } from '../../../utils/CommonUtils';
-import { LIST_CAP } from '../../../utils/PermissionsUtils';
+import { checkPermission, LIST_CAP } from '../../../utils/PermissionsUtils';
import {
getPolicyWithFqnPath,
getRoleWithFqnPath,
@@ -36,6 +42,23 @@ interface PolicyListProps {
const PoliciesList: FC = ({ policies, fetchPolicies }) => {
const [selectedPolicy, setSelectedPolicy] = useState();
+
+ 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 = useMemo(() => {
return [
{
@@ -71,27 +94,39 @@ const PoliciesList: FC = ({ policies, fetchPolicies }) => {
return record.roles?.length ? (
- {record.roles.slice(0, LIST_CAP).map((role) => (
-
- {getEntityName(role)}
-
- ))}
+ {record.roles.slice(0, LIST_CAP).map((role) =>
+ viewRolePermission ? (
+
+ {getEntityName(role)}
+
+ ) : (
+
+ {getEntityName(role)}
+
+ )
+ )}
{hasMore && (
- {record.roles.slice(LIST_CAP).map((role) => (
-
- {getEntityName(role)}
-
- ))}
+ {record.roles.slice(LIST_CAP).map((role) =>
+ viewRolePermission ? (
+
+ {getEntityName(role)}
+
+ ) : (
+
+ {getEntityName(role)}
+
+ )
+ )}
}
overlayClassName="tw-w-40 tw-text-center"
@@ -114,12 +149,19 @@ const PoliciesList: FC = ({ policies, fetchPolicies }) => {
key: 'actions',
render: (_, record) => {
return (
- setSelectedPolicy(record)}>
-
-
+
+ setSelectedPolicy(record)}>
+
+
+
);
},
},
@@ -135,7 +177,7 @@ const PoliciesList: FC = ({ policies, fetchPolicies }) => {
pagination={false}
size="middle"
/>
- {selectedPolicy && (
+ {selectedPolicy && deletePolicyPermission && (
{
const [paging, setPaging] = useState();
const [currentPage, setCurrentPage] = useState(INITIAL_PAGING_VALUE);
+ const { permissions } = usePermissionProvider();
+
+ const addPolicyPermission = useMemo(() => {
+ return (
+ !isEmpty(permissions) &&
+ checkPermission(Operation.Create, ResourceEntity.POLICY, permissions)
+ );
+ }, [permissions]);
+
const fetchPolicies = async (paging?: Paging) => {
setIsLoading(true);
try {
@@ -73,12 +87,19 @@ const PoliciesListPage = () => {
-
- Add Policy
-
+
+
+ Add Policy
+
+
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx
index ff8408bc01b..fe31e018370 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx
@@ -26,14 +26,18 @@ import Description from '../../../components/common/description/Description';
import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
import TitleBreadcrumb from '../../../components/common/title-breadcrumb/title-breadcrumb.component';
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 {
GlobalSettingOptions,
GlobalSettingsMenuCategory,
} from '../../../constants/globalSettings.constants';
import { EntityType } from '../../../enums/entity.enum';
+import { Operation } from '../../../generated/entity/policies/policy';
import { Role } from '../../../generated/entity/teams/role';
import { getEntityName } from '../../../utils/CommonUtils';
+import { checkPermission } from '../../../utils/PermissionsUtils';
import {
getPolicyWithFqnPath,
getSettingPath,
@@ -139,6 +143,7 @@ const List = ({
const RolesDetailPage = () => {
const history = useHistory();
+ const { permissions } = usePermissionProvider();
const { fqn } = useParams<{ fqn: string }>();
const [role, setRole] = useState({} as Role);
@@ -154,6 +159,17 @@ const RolesDetailPage = () => {
GlobalSettingOptions.ROLES
);
+ const editDescriptionPermission = useMemo(() => {
+ return (
+ !isEmpty(permissions) &&
+ checkPermission(
+ Operation.EditDescription,
+ ResourceEntity.ROLE,
+ permissions
+ )
+ );
+ }, [permissions]);
+
const breadcrumb = useMemo(
() => [
{
@@ -319,6 +335,7 @@ const RolesDetailPage = () => {
entityFqn={role.fullyQualifiedName}
entityName={getEntityName(role)}
entityType={EntityType.ROLE}
+ hasEditAccess={editDescriptionPermission}
isEdit={editDescription}
onCancel={() => setEditDescription(false)}
onDescriptionEdit={() => setEditDescription(true)}
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesList.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesList.tsx
index 8e7780bca0d..ea2193e8794 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesList.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesList.tsx
@@ -11,18 +11,25 @@
* 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 { isUndefined, uniqueId } from 'lodash';
+import { isEmpty, isUndefined, uniqueId } from 'lodash';
import React, { FC, useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
import DeleteWidgetModal from '../../../components/common/DeleteWidget/DeleteWidgetModal';
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 { Operation } from '../../../generated/entity/policies/policy';
import { Role } from '../../../generated/entity/teams/role';
import { Paging } from '../../../generated/type/paging';
import { getEntityName } from '../../../utils/CommonUtils';
-import { LIST_CAP } from '../../../utils/PermissionsUtils';
+import { checkPermission, LIST_CAP } from '../../../utils/PermissionsUtils';
import {
getPolicyWithFqnPath,
getRoleWithFqnPath,
@@ -37,6 +44,22 @@ interface RolesListProps {
const RolesList: FC = ({ roles, fetchRoles }) => {
const [selectedRole, setSelectedRole] = useState();
+ 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 = useMemo(() => {
return [
{
@@ -72,27 +95,39 @@ const RolesList: FC = ({ roles, fetchRoles }) => {
return record.policies?.length ? (
- {record.policies.slice(0, LIST_CAP).map((policy) => (
-
- {getEntityName(policy)}
-
- ))}
+ {record.policies.slice(0, LIST_CAP).map((policy) =>
+ viewPolicyPermission ? (
+
+ {getEntityName(policy)}
+
+ ) : (
+
+ {getEntityName(policy)}
+
+ )
+ )}
{hasMore && (
- {record.policies.slice(LIST_CAP).map((policy) => (
-
- {getEntityName(policy)}
-
- ))}
+ {record.policies.slice(LIST_CAP).map((policy) =>
+ viewPolicyPermission ? (
+
+ {getEntityName(policy)}
+
+ ) : (
+
+ {getEntityName(policy)}
+
+ )
+ )}
}
overlayClassName="tw-w-40 tw-text-center"
@@ -115,12 +150,21 @@ const RolesList: FC = ({ roles, fetchRoles }) => {
key: 'actions',
render: (_, record) => {
return (
- setSelectedRole(record)}>
-
-
+
+
+ }
+ type="text"
+ onClick={() => setSelectedRole(record)}
+ />
+
);
},
},
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesListPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesListPage.test.tsx
index b8fc74517b6..40f1bf10816 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesListPage.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesListPage.test.tsx
@@ -42,7 +42,27 @@ jest.mock('./RolesList', () =>
jest.fn().mockReturnValue(RolesList
)
);
-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 () => {
render();
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesListPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesListPage.tsx
index 5ac263d6e08..10821ebbccf 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesListPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesListPage/RolesListPage.tsx
@@ -11,20 +11,26 @@
* limitations under the License.
*/
-import { Button, Col, Row, Space } from 'antd';
+import { Button, Col, Row, Space, Tooltip } from 'antd';
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 { getRoles } from '../../../axiosAPIs/rolesAPIV1';
import NextPrevious from '../../../components/common/next-previous/NextPrevious';
import Loader from '../../../components/Loader/Loader';
+import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
+import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
import {
INITIAL_PAGING_VALUE,
PAGE_SIZE,
ROUTES,
} 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 { Paging } from '../../../generated/type/paging';
+import { checkPermission } from '../../../utils/PermissionsUtils';
import { showErrorToast } from '../../../utils/ToastUtils';
import RolesList from './RolesList';
import './RolesList.less';
@@ -37,6 +43,15 @@ const RolesListPage = () => {
const [paging, setPaging] = useState();
const [currentPage, setCurrentPage] = useState(INITIAL_PAGING_VALUE);
+ const { permissions } = usePermissionProvider();
+
+ const addRolePermission = useMemo(() => {
+ return (
+ !isEmpty(permissions) &&
+ checkPermission(Operation.Create, ResourceEntity.ROLE, permissions)
+ );
+ }, [permissions]);
+
const fetchRoles = async (paging?: Paging) => {
setIsLoading(true);
try {
@@ -77,9 +92,17 @@ const RolesListPage = () => {
gutter={[16, 16]}>
-
- Add Role
-
+
+
+ Add Role
+
+
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx
index b08840c4127..4ff6c654beb 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx
@@ -887,7 +887,7 @@ const ServicePage: FunctionComponent = () => {
};
return (
-
+
{isLoading ? (
) : isError ? (
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/services/ServicesPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/services/ServicesPage.tsx
index 7d2961522eb..9402d376a42 100644
--- a/openmetadata-ui/src/main/resources/ui/src/pages/services/ServicesPage.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/services/ServicesPage.tsx
@@ -11,19 +11,26 @@
* limitations under the License.
*/
+import { Col, Empty, Row } from 'antd';
import { AxiosError } from 'axios';
+import { isEmpty } from 'lodash';
import { ServiceCategory } from 'Models';
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useMemo, useState } from 'react';
import { useParams } from 'react-router-dom';
import { getServices } from '../../axiosAPIs/serviceAPI';
import Loader from '../../components/Loader/Loader';
+import { usePermissionProvider } from '../../components/PermissionProvider/PermissionProvider';
import Services from '../../components/Services/Services';
import { pagingObject } from '../../constants/constants';
+import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil';
import { SERVICE_CATEGORY } from '../../constants/services.const';
import { ServiceCategory as Category } from '../../enums/service.enum';
+import { Operation } from '../../generated/entity/policies/policy';
import { Paging } from '../../generated/type/paging';
import { ServicesType } from '../../interface/service.interface';
import jsonData from '../../jsons/en';
+import { checkPermission } from '../../utils/PermissionsUtils';
+import { getResourceEntityFromServiceCategory } from '../../utils/ServiceUtils';
import { showErrorToast } from '../../utils/ToastUtils';
const ServicesPage = () => {
@@ -37,6 +44,19 @@ const ServicesPage = () => {
);
const [currentPage, setCurrentPage] = useState(1);
+ const { permissions } = usePermissionProvider();
+
+ const viewAllPermission = useMemo(() => {
+ return (
+ !isEmpty(permissions) &&
+ checkPermission(
+ Operation.ViewAll,
+ getResourceEntityFromServiceCategory(tab),
+ permissions
+ )
+ );
+ }, [permissions]);
+
const getServiceDetails = async (type: string) => {
setIsLoading(true);
try {
@@ -78,7 +98,7 @@ const ServicesPage = () => {
return ;
}
- return (
+ return viewAllPermission ? (
{
serviceName={serviceName}
onPageChange={handlePageChange}
/>
+ ) : (
+
+
+
+
+
);
};
diff --git a/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx
index 9d32e8d6d87..5c16e5d4ef7 100644
--- a/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/router/AuthenticatedAppRouter.tsx
@@ -15,7 +15,12 @@ import { isEmpty } from 'lodash';
import React, { FunctionComponent } from 'react';
import { Redirect, Route, Switch } from 'react-router-dom';
import AppState from '../AppState';
+import { usePermissionProvider } from '../components/PermissionProvider/PermissionProvider';
+import { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
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';
const GlobalSettingPage = withSuspenseFallback(
@@ -70,9 +75,6 @@ const TourPageComponent = withSuspenseFallback(
const UserPage = withSuspenseFallback(
React.lazy(() => import('../pages/UserPage/UserPage.component'))
);
-const AdminProtectedRoute = withSuspenseFallback(
- React.lazy(() => import('./AdminProtectedRoute'))
-);
const AddGlossaryPage = withSuspenseFallback(
React.lazy(() => import('../pages/AddGlossary/AddGlossaryPage.component'))
@@ -190,6 +192,8 @@ const EditRulePage = withSuspenseFallback(
);
const AuthenticatedAppRouter: FunctionComponent = () => {
+ const { permissions } = usePermissionProvider();
+
return (
@@ -208,11 +212,21 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
@@ -290,47 +304,92 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
{
diff --git a/openmetadata-ui/src/main/resources/ui/src/router/GlobalSettingRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/router/GlobalSettingRouter.tsx
index 9878d3082cc..1a1b8245bd8 100644
--- a/openmetadata-ui/src/main/resources/ui/src/router/GlobalSettingRouter.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/router/GlobalSettingRouter.tsx
@@ -21,7 +21,7 @@ import {
} from '../constants/globalSettings.constants';
import { Operation } from '../generated/entity/policies/policy';
import TeamsPage from '../pages/teams/TeamsPage';
-import { checkPemission } from '../utils/PermissionsUtils';
+import { checkPermission } from '../utils/PermissionsUtils';
import { getSettingCategoryPath, getSettingPath } from '../utils/RouterUtils';
import AdminProtectedRoute from './AdminProtectedRoute';
import withSuspenseFallback from './withSuspenseFallback';
@@ -103,7 +103,7 @@ const GlobalSettingRouter = () => {
{
{
{
{
{
{
{
{
{
+ 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;
+};
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/PermissionsUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/PermissionsUtils.ts
index d5f4009080d..f760e4de3d5 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/PermissionsUtils.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/PermissionsUtils.ts
@@ -11,6 +11,7 @@
* limitations under the License.
*/
+import AppState from '../AppState';
import {
OperationPermission,
ResourceEntity,
@@ -25,6 +26,7 @@ import {
import { Operation } from '../generated/entity/policies/policy';
/**
+ * @deprecated
* TODO: Remove this method once we have new permission structure everywhere
*/
export const hasPemission = (
@@ -50,22 +52,26 @@ export const hasPemission = (
* @param permissions UIPermission
* @returns boolean - true/false
*/
-export const checkPemission = (
+export const checkPermission = (
operation: Operation,
resourceType: ResourceEntity,
permissions: UIPermission
) => {
- const allResource = permissions.all;
- const entityResource = permissions[resourceType];
+ const isAuthDisabled = AppState.authDisabled;
+ const allResource = permissions?.all;
+ const entityResource = permissions?.[resourceType];
+ let hasPemission = isAuthDisabled;
/**
* If allresource is present then check for permission and return it
*/
- if (allResource) {
- return allResource.All || allResource[operation];
+ if (allResource && !hasPemission) {
+ hasPemission = allResource.All || allResource[operation];
}
- return entityResource[operation];
+ hasPemission = hasPemission || (entityResource && entityResource[operation]);
+
+ return hasPemission;
};
/**
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/ServiceUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/ServiceUtils.tsx
index 73f8406874b..11bca83aeb4 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/ServiceUtils.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/ServiceUtils.tsx
@@ -22,6 +22,7 @@ import {
} from 'Models';
import React from 'react';
import { getEntityCount } from '../axiosAPIs/miscAPI';
+import { ResourceEntity } from '../components/PermissionProvider/PermissionProvider.interface';
import { GlobalSettingOptions } from '../constants/globalSettings.constants';
import {
addLineageIngestionGuide,
@@ -743,3 +744,31 @@ export const getServiceRouteFromServiceType = (type: ServiceTypes) => {
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;
+};