mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-29 19:35:56 +00:00
* fix(#10190): entities permissions cache issue * chore: update handler name * fix: component name typo * fix: minor issue * add unit test * chore: revert the reset entities permissions changes * chore: reset everything for permissions on logout * test: add unit test * update unit test
This commit is contained in:
parent
be7e6254d9
commit
12a846e35b
@ -13,7 +13,7 @@
|
||||
|
||||
import ApplicationConfigProvider from 'components/ApplicationConfigProvider/ApplicationConfigProvider';
|
||||
import { AuthProvider } from 'components/authentication/auth-provider/AuthProvider';
|
||||
import ErrorBoundry from 'components/ErrorBoundry/ErrorBoundry';
|
||||
import ErrorBoundary from 'components/ErrorBoundary/ErrorBoundary';
|
||||
import GlobalSearchProvider from 'components/GlobalSearchProvider/GlobalSearchProvider';
|
||||
import PermissionProvider from 'components/PermissionProvider/PermissionProvider';
|
||||
import AppRouter from 'components/router/AppRouter';
|
||||
@ -34,7 +34,7 @@ const App: FunctionComponent = () => {
|
||||
<div className="content-wrapper" data-testid="content-wrapper">
|
||||
<Router>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<ErrorBoundry>
|
||||
<ErrorBoundary>
|
||||
<ApplicationConfigProvider>
|
||||
<AuthProvider childComponentType={AppRouter}>
|
||||
<HelmetProvider>
|
||||
@ -50,7 +50,7 @@ const App: FunctionComponent = () => {
|
||||
</HelmetProvider>
|
||||
</AuthProvider>
|
||||
</ApplicationConfigProvider>
|
||||
</ErrorBoundry>
|
||||
</ErrorBoundary>
|
||||
</I18nextProvider>
|
||||
</Router>
|
||||
<ToastContainer {...TOAST_OPTIONS} newestOnTop />
|
||||
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { ErrorBoundary as ErrorBoundaryWrapper } from 'react-error-boundary';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { ROUTES } from '../../constants/constants';
|
||||
import ErrorFallback from './ErrorFallback';
|
||||
@ -21,7 +21,7 @@ interface Props {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const ErrorBoundry: React.FC<Props> = ({ children }) => {
|
||||
const ErrorBoundary: React.FC<Props> = ({ children }) => {
|
||||
const history = useHistory();
|
||||
|
||||
const onErrorReset = () => {
|
||||
@ -29,10 +29,12 @@ const ErrorBoundry: React.FC<Props> = ({ children }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback} onReset={onErrorReset}>
|
||||
<ErrorBoundaryWrapper
|
||||
FallbackComponent={ErrorFallback}
|
||||
onReset={onErrorReset}>
|
||||
{children}
|
||||
</ErrorBoundary>
|
||||
</ErrorBoundaryWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default ErrorBoundry;
|
||||
export default ErrorBoundary;
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
import { CookieStorage } from 'cookie-storage';
|
||||
import { isEmpty, isUndefined } from 'lodash';
|
||||
import { observer } from 'mobx-react';
|
||||
import React, {
|
||||
createContext,
|
||||
@ -166,10 +167,19 @@ const PermissionProvider: FC<PermissionProviderProps> = ({ children }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const resetPermissions = () => {
|
||||
setEntitiesPermission({} as EntityPermissionMap);
|
||||
setPermissions({} as UIPermission);
|
||||
setResourcesPermission({} as UIPermission);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isProtectedRoute(location.pathname)) {
|
||||
fetchLoggedInUserPermissions();
|
||||
}
|
||||
if (isUndefined(currentUser) || isEmpty(currentUser)) {
|
||||
resetPermissions();
|
||||
}
|
||||
}, [currentUser]);
|
||||
|
||||
return (
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2023 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 {
|
||||
act,
|
||||
render,
|
||||
screen,
|
||||
waitForElementToBeRemoved,
|
||||
} from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import AppState from 'AppState';
|
||||
import React from 'react';
|
||||
import AuthProvider, { useAuthContext } from './AuthProvider';
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
useHistory: jest.fn().mockReturnValue({ push: jest.fn(), listen: jest.fn() }),
|
||||
useLocation: jest.fn().mockReturnValue({ pathname: 'pathname' }),
|
||||
}));
|
||||
|
||||
jest.mock('rest/miscAPI', () => ({
|
||||
fetchAuthenticationConfig: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve()),
|
||||
fetchAuthorizerConfig: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
jest.mock('rest/userAPI', () => ({
|
||||
getLoggedInUser: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
updateUser: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
describe('Test auth provider', () => {
|
||||
it('Logout handler should call the "updateUserDetails" method', async () => {
|
||||
const mockUpdateUserDetails = jest.spyOn(AppState, 'updateUserDetails');
|
||||
const ConsumerComponent = () => {
|
||||
const { onLogoutHandler } = useAuthContext();
|
||||
|
||||
return (
|
||||
<button data-testid="logout-button" onClick={onLogoutHandler}>
|
||||
Logout
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
render(
|
||||
<AuthProvider childComponentType={ConsumerComponent}>
|
||||
<ConsumerComponent />
|
||||
</AuthProvider>
|
||||
);
|
||||
|
||||
await waitForElementToBeRemoved(() => screen.getByTestId('loader'));
|
||||
|
||||
const logoutButton = screen.getByTestId('logout-button');
|
||||
|
||||
expect(logoutButton).toBeInTheDocument();
|
||||
|
||||
await act(async () => {
|
||||
userEvent.click(logoutButton);
|
||||
});
|
||||
|
||||
expect(mockUpdateUserDetails).toHaveBeenCalled();
|
||||
expect(mockUpdateUserDetails).toHaveBeenCalledWith({});
|
||||
});
|
||||
});
|
@ -16,6 +16,7 @@ import { Auth0Provider } from '@auth0/auth0-react';
|
||||
import { Configuration } from '@azure/msal-browser';
|
||||
import { MsalProvider } from '@azure/msal-react';
|
||||
import { LoginCallback } from '@okta/okta-react';
|
||||
import appState from 'AppState';
|
||||
import { AxiosError } from 'axios';
|
||||
import { CookieStorage } from 'cookie-storage';
|
||||
import { AuthorizerConfiguration } from 'generated/configuration/authorizerConfiguration';
|
||||
@ -36,7 +37,6 @@ import { useHistory, useLocation } from 'react-router-dom';
|
||||
import axiosClient from 'rest/index';
|
||||
import { fetchAuthenticationConfig, fetchAuthorizerConfig } from 'rest/miscAPI';
|
||||
import { getLoggedInUser, updateUser } from 'rest/userAPI';
|
||||
import appState from '../../../AppState';
|
||||
import { NO_AUTH } from '../../../constants/auth.constants';
|
||||
import { REDIRECT_PATHNAME, ROUTES } from '../../../constants/constants';
|
||||
import { ClientErrors } from '../../../enums/axios.enum';
|
||||
@ -133,10 +133,13 @@ export const AuthProvider = ({
|
||||
clearTimeout(timeoutId);
|
||||
authenticatorRef.current?.invokeLogout();
|
||||
|
||||
// reset the user details on logout
|
||||
appState.updateUserDetails({} as User);
|
||||
|
||||
// remove analytics session on logout
|
||||
removeSession();
|
||||
setLoading(false);
|
||||
}, [timeoutId]);
|
||||
}, [timeoutId, appState]);
|
||||
|
||||
const onRenewIdTokenHandler = () => {
|
||||
return authenticatorRef.current?.renewIdToken();
|
||||
|
Loading…
x
Reference in New Issue
Block a user