mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-09 15:56:33 +00:00
UI : Add Permission Check on Entity Page (#7303)
* UI : Add Permission Check on Entity Page * Change dependency
This commit is contained in:
parent
1a9a67b087
commit
58c439e900
@ -38,6 +38,16 @@ export const getEntityPermissionById = async (
|
|||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
export const getEntityPermissionByFqn = async (
|
||||||
|
resource: ResourceEntity,
|
||||||
|
entityFqn: string
|
||||||
|
) => {
|
||||||
|
const response = await APIClient.get<ResourcePermission>(
|
||||||
|
`/permissions/${resource}/name/${entityFqn}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
export const getResourcePermission = async (resource: ResourceEntity) => {
|
export const getResourcePermission = async (resource: ResourceEntity) => {
|
||||||
const response = await APIClient.get<ResourcePermission>(
|
const response = await APIClient.get<ResourcePermission>(
|
||||||
|
@ -172,7 +172,9 @@ const DatasetDetails: React.FC<DatasetDetailsProps> = ({
|
|||||||
}, [tableDetails.id, getEntityPermission, setTablePermissions]);
|
}, [tableDetails.id, getEntityPermission, setTablePermissions]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchResourcePermission();
|
if (tableDetails.id) {
|
||||||
|
fetchResourcePermission();
|
||||||
|
}
|
||||||
}, [tableDetails.id]);
|
}, [tableDetails.id]);
|
||||||
|
|
||||||
const onEntityFieldSelect = (value: string) => {
|
const onEntityFieldSelect = (value: string) => {
|
||||||
|
@ -269,6 +269,31 @@ jest.mock('../PermissionProvider/PermissionProvider', () => ({
|
|||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../utils/PermissionsUtils', () => ({
|
||||||
|
DEFAULT_ENTITY_PERMISSION: {
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditCustomFields: true,
|
||||||
|
EditDataProfile: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
EditLineage: true,
|
||||||
|
EditOwner: true,
|
||||||
|
EditQueries: true,
|
||||||
|
EditSampleData: true,
|
||||||
|
EditTags: true,
|
||||||
|
EditTests: true,
|
||||||
|
EditTier: true,
|
||||||
|
ViewAll: true,
|
||||||
|
ViewDataProfile: true,
|
||||||
|
ViewQueries: true,
|
||||||
|
ViewSampleData: true,
|
||||||
|
ViewTests: true,
|
||||||
|
ViewUsage: true,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
describe('Test MyDataDetailsPage page', () => {
|
describe('Test MyDataDetailsPage page', () => {
|
||||||
it('Checks if the page has all the proper components rendered', async () => {
|
it('Checks if the page has all the proper components rendered', async () => {
|
||||||
const { container } = render(<DatasetDetails {...DatasetDetailsProps} />, {
|
const { container } = render(<DatasetDetails {...DatasetDetailsProps} />, {
|
||||||
|
@ -128,7 +128,9 @@ const MlModelDetail: FC<MlModelDetailProp> = ({
|
|||||||
}, [mlModelDetail.id, getEntityPermission, setPipelinePermissions]);
|
}, [mlModelDetail.id, getEntityPermission, setPipelinePermissions]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchResourcePermission();
|
if (mlModelDetail.id) {
|
||||||
|
fetchResourcePermission();
|
||||||
|
}
|
||||||
}, [mlModelDetail.id]);
|
}, [mlModelDetail.id]);
|
||||||
|
|
||||||
const currentUser = useMemo(
|
const currentUser = useMemo(
|
||||||
|
@ -65,6 +65,10 @@ export interface PermissionContextType {
|
|||||||
resource: ResourceEntity,
|
resource: ResourceEntity,
|
||||||
entityId: string
|
entityId: string
|
||||||
) => Promise<OperationPermission>;
|
) => Promise<OperationPermission>;
|
||||||
|
getEntityPermissionByFqn: (
|
||||||
|
resource: ResourceEntity,
|
||||||
|
entityFqn: string
|
||||||
|
) => Promise<OperationPermission>;
|
||||||
getResourcePermission: (
|
getResourcePermission: (
|
||||||
resource: ResourceEntity
|
resource: ResourceEntity
|
||||||
) => Promise<OperationPermission>;
|
) => Promise<OperationPermission>;
|
||||||
|
@ -23,6 +23,7 @@ import React, {
|
|||||||
} from 'react';
|
} from 'react';
|
||||||
import AppState from '../../AppState';
|
import AppState from '../../AppState';
|
||||||
import {
|
import {
|
||||||
|
getEntityPermissionByFqn,
|
||||||
getEntityPermissionById,
|
getEntityPermissionById,
|
||||||
getLoggedInUserPermissions,
|
getLoggedInUserPermissions,
|
||||||
getResourcePermission,
|
getResourcePermission,
|
||||||
@ -105,6 +106,25 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetchEntityPermissionByFqn = async (
|
||||||
|
resource: ResourceEntity,
|
||||||
|
entityFqn: string
|
||||||
|
) => {
|
||||||
|
const entityPermission = entitiesPermission[entityFqn];
|
||||||
|
if (entityPermission) {
|
||||||
|
return entityPermission;
|
||||||
|
} else {
|
||||||
|
const response = await getEntityPermissionByFqn(resource, entityFqn);
|
||||||
|
const operationPermission = getOperationPermissions(response);
|
||||||
|
setEntitiesPermission((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[entityFqn]: operationPermission,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return operationPermission;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const fetchResourcePermission = async (resource: ResourceEntity) => {
|
const fetchResourcePermission = async (resource: ResourceEntity) => {
|
||||||
const resourcePermission = resourcesPermission[resource];
|
const resourcePermission = resourcesPermission[resource];
|
||||||
if (resourcePermission) {
|
if (resourcePermission) {
|
||||||
@ -134,6 +154,7 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
|||||||
permissions,
|
permissions,
|
||||||
getEntityPermission: fetchEntityPermission,
|
getEntityPermission: fetchEntityPermission,
|
||||||
getResourcePermission: fetchResourcePermission,
|
getResourcePermission: fetchResourcePermission,
|
||||||
|
getEntityPermissionByFqn: fetchEntityPermissionByFqn,
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
</PermissionContext.Provider>
|
</PermissionContext.Provider>
|
||||||
|
@ -154,7 +154,9 @@ const PipelineDetails = ({
|
|||||||
}, [pipelineDetails.id, getEntityPermission, setPipelinePermissions]);
|
}, [pipelineDetails.id, getEntityPermission, setPipelinePermissions]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchResourcePermission();
|
if (pipelineDetails.id) {
|
||||||
|
fetchResourcePermission();
|
||||||
|
}
|
||||||
}, [pipelineDetails.id]);
|
}, [pipelineDetails.id]);
|
||||||
|
|
||||||
const onEntityFieldSelect = (value: string) => {
|
const onEntityFieldSelect = (value: string) => {
|
||||||
|
@ -272,12 +272,14 @@ const TableProfilerV1: FC<TableProfilerProps> = ({
|
|||||||
onAddTestClick={onAddTestClick}
|
onAddTestClick={onAddTestClick}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ProfilerSettingsModal
|
{settingModalVisible && (
|
||||||
columns={columns}
|
<ProfilerSettingsModal
|
||||||
tableId={table.id}
|
columns={columns}
|
||||||
visible={settingModalVisible}
|
tableId={table.id}
|
||||||
onVisibilityChange={handleSettingModal}
|
visible={settingModalVisible}
|
||||||
/>
|
onVisibilityChange={handleSettingModal}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -139,7 +139,9 @@ const TopicDetails: React.FC<TopicDetailsProps> = ({
|
|||||||
}, [topicDetails.id, getEntityPermission, setTopicPermissions]);
|
}, [topicDetails.id, getEntityPermission, setTopicPermissions]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchResourcePermission();
|
if (topicDetails.id) {
|
||||||
|
fetchResourcePermission();
|
||||||
|
}
|
||||||
}, [topicDetails.id]);
|
}, [topicDetails.id]);
|
||||||
|
|
||||||
const onEntityFieldSelect = (value: string) => {
|
const onEntityFieldSelect = (value: string) => {
|
||||||
|
@ -47,11 +47,14 @@ import {
|
|||||||
EdgeData,
|
EdgeData,
|
||||||
} from '../../components/EntityLineage/EntityLineage.interface';
|
} from '../../components/EntityLineage/EntityLineage.interface';
|
||||||
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 {
|
||||||
getDashboardDetailsPath,
|
getDashboardDetailsPath,
|
||||||
getServiceDetailsPath,
|
getServiceDetailsPath,
|
||||||
getVersionPath,
|
getVersionPath,
|
||||||
} from '../../constants/constants';
|
} from '../../constants/constants';
|
||||||
|
import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil';
|
||||||
import { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
import { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
||||||
import { FeedFilter } from '../../enums/mydata.enum';
|
import { FeedFilter } from '../../enums/mydata.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
@ -79,6 +82,7 @@ import {
|
|||||||
} from '../../utils/DashboardDetailsUtils';
|
} from '../../utils/DashboardDetailsUtils';
|
||||||
import { getEntityFeedLink, getEntityLineage } from '../../utils/EntityUtils';
|
import { getEntityFeedLink, getEntityLineage } from '../../utils/EntityUtils';
|
||||||
import { deletePost, updateThreadData } from '../../utils/FeedUtils';
|
import { deletePost, updateThreadData } from '../../utils/FeedUtils';
|
||||||
|
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||||
import { serviceTypeLogo } from '../../utils/ServiceUtils';
|
import { serviceTypeLogo } from '../../utils/ServiceUtils';
|
||||||
import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils';
|
import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
@ -90,6 +94,7 @@ export type ChartType = {
|
|||||||
const DashboardDetailsPage = () => {
|
const DashboardDetailsPage = () => {
|
||||||
const USERId = getCurrentUserId();
|
const USERId = getCurrentUserId();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||||
const { dashboardFQN, tab } = useParams() as Record<string, string>;
|
const { dashboardFQN, tab } = useParams() as Record<string, string>;
|
||||||
const [dashboardDetails, setDashboardDetails] = useState<Dashboard>(
|
const [dashboardDetails, setDashboardDetails] = useState<Dashboard>(
|
||||||
{} as Dashboard
|
{} as Dashboard
|
||||||
@ -136,6 +141,27 @@ const DashboardDetailsPage = () => {
|
|||||||
>([]);
|
>([]);
|
||||||
const [paging, setPaging] = useState<Paging>({} as Paging);
|
const [paging, setPaging] = useState<Paging>({} as Paging);
|
||||||
|
|
||||||
|
const [dashboardPermissions, setDashboardPermissions] = useState(
|
||||||
|
DEFAULT_ENTITY_PERMISSION
|
||||||
|
);
|
||||||
|
|
||||||
|
const fetchResourcePermission = async (entityFqn: string) => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const entityPermission = await getEntityPermissionByFqn(
|
||||||
|
ResourceEntity.DASHBOARD,
|
||||||
|
entityFqn
|
||||||
|
);
|
||||||
|
setDashboardPermissions(entityPermission);
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(
|
||||||
|
jsonData['api-error-messages']['fetch-entity-permissions-error']
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const activeTabHandler = (tabValue: number) => {
|
const activeTabHandler = (tabValue: number) => {
|
||||||
const currentTabIndex = tabValue - 1;
|
const currentTabIndex = tabValue - 1;
|
||||||
if (dashboardDetailsTabs[currentTabIndex].path !== tab) {
|
if (dashboardDetailsTabs[currentTabIndex].path !== tab) {
|
||||||
@ -727,9 +753,15 @@ const DashboardDetailsPage = () => {
|
|||||||
}, [activeTab]);
|
}, [activeTab]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchDashboardDetail(dashboardFQN);
|
if (dashboardPermissions.ViewAll) {
|
||||||
setEntityLineage({} as EntityLineage);
|
fetchDashboardDetail(dashboardFQN);
|
||||||
getEntityFeedCount();
|
setEntityLineage({} as EntityLineage);
|
||||||
|
getEntityFeedCount();
|
||||||
|
}
|
||||||
|
}, [dashboardFQN, dashboardPermissions]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchResourcePermission(dashboardFQN);
|
||||||
}, [dashboardFQN]);
|
}, [dashboardFQN]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -748,52 +780,58 @@ const DashboardDetailsPage = () => {
|
|||||||
{getEntityMissingError('dashboard', dashboardFQN)}
|
{getEntityMissingError('dashboard', dashboardFQN)}
|
||||||
</ErrorPlaceHolder>
|
</ErrorPlaceHolder>
|
||||||
) : (
|
) : (
|
||||||
<DashboardDetails
|
<>
|
||||||
activeTab={activeTab}
|
{dashboardPermissions.ViewAll ? (
|
||||||
addLineageHandler={addLineageHandler}
|
<DashboardDetails
|
||||||
chartDescriptionUpdateHandler={onChartUpdate}
|
activeTab={activeTab}
|
||||||
chartTagUpdateHandler={handleChartTagSelection}
|
addLineageHandler={addLineageHandler}
|
||||||
charts={charts}
|
chartDescriptionUpdateHandler={onChartUpdate}
|
||||||
createThread={createThread}
|
chartTagUpdateHandler={handleChartTagSelection}
|
||||||
dashboardDetails={dashboardDetails}
|
charts={charts}
|
||||||
dashboardFQN={dashboardFQN}
|
createThread={createThread}
|
||||||
dashboardTags={tags}
|
dashboardDetails={dashboardDetails}
|
||||||
dashboardUrl={dashboardUrl}
|
dashboardFQN={dashboardFQN}
|
||||||
deletePostHandler={deletePostHandler}
|
dashboardTags={tags}
|
||||||
deleted={deleted}
|
dashboardUrl={dashboardUrl}
|
||||||
description={description}
|
deletePostHandler={deletePostHandler}
|
||||||
descriptionUpdateHandler={descriptionUpdateHandler}
|
deleted={deleted}
|
||||||
entityFieldTaskCount={entityFieldTaskCount}
|
description={description}
|
||||||
entityFieldThreadCount={entityFieldThreadCount}
|
descriptionUpdateHandler={descriptionUpdateHandler}
|
||||||
entityLineage={entityLineage}
|
entityFieldTaskCount={entityFieldTaskCount}
|
||||||
entityLineageHandler={entityLineageHandler}
|
entityFieldThreadCount={entityFieldThreadCount}
|
||||||
entityName={displayName}
|
entityLineage={entityLineage}
|
||||||
entityThread={entityThread}
|
entityLineageHandler={entityLineageHandler}
|
||||||
feedCount={feedCount}
|
entityName={displayName}
|
||||||
fetchFeedHandler={getFeedData}
|
entityThread={entityThread}
|
||||||
followDashboardHandler={followDashboard}
|
feedCount={feedCount}
|
||||||
followers={followers}
|
fetchFeedHandler={getFeedData}
|
||||||
isLineageLoading={isLineageLoading}
|
followDashboardHandler={followDashboard}
|
||||||
isNodeLoading={isNodeLoading}
|
followers={followers}
|
||||||
isentityThreadLoading={isentityThreadLoading}
|
isLineageLoading={isLineageLoading}
|
||||||
lineageLeafNodes={leafNodes}
|
isNodeLoading={isNodeLoading}
|
||||||
loadNodeHandler={loadNodeHandler}
|
isentityThreadLoading={isentityThreadLoading}
|
||||||
owner={owner as EntityReference}
|
lineageLeafNodes={leafNodes}
|
||||||
paging={paging}
|
loadNodeHandler={loadNodeHandler}
|
||||||
postFeedHandler={postFeedHandler}
|
owner={owner as EntityReference}
|
||||||
removeLineageHandler={removeLineageHandler}
|
paging={paging}
|
||||||
serviceType={serviceType}
|
postFeedHandler={postFeedHandler}
|
||||||
setActiveTabHandler={activeTabHandler}
|
removeLineageHandler={removeLineageHandler}
|
||||||
settingsUpdateHandler={settingsUpdateHandler}
|
serviceType={serviceType}
|
||||||
slashedDashboardName={slashedDashboardName}
|
setActiveTabHandler={activeTabHandler}
|
||||||
tagUpdateHandler={onTagUpdate}
|
settingsUpdateHandler={settingsUpdateHandler}
|
||||||
tier={tier as TagLabel}
|
slashedDashboardName={slashedDashboardName}
|
||||||
unfollowDashboardHandler={unfollowDashboard}
|
tagUpdateHandler={onTagUpdate}
|
||||||
updateThreadHandler={updateThreadHandler}
|
tier={tier as TagLabel}
|
||||||
version={currentVersion as string}
|
unfollowDashboardHandler={unfollowDashboard}
|
||||||
versionHandler={versionHandler}
|
updateThreadHandler={updateThreadHandler}
|
||||||
onExtensionUpdate={handleExtentionUpdate}
|
version={currentVersion as string}
|
||||||
/>
|
versionHandler={versionHandler}
|
||||||
|
onExtensionUpdate={handleExtentionUpdate}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -50,6 +50,11 @@ import {
|
|||||||
EdgeData,
|
EdgeData,
|
||||||
} from '../../components/EntityLineage/EntityLineage.interface';
|
} from '../../components/EntityLineage/EntityLineage.interface';
|
||||||
import Loader from '../../components/Loader/Loader';
|
import Loader from '../../components/Loader/Loader';
|
||||||
|
import { usePermissionProvider } from '../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import {
|
||||||
|
OperationPermission,
|
||||||
|
ResourceEntity,
|
||||||
|
} from '../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants';
|
import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants';
|
||||||
import {
|
import {
|
||||||
getDatabaseDetailsPath,
|
getDatabaseDetailsPath,
|
||||||
@ -58,6 +63,7 @@ import {
|
|||||||
getTableTabPath,
|
getTableTabPath,
|
||||||
getVersionPath,
|
getVersionPath,
|
||||||
} from '../../constants/constants';
|
} from '../../constants/constants';
|
||||||
|
import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil';
|
||||||
import { EntityType, FqnPart, TabSpecificField } from '../../enums/entity.enum';
|
import { EntityType, FqnPart, TabSpecificField } from '../../enums/entity.enum';
|
||||||
import { FeedFilter } from '../../enums/mydata.enum';
|
import { FeedFilter } from '../../enums/mydata.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
@ -100,12 +106,14 @@ import {
|
|||||||
} from '../../utils/DatasetDetailsUtils';
|
} from '../../utils/DatasetDetailsUtils';
|
||||||
import { getEntityFeedLink, getEntityLineage } from '../../utils/EntityUtils';
|
import { getEntityFeedLink, getEntityLineage } from '../../utils/EntityUtils';
|
||||||
import { deletePost, updateThreadData } from '../../utils/FeedUtils';
|
import { deletePost, updateThreadData } from '../../utils/FeedUtils';
|
||||||
|
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||||
import { serviceTypeLogo } from '../../utils/ServiceUtils';
|
import { serviceTypeLogo } from '../../utils/ServiceUtils';
|
||||||
import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils';
|
import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils';
|
||||||
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
||||||
|
|
||||||
const DatasetDetailsPage: FunctionComponent = () => {
|
const DatasetDetailsPage: FunctionComponent = () => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||||
const [isLineageLoading, setIsLineageLoading] = useState<boolean>(false);
|
const [isLineageLoading, setIsLineageLoading] = useState<boolean>(false);
|
||||||
const [isSampleDataLoading, setIsSampleDataLoading] =
|
const [isSampleDataLoading, setIsSampleDataLoading] =
|
||||||
@ -174,6 +182,10 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
|||||||
EntityFieldThreadCount[]
|
EntityFieldThreadCount[]
|
||||||
>([]);
|
>([]);
|
||||||
|
|
||||||
|
const [tablePermissions, setTablePermissions] = useState<OperationPermission>(
|
||||||
|
DEFAULT_ENTITY_PERMISSION
|
||||||
|
);
|
||||||
|
|
||||||
// Data Quality tab state
|
// Data Quality tab state
|
||||||
const [testMode, setTestMode] = useState<DatasetTestModeType>('table');
|
const [testMode, setTestMode] = useState<DatasetTestModeType>('table');
|
||||||
const [showTestForm, setShowTestForm] = useState(false);
|
const [showTestForm, setShowTestForm] = useState(false);
|
||||||
@ -289,6 +301,24 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
|||||||
getFeedData(after, feedType, threadType);
|
getFeedData(after, feedType, threadType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetchResourcePermission = async (entityFqn: string) => {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const tablePermission = await getEntityPermissionByFqn(
|
||||||
|
ResourceEntity.TABLE,
|
||||||
|
entityFqn
|
||||||
|
);
|
||||||
|
|
||||||
|
setTablePermissions(tablePermission);
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(
|
||||||
|
jsonData['api-error-messages']['fetch-entity-permissions-error']
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const fetchTableDetail = () => {
|
const fetchTableDetail = () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
getTableDetailsByFQN(
|
getTableDetailsByFQN(
|
||||||
@ -945,9 +975,15 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTableDetail();
|
if (tablePermissions.ViewAll) {
|
||||||
setActiveTab(getCurrentDatasetTab(tab));
|
fetchTableDetail();
|
||||||
getEntityFeedCount();
|
setActiveTab(getCurrentDatasetTab(tab));
|
||||||
|
getEntityFeedCount();
|
||||||
|
}
|
||||||
|
}, [tablePermissions]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchResourcePermission(tableFQN);
|
||||||
}, [tableFQN]);
|
}, [tableFQN]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -970,70 +1006,76 @@ const DatasetDetailsPage: FunctionComponent = () => {
|
|||||||
{getEntityMissingError('table', tableFQN)}
|
{getEntityMissingError('table', tableFQN)}
|
||||||
</ErrorPlaceHolder>
|
</ErrorPlaceHolder>
|
||||||
) : (
|
) : (
|
||||||
<DatasetDetails
|
<>
|
||||||
activeTab={activeTab}
|
{tablePermissions.ViewAll ? (
|
||||||
addLineageHandler={addLineageHandler}
|
<DatasetDetails
|
||||||
columns={columns}
|
activeTab={activeTab}
|
||||||
columnsUpdateHandler={columnsUpdateHandler}
|
addLineageHandler={addLineageHandler}
|
||||||
createThread={createThread}
|
columns={columns}
|
||||||
dataModel={tableDetails.dataModel}
|
columnsUpdateHandler={columnsUpdateHandler}
|
||||||
datasetFQN={tableFQN}
|
createThread={createThread}
|
||||||
deletePostHandler={deletePostHandler}
|
dataModel={tableDetails.dataModel}
|
||||||
deleted={deleted}
|
datasetFQN={tableFQN}
|
||||||
description={description}
|
deletePostHandler={deletePostHandler}
|
||||||
descriptionUpdateHandler={descriptionUpdateHandler}
|
deleted={deleted}
|
||||||
entityFieldTaskCount={entityFieldTaskCount}
|
description={description}
|
||||||
entityFieldThreadCount={entityFieldThreadCount}
|
descriptionUpdateHandler={descriptionUpdateHandler}
|
||||||
entityLineage={entityLineage}
|
entityFieldTaskCount={entityFieldTaskCount}
|
||||||
entityLineageHandler={entityLineageHandler}
|
entityFieldThreadCount={entityFieldThreadCount}
|
||||||
entityName={name}
|
entityLineage={entityLineage}
|
||||||
entityThread={entityThread}
|
entityLineageHandler={entityLineageHandler}
|
||||||
feedCount={feedCount}
|
entityName={name}
|
||||||
fetchFeedHandler={handleFeedFetchFromFeedList}
|
entityThread={entityThread}
|
||||||
followTableHandler={followTable}
|
feedCount={feedCount}
|
||||||
followers={followers}
|
fetchFeedHandler={handleFeedFetchFromFeedList}
|
||||||
handleAddColumnTestCase={handleAddColumnTestCase}
|
followTableHandler={followTable}
|
||||||
handleAddTableTestCase={handleAddTableTestCase}
|
followers={followers}
|
||||||
handleExtentionUpdate={handleExtentionUpdate}
|
handleAddColumnTestCase={handleAddColumnTestCase}
|
||||||
handleRemoveColumnTest={handleRemoveColumnTest}
|
handleAddTableTestCase={handleAddTableTestCase}
|
||||||
handleRemoveTableTest={handleRemoveTableTest}
|
handleExtentionUpdate={handleExtentionUpdate}
|
||||||
handleSelectedColumn={handleSelectedColumn}
|
handleRemoveColumnTest={handleRemoveColumnTest}
|
||||||
handleShowTestForm={handleShowTestForm}
|
handleRemoveTableTest={handleRemoveTableTest}
|
||||||
handleTestModeChange={handleTestModeChange}
|
handleSelectedColumn={handleSelectedColumn}
|
||||||
isLineageLoading={isLineageLoading}
|
handleShowTestForm={handleShowTestForm}
|
||||||
isNodeLoading={isNodeLoading}
|
handleTestModeChange={handleTestModeChange}
|
||||||
isQueriesLoading={isTableQueriesLoading}
|
isLineageLoading={isLineageLoading}
|
||||||
isSampleDataLoading={isSampleDataLoading}
|
isNodeLoading={isNodeLoading}
|
||||||
isentityThreadLoading={isentityThreadLoading}
|
isQueriesLoading={isTableQueriesLoading}
|
||||||
joins={joins}
|
isSampleDataLoading={isSampleDataLoading}
|
||||||
lineageLeafNodes={leafNodes}
|
isentityThreadLoading={isentityThreadLoading}
|
||||||
loadNodeHandler={loadNodeHandler}
|
joins={joins}
|
||||||
owner={owner as EntityReference}
|
lineageLeafNodes={leafNodes}
|
||||||
paging={paging}
|
loadNodeHandler={loadNodeHandler}
|
||||||
postFeedHandler={postFeedHandler}
|
owner={owner as EntityReference}
|
||||||
qualityTestFormHandler={qualityTestFormHandler}
|
paging={paging}
|
||||||
removeLineageHandler={removeLineageHandler}
|
postFeedHandler={postFeedHandler}
|
||||||
sampleData={sampleData}
|
qualityTestFormHandler={qualityTestFormHandler}
|
||||||
selectedColumn={selectedColumn as string}
|
removeLineageHandler={removeLineageHandler}
|
||||||
setActiveTabHandler={activeTabHandler}
|
sampleData={sampleData}
|
||||||
settingsUpdateHandler={settingsUpdateHandler}
|
selectedColumn={selectedColumn as string}
|
||||||
showTestForm={showTestForm}
|
setActiveTabHandler={activeTabHandler}
|
||||||
slashedTableName={slashedTableName}
|
settingsUpdateHandler={settingsUpdateHandler}
|
||||||
tableDetails={tableDetails}
|
showTestForm={showTestForm}
|
||||||
tableProfile={tableProfile}
|
slashedTableName={slashedTableName}
|
||||||
tableQueries={tableQueries}
|
tableDetails={tableDetails}
|
||||||
tableTags={tableTags}
|
tableProfile={tableProfile}
|
||||||
tableTestCase={tableTestCase}
|
tableQueries={tableQueries}
|
||||||
tableType={tableType}
|
tableTags={tableTags}
|
||||||
tagUpdateHandler={onTagUpdate}
|
tableTestCase={tableTestCase}
|
||||||
testMode={testMode}
|
tableType={tableType}
|
||||||
tier={tier as TagLabel}
|
tagUpdateHandler={onTagUpdate}
|
||||||
unfollowTableHandler={unfollowTable}
|
testMode={testMode}
|
||||||
updateThreadHandler={updateThreadHandler}
|
tier={tier as TagLabel}
|
||||||
usageSummary={usageSummary}
|
unfollowTableHandler={unfollowTable}
|
||||||
version={currentVersion}
|
updateThreadHandler={updateThreadHandler}
|
||||||
versionHandler={versionHandler}
|
usageSummary={usageSummary}
|
||||||
/>
|
version={currentVersion}
|
||||||
|
versionHandler={versionHandler}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -70,6 +70,59 @@ jest.mock('../../AppState', () => ({
|
|||||||
],
|
],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../components/PermissionProvider/PermissionProvider', () => ({
|
||||||
|
usePermissionProvider: jest.fn().mockImplementation(() => ({
|
||||||
|
permissions: {},
|
||||||
|
getEntityPermission: jest.fn().mockResolvedValue({
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditCustomFields: true,
|
||||||
|
EditDataProfile: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
EditLineage: true,
|
||||||
|
EditOwner: true,
|
||||||
|
EditQueries: true,
|
||||||
|
EditSampleData: true,
|
||||||
|
EditTags: true,
|
||||||
|
EditTests: true,
|
||||||
|
EditTier: true,
|
||||||
|
ViewAll: true,
|
||||||
|
ViewDataProfile: true,
|
||||||
|
ViewQueries: true,
|
||||||
|
ViewSampleData: true,
|
||||||
|
ViewTests: true,
|
||||||
|
ViewUsage: true,
|
||||||
|
}),
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../utils/PermissionsUtils', () => ({
|
||||||
|
DEFAULT_ENTITY_PERMISSION: {
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditCustomFields: true,
|
||||||
|
EditDataProfile: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
EditLineage: true,
|
||||||
|
EditOwner: true,
|
||||||
|
EditQueries: true,
|
||||||
|
EditSampleData: true,
|
||||||
|
EditTags: true,
|
||||||
|
EditTests: true,
|
||||||
|
EditTier: true,
|
||||||
|
ViewAll: true,
|
||||||
|
ViewDataProfile: true,
|
||||||
|
ViewQueries: true,
|
||||||
|
ViewSampleData: true,
|
||||||
|
ViewTests: true,
|
||||||
|
ViewUsage: true,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
jest.mock('../../components/DatasetDetails/DatasetDetails.component', () => {
|
jest.mock('../../components/DatasetDetails/DatasetDetails.component', () => {
|
||||||
return jest
|
return jest
|
||||||
.fn()
|
.fn()
|
||||||
|
@ -153,6 +153,59 @@ jest.mock('../../components/MlModelDetail/MlModelDetail.component', () => {
|
|||||||
.mockReturnValue(<div data-testid="mlmodel-details">MlModelDetails</div>);
|
.mockReturnValue(<div data-testid="mlmodel-details">MlModelDetails</div>);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
jest.mock('../../components/PermissionProvider/PermissionProvider', () => ({
|
||||||
|
usePermissionProvider: jest.fn().mockImplementation(() => ({
|
||||||
|
permissions: {},
|
||||||
|
getEntityPermission: jest.fn().mockResolvedValue({
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditCustomFields: true,
|
||||||
|
EditDataProfile: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
EditLineage: true,
|
||||||
|
EditOwner: true,
|
||||||
|
EditQueries: true,
|
||||||
|
EditSampleData: true,
|
||||||
|
EditTags: true,
|
||||||
|
EditTests: true,
|
||||||
|
EditTier: true,
|
||||||
|
ViewAll: true,
|
||||||
|
ViewDataProfile: true,
|
||||||
|
ViewQueries: true,
|
||||||
|
ViewSampleData: true,
|
||||||
|
ViewTests: true,
|
||||||
|
ViewUsage: true,
|
||||||
|
}),
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../utils/PermissionsUtils', () => ({
|
||||||
|
DEFAULT_ENTITY_PERMISSION: {
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditCustomFields: true,
|
||||||
|
EditDataProfile: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
EditLineage: true,
|
||||||
|
EditOwner: true,
|
||||||
|
EditQueries: true,
|
||||||
|
EditSampleData: true,
|
||||||
|
EditTags: true,
|
||||||
|
EditTests: true,
|
||||||
|
EditTier: true,
|
||||||
|
ViewAll: true,
|
||||||
|
ViewDataProfile: true,
|
||||||
|
ViewQueries: true,
|
||||||
|
ViewSampleData: true,
|
||||||
|
ViewTests: true,
|
||||||
|
ViewUsage: true,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
describe('Test MlModel Entity Page', () => {
|
describe('Test MlModel Entity Page', () => {
|
||||||
it('Should render component', async () => {
|
it('Should render component', async () => {
|
||||||
const { container } = render(<MlModelPageComponent />, {
|
const { container } = render(<MlModelPageComponent />, {
|
||||||
|
@ -33,7 +33,10 @@ import {
|
|||||||
} from '../../components/EntityLineage/EntityLineage.interface';
|
} from '../../components/EntityLineage/EntityLineage.interface';
|
||||||
import Loader from '../../components/Loader/Loader';
|
import Loader from '../../components/Loader/Loader';
|
||||||
import MlModelDetailComponent from '../../components/MlModelDetail/MlModelDetail.component';
|
import MlModelDetailComponent from '../../components/MlModelDetail/MlModelDetail.component';
|
||||||
|
import { usePermissionProvider } from '../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import { ResourceEntity } from '../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { getMlModelPath } from '../../constants/constants';
|
import { getMlModelPath } from '../../constants/constants';
|
||||||
|
import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil';
|
||||||
import { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
import { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
||||||
import { Mlmodel } from '../../generated/entity/data/mlmodel';
|
import { Mlmodel } from '../../generated/entity/data/mlmodel';
|
||||||
import {
|
import {
|
||||||
@ -51,6 +54,7 @@ import {
|
|||||||
getCurrentMlModelTab,
|
getCurrentMlModelTab,
|
||||||
mlModelTabs,
|
mlModelTabs,
|
||||||
} from '../../utils/MlModelDetailsUtils';
|
} from '../../utils/MlModelDetailsUtils';
|
||||||
|
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
|
|
||||||
const MlModelPage = () => {
|
const MlModelPage = () => {
|
||||||
@ -71,6 +75,29 @@ const MlModelPage = () => {
|
|||||||
});
|
});
|
||||||
const [isLineageLoading, setIsLineageLoading] = useState<boolean>(false);
|
const [isLineageLoading, setIsLineageLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const [mlModelPermissions, setPipelinePermissions] = useState(
|
||||||
|
DEFAULT_ENTITY_PERMISSION
|
||||||
|
);
|
||||||
|
|
||||||
|
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||||
|
|
||||||
|
const fetchResourcePermission = async (entityFqn: string) => {
|
||||||
|
setIsDetailLoading(true);
|
||||||
|
try {
|
||||||
|
const entityPermission = await getEntityPermissionByFqn(
|
||||||
|
ResourceEntity.ML_MODEL,
|
||||||
|
entityFqn
|
||||||
|
);
|
||||||
|
setPipelinePermissions(entityPermission);
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(
|
||||||
|
jsonData['api-error-messages']['fetch-entity-permissions-error']
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
setIsDetailLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getLineageData = () => {
|
const getLineageData = () => {
|
||||||
setIsLineageLoading(true);
|
setIsLineageLoading(true);
|
||||||
getLineageByFQN(mlModelDetail.fullyQualifiedName ?? '', EntityType.MLMODEL)
|
getLineageByFQN(mlModelDetail.fullyQualifiedName ?? '', EntityType.MLMODEL)
|
||||||
@ -404,11 +431,29 @@ const MlModelPage = () => {
|
|||||||
}, [activeTab, mlModelDetail]);
|
}, [activeTab, mlModelDetail]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchMlModelDetails(mlModelFqn);
|
if (mlModelPermissions.ViewAll) {
|
||||||
|
fetchMlModelDetails(mlModelFqn);
|
||||||
|
}
|
||||||
|
}, [mlModelPermissions, mlModelFqn]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchResourcePermission(mlModelFqn);
|
||||||
}, [mlModelFqn]);
|
}, [mlModelFqn]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>{isDetailLoading ? <Loader /> : getMlModelDetail()}</Fragment>
|
<Fragment>
|
||||||
|
{isDetailLoading ? (
|
||||||
|
<Loader />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{mlModelPermissions.ViewAll ? (
|
||||||
|
getMlModelDetail()
|
||||||
|
) : (
|
||||||
|
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,12 +46,15 @@ import {
|
|||||||
EdgeData,
|
EdgeData,
|
||||||
} from '../../components/EntityLineage/EntityLineage.interface';
|
} from '../../components/EntityLineage/EntityLineage.interface';
|
||||||
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 PipelineDetails from '../../components/PipelineDetails/PipelineDetails.component';
|
import PipelineDetails from '../../components/PipelineDetails/PipelineDetails.component';
|
||||||
import {
|
import {
|
||||||
getPipelineDetailsPath,
|
getPipelineDetailsPath,
|
||||||
getServiceDetailsPath,
|
getServiceDetailsPath,
|
||||||
getVersionPath,
|
getVersionPath,
|
||||||
} from '../../constants/constants';
|
} from '../../constants/constants';
|
||||||
|
import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil';
|
||||||
import { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
import { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
||||||
import { FeedFilter } from '../../enums/mydata.enum';
|
import { FeedFilter } from '../../enums/mydata.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
@ -73,6 +76,7 @@ import {
|
|||||||
} from '../../utils/CommonUtils';
|
} from '../../utils/CommonUtils';
|
||||||
import { getEntityFeedLink, getEntityLineage } from '../../utils/EntityUtils';
|
import { getEntityFeedLink, getEntityLineage } from '../../utils/EntityUtils';
|
||||||
import { deletePost, updateThreadData } from '../../utils/FeedUtils';
|
import { deletePost, updateThreadData } from '../../utils/FeedUtils';
|
||||||
|
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||||
import {
|
import {
|
||||||
defaultFields,
|
defaultFields,
|
||||||
getCurrentPipelineTab,
|
getCurrentPipelineTab,
|
||||||
@ -137,6 +141,29 @@ const PipelineDetailsPage = () => {
|
|||||||
EntityFieldThreadCount[]
|
EntityFieldThreadCount[]
|
||||||
>([]);
|
>([]);
|
||||||
|
|
||||||
|
const [pipelinePermissions, setPipelinePermissions] = useState(
|
||||||
|
DEFAULT_ENTITY_PERMISSION
|
||||||
|
);
|
||||||
|
|
||||||
|
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||||
|
|
||||||
|
const fetchResourcePermission = async (entityFqn: string) => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const entityPermission = await getEntityPermissionByFqn(
|
||||||
|
ResourceEntity.PIPELINE,
|
||||||
|
entityFqn
|
||||||
|
);
|
||||||
|
setPipelinePermissions(entityPermission);
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(
|
||||||
|
jsonData['api-error-messages']['fetch-entity-permissions-error']
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const activeTabHandler = (tabValue: number) => {
|
const activeTabHandler = (tabValue: number) => {
|
||||||
const currentTabIndex = tabValue - 1;
|
const currentTabIndex = tabValue - 1;
|
||||||
if (pipelineDetailsTabs[currentTabIndex].path !== tab) {
|
if (pipelineDetailsTabs[currentTabIndex].path !== tab) {
|
||||||
@ -668,9 +695,15 @@ const PipelineDetailsPage = () => {
|
|||||||
}, [activeTab]);
|
}, [activeTab]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchPipelineDetail(pipelineFQN);
|
if (pipelinePermissions.ViewAll) {
|
||||||
setEntityLineage({} as EntityLineage);
|
fetchPipelineDetail(pipelineFQN);
|
||||||
getEntityFeedCount();
|
setEntityLineage({} as EntityLineage);
|
||||||
|
getEntityFeedCount();
|
||||||
|
}
|
||||||
|
}, [pipelinePermissions, pipelineFQN]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchResourcePermission(pipelineFQN);
|
||||||
}, [pipelineFQN]);
|
}, [pipelineFQN]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -689,52 +722,58 @@ const PipelineDetailsPage = () => {
|
|||||||
{getEntityMissingError('pipeline', pipelineFQN)}
|
{getEntityMissingError('pipeline', pipelineFQN)}
|
||||||
</ErrorPlaceHolder>
|
</ErrorPlaceHolder>
|
||||||
) : (
|
) : (
|
||||||
<PipelineDetails
|
<>
|
||||||
activeTab={activeTab}
|
{pipelinePermissions.ViewAll ? (
|
||||||
addLineageHandler={addLineageHandler}
|
<PipelineDetails
|
||||||
createThread={createThread}
|
activeTab={activeTab}
|
||||||
deletePostHandler={deletePostHandler}
|
addLineageHandler={addLineageHandler}
|
||||||
deleted={deleted}
|
createThread={createThread}
|
||||||
description={description}
|
deletePostHandler={deletePostHandler}
|
||||||
descriptionUpdateHandler={descriptionUpdateHandler}
|
deleted={deleted}
|
||||||
entityFieldTaskCount={entityFieldTaskCount}
|
description={description}
|
||||||
entityFieldThreadCount={entityFieldThreadCount}
|
descriptionUpdateHandler={descriptionUpdateHandler}
|
||||||
entityLineage={entityLineage}
|
entityFieldTaskCount={entityFieldTaskCount}
|
||||||
entityLineageHandler={entityLineageHandler}
|
entityFieldThreadCount={entityFieldThreadCount}
|
||||||
entityName={displayName}
|
entityLineage={entityLineage}
|
||||||
entityThread={entityThread}
|
entityLineageHandler={entityLineageHandler}
|
||||||
feedCount={feedCount}
|
entityName={displayName}
|
||||||
fetchFeedHandler={handleFeedFetchFromFeedList}
|
entityThread={entityThread}
|
||||||
followPipelineHandler={followPipeline}
|
feedCount={feedCount}
|
||||||
followers={followers}
|
fetchFeedHandler={handleFeedFetchFromFeedList}
|
||||||
isLineageLoading={isLineageLoading}
|
followPipelineHandler={followPipeline}
|
||||||
isNodeLoading={isNodeLoading}
|
followers={followers}
|
||||||
isentityThreadLoading={isentityThreadLoading}
|
isLineageLoading={isLineageLoading}
|
||||||
lineageLeafNodes={leafNodes}
|
isNodeLoading={isNodeLoading}
|
||||||
loadNodeHandler={loadNodeHandler}
|
isentityThreadLoading={isentityThreadLoading}
|
||||||
owner={owner as EntityReference}
|
lineageLeafNodes={leafNodes}
|
||||||
paging={paging}
|
loadNodeHandler={loadNodeHandler}
|
||||||
pipelineDetails={pipelineDetails}
|
owner={owner as EntityReference}
|
||||||
pipelineFQN={pipelineFQN}
|
paging={paging}
|
||||||
pipelineStatus={pipeLineStatus}
|
pipelineDetails={pipelineDetails}
|
||||||
pipelineTags={tags}
|
pipelineFQN={pipelineFQN}
|
||||||
pipelineUrl={pipelineUrl}
|
pipelineStatus={pipeLineStatus}
|
||||||
postFeedHandler={postFeedHandler}
|
pipelineTags={tags}
|
||||||
removeLineageHandler={removeLineageHandler}
|
pipelineUrl={pipelineUrl}
|
||||||
serviceType={serviceType}
|
postFeedHandler={postFeedHandler}
|
||||||
setActiveTabHandler={activeTabHandler}
|
removeLineageHandler={removeLineageHandler}
|
||||||
settingsUpdateHandler={settingsUpdateHandler}
|
serviceType={serviceType}
|
||||||
slashedPipelineName={slashedPipelineName}
|
setActiveTabHandler={activeTabHandler}
|
||||||
tagUpdateHandler={onTagUpdate}
|
settingsUpdateHandler={settingsUpdateHandler}
|
||||||
taskUpdateHandler={onTaskUpdate}
|
slashedPipelineName={slashedPipelineName}
|
||||||
tasks={tasks}
|
tagUpdateHandler={onTagUpdate}
|
||||||
tier={tier as TagLabel}
|
taskUpdateHandler={onTaskUpdate}
|
||||||
unfollowPipelineHandler={unfollowPipeline}
|
tasks={tasks}
|
||||||
updateThreadHandler={updateThreadHandler}
|
tier={tier as TagLabel}
|
||||||
version={currentVersion as string}
|
unfollowPipelineHandler={unfollowPipeline}
|
||||||
versionHandler={versionHandler}
|
updateThreadHandler={updateThreadHandler}
|
||||||
onExtensionUpdate={handleExtentionUpdate}
|
version={currentVersion as string}
|
||||||
/>
|
versionHandler={versionHandler}
|
||||||
|
onExtensionUpdate={handleExtentionUpdate}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -38,6 +38,59 @@ jest.mock(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
jest.mock('../../components/PermissionProvider/PermissionProvider', () => ({
|
||||||
|
usePermissionProvider: jest.fn().mockImplementation(() => ({
|
||||||
|
permissions: {},
|
||||||
|
getEntityPermission: jest.fn().mockResolvedValue({
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditCustomFields: true,
|
||||||
|
EditDataProfile: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
EditLineage: true,
|
||||||
|
EditOwner: true,
|
||||||
|
EditQueries: true,
|
||||||
|
EditSampleData: true,
|
||||||
|
EditTags: true,
|
||||||
|
EditTests: true,
|
||||||
|
EditTier: true,
|
||||||
|
ViewAll: true,
|
||||||
|
ViewDataProfile: true,
|
||||||
|
ViewQueries: true,
|
||||||
|
ViewSampleData: true,
|
||||||
|
ViewTests: true,
|
||||||
|
ViewUsage: true,
|
||||||
|
}),
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../utils/PermissionsUtils', () => ({
|
||||||
|
DEFAULT_ENTITY_PERMISSION: {
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditCustomFields: true,
|
||||||
|
EditDataProfile: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
EditLineage: true,
|
||||||
|
EditOwner: true,
|
||||||
|
EditQueries: true,
|
||||||
|
EditSampleData: true,
|
||||||
|
EditTags: true,
|
||||||
|
EditTests: true,
|
||||||
|
EditTier: true,
|
||||||
|
ViewAll: true,
|
||||||
|
ViewDataProfile: true,
|
||||||
|
ViewQueries: true,
|
||||||
|
ViewSampleData: true,
|
||||||
|
ViewTests: true,
|
||||||
|
ViewUsage: true,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
describe('Test PipelineDetailsPage component', () => {
|
describe('Test PipelineDetailsPage component', () => {
|
||||||
it('PipelineDetailsPage component should render properly', async () => {
|
it('PipelineDetailsPage component should render properly', async () => {
|
||||||
const { container } = render(<PipelineDetailsPage />, {
|
const { container } = render(<PipelineDetailsPage />, {
|
||||||
|
@ -45,12 +45,18 @@ import {
|
|||||||
EdgeData,
|
EdgeData,
|
||||||
} from '../../components/EntityLineage/EntityLineage.interface';
|
} from '../../components/EntityLineage/EntityLineage.interface';
|
||||||
import Loader from '../../components/Loader/Loader';
|
import Loader from '../../components/Loader/Loader';
|
||||||
|
import { usePermissionProvider } from '../../components/PermissionProvider/PermissionProvider';
|
||||||
|
import {
|
||||||
|
OperationPermission,
|
||||||
|
ResourceEntity,
|
||||||
|
} from '../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
import TopicDetails from '../../components/TopicDetails/TopicDetails.component';
|
import TopicDetails from '../../components/TopicDetails/TopicDetails.component';
|
||||||
import {
|
import {
|
||||||
getServiceDetailsPath,
|
getServiceDetailsPath,
|
||||||
getTopicDetailsPath,
|
getTopicDetailsPath,
|
||||||
getVersionPath,
|
getVersionPath,
|
||||||
} from '../../constants/constants';
|
} from '../../constants/constants';
|
||||||
|
import { NO_PERMISSION_TO_VIEW } from '../../constants/HelperTextUtil';
|
||||||
import { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
import { EntityType, TabSpecificField } from '../../enums/entity.enum';
|
||||||
import { FeedFilter } from '../../enums/mydata.enum';
|
import { FeedFilter } from '../../enums/mydata.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
@ -71,6 +77,7 @@ import {
|
|||||||
} from '../../utils/CommonUtils';
|
} from '../../utils/CommonUtils';
|
||||||
import { getEntityFeedLink, getEntityLineage } from '../../utils/EntityUtils';
|
import { getEntityFeedLink, getEntityLineage } from '../../utils/EntityUtils';
|
||||||
import { deletePost, updateThreadData } from '../../utils/FeedUtils';
|
import { deletePost, updateThreadData } from '../../utils/FeedUtils';
|
||||||
|
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||||
import { serviceTypeLogo } from '../../utils/ServiceUtils';
|
import { serviceTypeLogo } from '../../utils/ServiceUtils';
|
||||||
import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils';
|
import { getTagsWithoutTier, getTierTags } from '../../utils/TableUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
@ -82,6 +89,7 @@ import {
|
|||||||
const TopicDetailsPage: FunctionComponent = () => {
|
const TopicDetailsPage: FunctionComponent = () => {
|
||||||
const USERId = getCurrentUserId();
|
const USERId = getCurrentUserId();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||||
|
|
||||||
const { topicFQN, tab } = useParams() as Record<string, string>;
|
const { topicFQN, tab } = useParams() as Record<string, string>;
|
||||||
const [topicDetails, setTopicDetails] = useState<Topic>({} as Topic);
|
const [topicDetails, setTopicDetails] = useState<Topic>({} as Topic);
|
||||||
@ -133,6 +141,10 @@ const TopicDetailsPage: FunctionComponent = () => {
|
|||||||
});
|
});
|
||||||
const [isLineageLoading, setIsLineageLoading] = useState<boolean>(false);
|
const [isLineageLoading, setIsLineageLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const [topicPermissions, setTopicPermissions] = useState<OperationPermission>(
|
||||||
|
DEFAULT_ENTITY_PERMISSION
|
||||||
|
);
|
||||||
|
|
||||||
const getLineageData = () => {
|
const getLineageData = () => {
|
||||||
setIsLineageLoading(true);
|
setIsLineageLoading(true);
|
||||||
getLineageByFQN(topicFQN, EntityType.TOPIC)
|
getLineageByFQN(topicFQN, EntityType.TOPIC)
|
||||||
@ -352,6 +364,23 @@ const TopicDetailsPage: FunctionComponent = () => {
|
|||||||
return patchTopicDetails(topicId, jsonPatch);
|
return patchTopicDetails(topicId, jsonPatch);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetchResourcePermission = async (entityFqn: string) => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const permissions = await getEntityPermissionByFqn(
|
||||||
|
ResourceEntity.TOPIC,
|
||||||
|
entityFqn
|
||||||
|
);
|
||||||
|
setTopicPermissions(permissions);
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(
|
||||||
|
jsonData['api-error-messages']['fetch-entity-permissions-error']
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const fetchTopicDetail = (topicFQN: string) => {
|
const fetchTopicDetail = (topicFQN: string) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
getTopicByFqn(topicFQN, [
|
getTopicByFqn(topicFQN, [
|
||||||
@ -662,10 +691,16 @@ const TopicDetailsPage: FunctionComponent = () => {
|
|||||||
}, [activeTab]);
|
}, [activeTab]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTopicDetail(topicFQN);
|
fetchResourcePermission(topicFQN);
|
||||||
getEntityFeedCount();
|
|
||||||
}, [topicFQN]);
|
}, [topicFQN]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (topicPermissions.ViewAll) {
|
||||||
|
fetchTopicDetail(topicFQN);
|
||||||
|
getEntityFeedCount();
|
||||||
|
}
|
||||||
|
}, [topicPermissions, topicFQN]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
@ -675,58 +710,64 @@ const TopicDetailsPage: FunctionComponent = () => {
|
|||||||
{getEntityMissingError('topic', topicFQN)}
|
{getEntityMissingError('topic', topicFQN)}
|
||||||
</ErrorPlaceHolder>
|
</ErrorPlaceHolder>
|
||||||
) : (
|
) : (
|
||||||
<TopicDetails
|
<>
|
||||||
activeTab={activeTab}
|
{topicPermissions.ViewAll ? (
|
||||||
cleanupPolicies={cleanupPolicies}
|
<TopicDetails
|
||||||
createThread={createThread}
|
activeTab={activeTab}
|
||||||
deletePostHandler={deletePostHandler}
|
cleanupPolicies={cleanupPolicies}
|
||||||
deleted={deleted}
|
createThread={createThread}
|
||||||
description={description}
|
deletePostHandler={deletePostHandler}
|
||||||
descriptionUpdateHandler={descriptionUpdateHandler}
|
deleted={deleted}
|
||||||
entityFieldTaskCount={entityFieldTaskCount}
|
description={description}
|
||||||
entityFieldThreadCount={entityFieldThreadCount}
|
descriptionUpdateHandler={descriptionUpdateHandler}
|
||||||
entityName={name}
|
entityFieldTaskCount={entityFieldTaskCount}
|
||||||
entityThread={entityThread}
|
entityFieldThreadCount={entityFieldThreadCount}
|
||||||
feedCount={feedCount}
|
entityName={name}
|
||||||
fetchFeedHandler={handleFeedFetchFromFeedList}
|
entityThread={entityThread}
|
||||||
followTopicHandler={followTopic}
|
feedCount={feedCount}
|
||||||
followers={followers}
|
fetchFeedHandler={handleFeedFetchFromFeedList}
|
||||||
isSampleDataLoading={isSampleDataLoading}
|
followTopicHandler={followTopic}
|
||||||
isentityThreadLoading={isentityThreadLoading}
|
followers={followers}
|
||||||
lineageTabData={{
|
isSampleDataLoading={isSampleDataLoading}
|
||||||
loadNodeHandler,
|
isentityThreadLoading={isentityThreadLoading}
|
||||||
addLineageHandler,
|
lineageTabData={{
|
||||||
removeLineageHandler,
|
loadNodeHandler,
|
||||||
entityLineageHandler,
|
addLineageHandler,
|
||||||
isLineageLoading,
|
removeLineageHandler,
|
||||||
entityLineage,
|
entityLineageHandler,
|
||||||
lineageLeafNodes: leafNodes,
|
isLineageLoading,
|
||||||
isNodeLoading,
|
entityLineage,
|
||||||
}}
|
lineageLeafNodes: leafNodes,
|
||||||
maximumMessageSize={maximumMessageSize}
|
isNodeLoading,
|
||||||
owner={owner as EntityReference}
|
}}
|
||||||
paging={paging}
|
maximumMessageSize={maximumMessageSize}
|
||||||
partitions={partitions}
|
owner={owner as EntityReference}
|
||||||
postFeedHandler={postFeedHandler}
|
paging={paging}
|
||||||
replicationFactor={replicationFactor}
|
partitions={partitions}
|
||||||
retentionSize={retentionSize}
|
postFeedHandler={postFeedHandler}
|
||||||
sampleData={sampleData}
|
replicationFactor={replicationFactor}
|
||||||
schemaText={schemaText}
|
retentionSize={retentionSize}
|
||||||
schemaType={schemaType}
|
sampleData={sampleData}
|
||||||
setActiveTabHandler={activeTabHandler}
|
schemaText={schemaText}
|
||||||
settingsUpdateHandler={settingsUpdateHandler}
|
schemaType={schemaType}
|
||||||
slashedTopicName={slashedTopicName}
|
setActiveTabHandler={activeTabHandler}
|
||||||
tagUpdateHandler={onTagUpdate}
|
settingsUpdateHandler={settingsUpdateHandler}
|
||||||
tier={tier as TagLabel}
|
slashedTopicName={slashedTopicName}
|
||||||
topicDetails={topicDetails}
|
tagUpdateHandler={onTagUpdate}
|
||||||
topicFQN={topicFQN}
|
tier={tier as TagLabel}
|
||||||
topicTags={tags}
|
topicDetails={topicDetails}
|
||||||
unfollowTopicHandler={unfollowTopic}
|
topicFQN={topicFQN}
|
||||||
updateThreadHandler={updateThreadHandler}
|
topicTags={tags}
|
||||||
version={currentVersion}
|
unfollowTopicHandler={unfollowTopic}
|
||||||
versionHandler={versionHandler}
|
updateThreadHandler={updateThreadHandler}
|
||||||
onExtensionUpdate={handleExtentionUpdate}
|
version={currentVersion}
|
||||||
/>
|
versionHandler={versionHandler}
|
||||||
|
onExtensionUpdate={handleExtentionUpdate}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ErrorPlaceHolder>{NO_PERMISSION_TO_VIEW}</ErrorPlaceHolder>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -21,6 +21,59 @@ jest.mock('react-router-dom', () => ({
|
|||||||
useHistory: jest.fn(),
|
useHistory: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../components/PermissionProvider/PermissionProvider', () => ({
|
||||||
|
usePermissionProvider: jest.fn().mockImplementation(() => ({
|
||||||
|
permissions: {},
|
||||||
|
getEntityPermission: jest.fn().mockResolvedValue({
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditCustomFields: true,
|
||||||
|
EditDataProfile: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
EditLineage: true,
|
||||||
|
EditOwner: true,
|
||||||
|
EditQueries: true,
|
||||||
|
EditSampleData: true,
|
||||||
|
EditTags: true,
|
||||||
|
EditTests: true,
|
||||||
|
EditTier: true,
|
||||||
|
ViewAll: true,
|
||||||
|
ViewDataProfile: true,
|
||||||
|
ViewQueries: true,
|
||||||
|
ViewSampleData: true,
|
||||||
|
ViewTests: true,
|
||||||
|
ViewUsage: true,
|
||||||
|
}),
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../utils/PermissionsUtils', () => ({
|
||||||
|
DEFAULT_ENTITY_PERMISSION: {
|
||||||
|
Create: true,
|
||||||
|
Delete: true,
|
||||||
|
EditAll: true,
|
||||||
|
EditCustomFields: true,
|
||||||
|
EditDataProfile: true,
|
||||||
|
EditDescription: true,
|
||||||
|
EditDisplayName: true,
|
||||||
|
EditLineage: true,
|
||||||
|
EditOwner: true,
|
||||||
|
EditQueries: true,
|
||||||
|
EditSampleData: true,
|
||||||
|
EditTags: true,
|
||||||
|
EditTests: true,
|
||||||
|
EditTier: true,
|
||||||
|
ViewAll: true,
|
||||||
|
ViewDataProfile: true,
|
||||||
|
ViewQueries: true,
|
||||||
|
ViewSampleData: true,
|
||||||
|
ViewTests: true,
|
||||||
|
ViewUsage: true,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
describe('Test TopicDetailsPage component', () => {
|
describe('Test TopicDetailsPage component', () => {
|
||||||
it('TopicDetailsPage component should render properly', async () => {
|
it('TopicDetailsPage component should render properly', async () => {
|
||||||
const { container } = render(<TopicDetailsPageComponent />, {
|
const { container } = render(<TopicDetailsPageComponent />, {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user