From 4c49f098bd702b0183d652d81403af8c92d1bf18 Mon Sep 17 00:00:00 2001 From: Karan Hotchandani <33024356+karanh37@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:29:07 +0530 Subject: [PATCH] fix import export permissions (#17482) --- .../GlossaryHeader.component.tsx | 17 ++++++++- .../GlossaryHeader/GlossaryHeader.test.tsx | 37 +++++++++++++++++++ .../EntityImport/EntityImport.component.tsx | 8 ++-- .../resources/ui/src/utils/SearchUtils.tsx | 13 +++++-- .../main/resources/ui/src/utils/ToastUtils.ts | 4 +- 5 files changed, 71 insertions(+), 8 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.component.tsx index 641089879f8..4c96562d960 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.component.tsx @@ -120,6 +120,21 @@ const GlossaryHeader = ({ [globalPermissions] ); + const importExportPermissions = useMemo( + () => + checkPermission( + Operation.All, + ResourceEntity.GLOSSARY_TERM, + globalPermissions + ) || + checkPermission( + Operation.EditAll, + ResourceEntity.GLOSSARY_TERM, + globalPermissions + ), + [globalPermissions] + ); + // To fetch the latest glossary data // necessary to handle back click functionality to work properly in version page const fetchCurrentGlossaryInfo = async () => { @@ -298,7 +313,7 @@ const GlossaryHeader = ({ }, [selectedData]); const manageButtonContent: ItemType[] = [ - ...(isGlossary + ...(isGlossary && importExportPermissions ? ([ { label: ( diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.test.tsx index 00c123fe015..f3b7a3a683f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Glossary/GlossaryHeader/GlossaryHeader.test.tsx @@ -23,6 +23,25 @@ import { DEFAULT_ENTITY_PERMISSION } from '../../../utils/PermissionsUtils'; import { QueryVoteType } from '../../Database/TableQueries/TableQueries.interface'; import GlossaryHeader from './GlossaryHeader.component'; +const glossaryTermPermission = { + All: true, + Create: true, + Delete: true, + ViewAll: true, + EditAll: true, + EditDescription: true, + EditDisplayName: true, + EditCustomFields: true, +}; + +jest.mock('../../../context/PermissionProvider/PermissionProvider', () => ({ + usePermissionProvider: jest.fn().mockImplementation(() => ({ + permissions: { + glossaryTerm: glossaryTermPermission, + }, + })), +})); + jest.mock('react-router-dom', () => ({ useHistory: jest.fn(), useParams: jest.fn().mockReturnValue({ @@ -195,6 +214,24 @@ describe('GlossaryHeader component', () => { expect(screen.queryByText('label.style')).not.toBeInTheDocument(); }); + it('should not render import and export dropdown menu items if no permission', async () => { + glossaryTermPermission.All = false; + glossaryTermPermission.EditAll = false; + render( + + ); + + expect(screen.queryByTestId('manage-button')).not.toBeInTheDocument(); + }); + it('should render changeParentHierarchy and style dropdown menu items only for glossaryTerm', async () => { render( { break; case SearchIndex.GLOSSARY_TERM: label = i18next.t('label.glossary-term-plural'); - GroupIcon = IconTable; + GroupIcon = GlossaryTermIcon; break; case SearchIndex.TAG: @@ -219,11 +219,18 @@ export const getSuggestionElement = ( FqnPart.Service, ])}-${name}`.replaceAll(`"`, ''); - const displayText = + let displayText = database && schema ? `${database}${FQN_SEPARATOR_CHAR}${schema}${FQN_SEPARATOR_CHAR}${name}` : searchClassBase.getEntityName(entitySource); + if (index === SearchIndex.GLOSSARY_TERM) { + // Show Fqn for Glossary Term. Adding this to avoid confusion for nested terms + displayText = + entitySource.fullyQualifiedName ?? + searchClassBase.getEntityName(entitySource); + } + const retn = (