diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts index 79151d98ca9..8a5d16e7bb1 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Pages/Domains.spec.ts @@ -12,9 +12,11 @@ */ import test, { expect } from '@playwright/test'; import { Operation } from 'fast-json-patch'; +import { get } from 'lodash'; import { SidebarItem } from '../../constant/sidebar'; import { DataProduct } from '../../support/domain/DataProduct'; import { Domain } from '../../support/domain/Domain'; +import { ENTITY_PATH } from '../../support/entity/Entity.interface'; import { UserClass } from '../../support/user/UserClass'; import { performAdminLogin } from '../../utils/admin'; import { getApiContext, redirectToHomePage } from '../../utils/common'; @@ -31,7 +33,7 @@ import { verifyDomain, } from '../../utils/domain'; import { sidebarClick } from '../../utils/sidebar'; -import { performUserLogin } from '../../utils/user'; +import { performUserLogin, visitUserProfilePage } from '../../utils/user'; test.describe('Domains', () => { test.use({ storageState: 'playwright/.auth/admin.json' }); @@ -181,6 +183,7 @@ test.describe('Domains', () => { await checkAssetsCount(page, assets.length); await domain.delete(apiContext); + await assetCleanup(); await afterAction(); }); }); @@ -194,7 +197,7 @@ test.describe('Domains Rbac', () => { const user1 = new UserClass(); test.beforeAll('Setup pre-requests', async ({ browser }) => { - const { apiContext, afterAction } = await performAdminLogin(browser); + const { apiContext, afterAction, page } = await performAdminLogin(browser); await domain1.create(apiContext); await domain2.create(apiContext); await domain3.create(apiContext); @@ -220,6 +223,24 @@ test.describe('Domains Rbac', () => { ]; await user1.patch({ apiContext, patchData: domainPayload }); + + // Add domain role to the user + await visitUserProfilePage(page, user1.responseData.name); + await page + .getByTestId('user-profile') + .locator('.ant-collapse-expand-icon') + .click(); + await page.getByTestId('edit-roles-button').click(); + + await page + .getByTestId('select-user-roles') + .getByLabel('Select roles') + .click(); + await page.getByText('Domain Only Access Role').click(); + await page.click('body'); + const patchRes = page.waitForResponse('/api/v1/users/*'); + await page.getByTestId('inline-save-btn').click(); + await patchRes; await afterAction(); }); @@ -265,6 +286,24 @@ test.describe('Domains Rbac', () => { .locator('span') ).toBeVisible(); + for (const asset of domainAssset2) { + const fqn = encodeURIComponent( + get(asset, 'entityResponseData.fullyQualifiedName', '') + ); + + const assetData = userPage.waitForResponse( + `/api/v1/${asset.endpoint}/name/${fqn}*` + ); + await userPage.goto(`/${ENTITY_PATH[asset.endpoint]}/${fqn}`); + await assetData; + + await expect( + userPage.getByTestId('permission-error-placeholder') + ).toHaveText( + 'You don’t have access, please check with the admin to get permissions' + ); + } + await afterActionUser1(); }); diff --git a/openmetadata-ui/src/main/resources/ui/playwright/utils/user.ts b/openmetadata-ui/src/main/resources/ui/playwright/utils/user.ts index 48ac2374591..5a262ea47d6 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/utils/user.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/utils/user.ts @@ -12,8 +12,10 @@ */ import { expect, Page } from '@playwright/test'; +import { GlobalSettingOptions } from '../constant/settings'; import { UserClass } from '../support/user/UserClass'; import { getAuthContext, getToken, toastNotification } from './common'; +import { settingClick } from './sidebar'; export const performUserLogin = async (browser, user: UserClass) => { const page = await browser.newPage(); @@ -76,6 +78,16 @@ export const deletedUserChecks = async (page: Page) => { ).not.toBeVisible(); }; +export const visitUserProfilePage = async (page: Page, userName: string) => { + await settingClick(page, GlobalSettingOptions.USERS); + const userResponse = page.waitForResponse( + '/api/v1/search/query?q=**&from=0&size=*&index=*' + ); + await page.getByTestId('searchbar').fill(userName); + await userResponse; + await page.getByTestId(userName).click(); +}; + export const softDeleteUserProfilePage = async ( page: Page, userName: string, diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedAppRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedAppRouter.tsx index b7b02f68bce..e11a37fc8ff 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedAppRouter.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/AuthenticatedAppRouter.tsx @@ -23,6 +23,7 @@ import { Operation } from '../../generated/entity/policies/policy'; import AddCustomMetricPage from '../../pages/AddCustomMetricPage/AddCustomMetricPage'; import { CustomizablePage } from '../../pages/CustomizablePage/CustomizablePage'; import DataQualityPage from '../../pages/DataQuality/DataQualityPage'; +import ForbiddenPage from '../../pages/ForbiddenPage/ForbiddenPage'; import { checkPermission, userPermissions } from '../../utils/PermissionsUtils'; import AdminProtectedRoute from './AdminProtectedRoute'; import withSuspenseFallback from './withSuspenseFallback'; @@ -265,6 +266,7 @@ const AuthenticatedAppRouter: FunctionComponent = () => { return ( + diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Suggestions/SuggestionsSlider/SuggestionsSlider.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Suggestions/SuggestionsSlider/SuggestionsSlider.tsx index d7b07573218..c28fee7f077 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Suggestions/SuggestionsSlider/SuggestionsSlider.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Suggestions/SuggestionsSlider/SuggestionsSlider.tsx @@ -30,7 +30,7 @@ const SuggestionsSlider = () => { } = useSuggestionsContext(); return ( -
+
{t('label.suggested-description-plural')} diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts index 6a1cfff8956..e5076e63d69 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts @@ -135,6 +135,7 @@ export const ROUTES = { SAML_CALLBACK: '/saml/callback', SILENT_CALLBACK: '/silent-callback', NOT_FOUND: '/404', + FORBIDDEN: '/403', MY_DATA: '/my-data', TOUR: '/tour', REPORTS: '/reports', diff --git a/openmetadata-ui/src/main/resources/ui/src/hooks/useDomainStore.ts b/openmetadata-ui/src/main/resources/ui/src/hooks/useDomainStore.ts index 16f736c6c16..c2a58b3acd2 100644 --- a/openmetadata-ui/src/main/resources/ui/src/hooks/useDomainStore.ts +++ b/openmetadata-ui/src/main/resources/ui/src/hooks/useDomainStore.ts @@ -42,7 +42,7 @@ export const useDomainStore = create()( userDomainsObj.map((item) => item.fullyQualifiedName) ?? []; let filteredDomains: Domain[] = data; - if (domains.length > 0) { + if (domains.length > 0 && !isAdmin) { filteredDomains = data.filter((domain) => userDomainFqn.includes(domain.fullyQualifiedName) ); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.tsx index e092275b655..fae4dec83cc 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/APICollectionPage/APICollectionPage.tsx @@ -46,6 +46,7 @@ import { getEntityDetailsPath, getVersionPath, INITIAL_PAGING_VALUE, + ROUTES, } from '../../constants/constants'; import { FEED_COUNT_INITIAL_DATA } from '../../constants/entity.constants'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; @@ -53,6 +54,7 @@ import { OperationPermission, ResourceEntity, } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityTabs, @@ -213,6 +215,9 @@ const APICollectionPage: FunctionComponent = () => { setShowDeletedEndpoints(response.deleted ?? false); } catch (err) { // Error + if ((err as AxiosError)?.response?.status === ClientErrors.FORBIDDEN) { + history.replace(ROUTES.FORBIDDEN); + } } finally { setIsAPICollectionLoading(false); } diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/APIEndpointPage/APIEndpointPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/APIEndpointPage/APIEndpointPage.tsx index c1bf0d9ca30..3b424b807e0 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/APIEndpointPage/APIEndpointPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/APIEndpointPage/APIEndpointPage.tsx @@ -22,12 +22,13 @@ import APIEndpointDetails from '../../components/APIEndpoint/APIEndpointDetails/ import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder'; import Loader from '../../components/common/Loader/Loader'; import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface'; -import { getVersionPath } from '../../constants/constants'; +import { getVersionPath, ROUTES } from '../../constants/constants'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; import { OperationPermission, ResourceEntity, } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityType, TabSpecificField } from '../../enums/entity.enum'; import { CreateThread } from '../../generated/api/feed/createThread'; @@ -154,6 +155,10 @@ const APIEndpointPage = () => { } catch (error) { if ((error as AxiosError).response?.status === 404) { setIsError(true); + } else if ( + (error as AxiosError)?.response?.status === ClientErrors.FORBIDDEN + ) { + history.replace(ROUTES.FORBIDDEN); } else { showErrorToast( error as AxiosError, diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx index 5b4f5192231..fd87e53dfb1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx @@ -41,6 +41,7 @@ import { SourceType } from '../../components/SearchedData/SearchedData.interface import { getEntityDetailsPath, getVersionPath, + ROUTES, } from '../../constants/constants'; import { FEED_COUNT_INITIAL_DATA } from '../../constants/entity.constants'; import LineageProvider from '../../context/LineageProvider/LineageProvider'; @@ -49,6 +50,7 @@ import { OperationPermission, ResourceEntity, } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityTabs, @@ -150,6 +152,9 @@ const ContainerPage = () => { } catch (error) { showErrorToast(error as AxiosError); setHasError(true); + if ((error as AxiosError)?.response?.status === ClientErrors.FORBIDDEN) { + history.replace(ROUTES.FORBIDDEN); + } } finally { setIsLoading(false); } diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx index 6b20b0c1666..b4939b2a0e0 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/DashboardDetailsPage/DashboardDetailsPage.component.tsx @@ -22,9 +22,10 @@ import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/Error import Loader from '../../components/common/Loader/Loader'; import DashboardDetails from '../../components/Dashboard/DashboardDetails/DashboardDetails.component'; import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface'; -import { getVersionPath } from '../../constants/constants'; +import { getVersionPath, ROUTES } from '../../constants/constants'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; import { ResourceEntity } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityType, TabSpecificField } from '../../enums/entity.enum'; import { CreateThread } from '../../generated/api/feed/createThread'; @@ -151,6 +152,10 @@ const DashboardDetailsPage = () => { } catch (error) { if ((error as AxiosError).response?.status === 404) { setIsError(true); + } else if ( + (error as AxiosError)?.response?.status === ClientErrors.FORBIDDEN + ) { + history.replace(ROUTES.FORBIDDEN); } else { showErrorToast( error as AxiosError, diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx index b38c503ad8a..59918902437 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/DataModelPage/DataModelPage.component.tsx @@ -24,15 +24,18 @@ import { } from 'react'; import { useTranslation } from 'react-i18next'; +import { useHistory } from 'react-router-dom'; import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder'; import Loader from '../../components/common/Loader/Loader'; import DataModelDetails from '../../components/Dashboard/DataModel/DataModels/DataModelDetails.component'; import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface'; +import { ROUTES } from '../../constants/constants'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; import { OperationPermission, ResourceEntity, } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { TabSpecificField } from '../../enums/entity.enum'; import { CreateThread } from '../../generated/api/feed/createThread'; @@ -61,6 +64,7 @@ import { showErrorToast } from '../../utils/ToastUtils'; const DataModelsPage = () => { const { t } = useTranslation(); + const history = useHistory(); const { currentUser } = useApplicationStore(); const { getEntityPermissionByFqn } = usePermissionProvider(); @@ -133,6 +137,9 @@ const DataModelsPage = () => { } catch (error) { showErrorToast(error as AxiosError); setHasError(true); + if ((error as AxiosError)?.response?.status === ClientErrors.FORBIDDEN) { + history.replace(ROUTES.FORBIDDEN); + } } finally { setIsLoading(false); } diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseDetailsPage/DatabaseDetailsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseDetailsPage/DatabaseDetailsPage.tsx index e3a4e84d1c7..1364c5853c7 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseDetailsPage/DatabaseDetailsPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseDetailsPage/DatabaseDetailsPage.tsx @@ -48,6 +48,7 @@ import { getEntityDetailsPath, getExplorePath, getVersionPath, + ROUTES, } from '../../constants/constants'; import { FEED_COUNT_INITIAL_DATA } from '../../constants/entity.constants'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; @@ -55,6 +56,7 @@ import { OperationPermission, ResourceEntity, } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityTabs, @@ -214,8 +216,13 @@ const DatabaseDetails: FunctionComponent = () => { setServiceType(serviceType); } }) - .catch(() => { + .catch((error) => { // Error + if ( + (error as AxiosError)?.response?.status === ClientErrors.FORBIDDEN + ) { + history.replace(ROUTES.FORBIDDEN); + } }) .finally(() => { setIsLoading(false); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx index 285f6c6d8ad..2428783cb46 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/DatabaseSchemaPage/DatabaseSchemaPage.component.tsx @@ -47,6 +47,7 @@ import { getEntityDetailsPath, getVersionPath, INITIAL_PAGING_VALUE, + ROUTES, } from '../../constants/constants'; import { FEED_COUNT_INITIAL_DATA } from '../../constants/entity.constants'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; @@ -54,6 +55,7 @@ import { OperationPermission, ResourceEntity, } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityTabs, @@ -229,6 +231,9 @@ const DatabaseSchemaPage: FunctionComponent = () => { setShowDeletedTables(response.deleted ?? false); } catch (err) { // Error + if ((err as AxiosError)?.response?.status === ClientErrors.FORBIDDEN) { + history.replace(ROUTES.FORBIDDEN); + } } finally { setIsSchemaDetailsLoading(false); } diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ForbiddenPage/ForbiddenPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ForbiddenPage/ForbiddenPage.tsx new file mode 100644 index 00000000000..b998eea1b4c --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/pages/ForbiddenPage/ForbiddenPage.tsx @@ -0,0 +1,21 @@ +/* + * Copyright 2024 Collate. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder'; +import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; + +const ForbiddenPage = () => { + return ; +}; + +export default ForbiddenPage; diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx index 12f12572dbd..fbddb5f96e9 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/MlModelPage/MlModelPage.component.tsx @@ -22,9 +22,10 @@ import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/Error import Loader from '../../components/common/Loader/Loader'; import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface'; import MlModelDetailComponent from '../../components/MlModel/MlModelDetail/MlModelDetail.component'; -import { getVersionPath } from '../../constants/constants'; +import { getVersionPath, ROUTES } from '../../constants/constants'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; import { ResourceEntity } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityType, TabSpecificField } from '../../enums/entity.enum'; import { CreateThread } from '../../generated/api/feed/createThread'; @@ -107,6 +108,9 @@ const MlModelPage = () => { }); } catch (error) { showErrorToast(error as AxiosError); + if ((error as AxiosError)?.response?.status === ClientErrors.FORBIDDEN) { + history.replace(ROUTES.FORBIDDEN); + } } finally { setIsDetailLoading(false); } diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx index 2ac087a79b8..daee9f7f207 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/PipelineDetails/PipelineDetailsPage.component.tsx @@ -21,9 +21,10 @@ import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/Error import Loader from '../../components/common/Loader/Loader'; import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface'; import PipelineDetails from '../../components/Pipeline/PipelineDetails/PipelineDetails.component'; -import { getVersionPath } from '../../constants/constants'; +import { getVersionPath, ROUTES } from '../../constants/constants'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; import { ResourceEntity } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityType } from '../../enums/entity.enum'; import { Pipeline } from '../../generated/entity/data/pipeline'; @@ -135,6 +136,10 @@ const PipelineDetailsPage = () => { } catch (error) { if ((error as AxiosError).response?.status === 404) { setIsError(true); + } else if ( + (error as AxiosError)?.response?.status === ClientErrors.FORBIDDEN + ) { + history.replace(ROUTES.FORBIDDEN); } else { showErrorToast( error as AxiosError, diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.tsx index 1d54824e8e4..b31f386fa1c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/StoredProcedure/StoredProcedurePage.tsx @@ -40,6 +40,7 @@ import { SourceType } from '../../components/SearchedData/SearchedData.interface import { getEntityDetailsPath, getVersionPath, + ROUTES, } from '../../constants/constants'; import { FEED_COUNT_INITIAL_DATA } from '../../constants/entity.constants'; import LineageProvider from '../../context/LineageProvider/LineageProvider'; @@ -48,6 +49,7 @@ import { OperationPermission, ResourceEntity, } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { CSMode } from '../../enums/codemirror.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityTabs, EntityType } from '../../enums/entity.enum'; @@ -198,7 +200,9 @@ const StoredProcedurePage = () => { id: response.id ?? '', }); } catch (error) { - // Error here + if ((error as AxiosError)?.response?.status === ClientErrors.FORBIDDEN) { + history.replace(ROUTES.FORBIDDEN); + } } finally { setIsLoading(false); } diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx index e1407799cea..b93db372758 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableDetailsPageV1.tsx @@ -48,6 +48,7 @@ import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; import { getEntityDetailsPath, getVersionPath, + ROUTES, } from '../../constants/constants'; import { FEED_COUNT_INITIAL_DATA } from '../../constants/entity.constants'; import { mockDatasetData } from '../../constants/mockTourData.constants'; @@ -58,6 +59,7 @@ import { ResourceEntity, } from '../../context/PermissionProvider/PermissionProvider.interface'; import { useTourProvider } from '../../context/TourProvider/TourProvider'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityTabs, @@ -196,7 +198,9 @@ const TableDetailsPageV1: React.FC = () => { id: details.id, }); } catch (error) { - // Error here + if ((error as AxiosError)?.response?.status === ClientErrors.FORBIDDEN) { + history.replace(ROUTES.FORBIDDEN); + } } finally { setLoading(false); } diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx index cfef96334aa..56d035ac4ed 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TopicDetails/TopicDetailsPage.component.tsx @@ -27,12 +27,13 @@ import ErrorPlaceHolder from '../../components/common/ErrorWithPlaceholder/Error import Loader from '../../components/common/Loader/Loader'; import { QueryVote } from '../../components/Database/TableQueries/TableQueries.interface'; import TopicDetails from '../../components/Topic/TopicDetails/TopicDetails.component'; -import { getVersionPath } from '../../constants/constants'; +import { getVersionPath, ROUTES } from '../../constants/constants'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; import { OperationPermission, ResourceEntity, } from '../../context/PermissionProvider/PermissionProvider.interface'; +import { ClientErrors } from '../../enums/Axios.enum'; import { ERROR_PLACEHOLDER_TYPE } from '../../enums/common.enum'; import { EntityType, TabSpecificField } from '../../enums/entity.enum'; import { CreateThread } from '../../generated/api/feed/createThread'; @@ -152,6 +153,10 @@ const TopicDetailsPage: FunctionComponent = () => { } catch (error) { if ((error as AxiosError).response?.status === 404) { setIsError(true); + } else if ( + (error as AxiosError)?.response?.status === ClientErrors.FORBIDDEN + ) { + history.replace(ROUTES.FORBIDDEN); } else { showErrorToast( error as AxiosError,