fix import export permissions (#17482)

This commit is contained in:
Karan Hotchandani 2024-08-19 15:29:07 +05:30 committed by GitHub
parent c47a46ad78
commit 4c49f098bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 71 additions and 8 deletions

View File

@ -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: (

View File

@ -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(
<GlossaryHeader
isGlossary
permissions={DEFAULT_ENTITY_PERMISSION}
selectedData={{ displayName: 'glossaryTest' } as Glossary}
updateVote={mockOnUpdateVote}
onAddGlossaryTerm={mockOnDelete}
onDelete={mockOnDelete}
onUpdate={mockOnUpdate}
/>
);
expect(screen.queryByTestId('manage-button')).not.toBeInTheDocument();
});
it('should render changeParentHierarchy and style dropdown menu items only for glossaryTerm', async () => {
render(
<GlossaryHeader

View File

@ -74,10 +74,12 @@ export const EntityImport = ({
setUploading(true);
const response = await onImport(entityName, result);
if (response) {
setCsvImportResult(response);
setCsvFileResult(result);
setActiveStep(2);
}
}
} catch (error) {
setCsvImportResult(undefined);
} finally {

View File

@ -17,6 +17,7 @@ import i18next from 'i18next';
import { isEmpty } from 'lodash';
import React from 'react';
import { Link } from 'react-router-dom';
import { ReactComponent as GlossaryTermIcon } from '../assets/svg/book.svg';
import { ReactComponent as IconChart } from '../assets/svg/chart.svg';
import { ReactComponent as IconDashboard } from '../assets/svg/dashboard-grey.svg';
import { ReactComponent as IconApiCollection } from '../assets/svg/ic-api-collection-default.svg';
@ -26,7 +27,6 @@ import { ReactComponent as IconContainer } from '../assets/svg/ic-storage.svg';
import { ReactComponent as IconStoredProcedure } from '../assets/svg/ic-stored-procedure.svg';
import { ReactComponent as IconMlModal } from '../assets/svg/mlmodal.svg';
import { ReactComponent as IconPipeline } from '../assets/svg/pipeline-grey.svg';
import { ReactComponent as IconTable } from '../assets/svg/table-grey.svg';
import { ReactComponent as IconTag } from '../assets/svg/tag-grey.svg';
import { ReactComponent as IconTopic } from '../assets/svg/topic-grey.svg';
import {
@ -124,7 +124,7 @@ export const getGroupLabel = (index: string) => {
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 = (
<Button
block

View File

@ -51,6 +51,7 @@ export const showErrorToast = (
if (isString(error)) {
errorMessage = error.toString();
} else {
const method = error.config?.method?.toUpperCase();
const fallback =
fallbackText && fallbackText.length > 0
? fallbackText
@ -62,7 +63,8 @@ export const showErrorToast = (
if (
error &&
(error.response?.status === ClientErrors.UNAUTHORIZED ||
error.response?.status === ClientErrors.FORBIDDEN) &&
(error.response?.status === ClientErrors.FORBIDDEN &&
method === 'GET')) &&
!errorMessage.includes('principal domain')
) {
return;