🚚(frontend) redirect to 401 page when 401 error
Users could still be able to edit a document if the session was expired. It could give the feeling that the document was not saved. If during a mutation request (POST, PUT, DELETE), the server returns a 401 error, the user is redirected to the 401 page.
This commit is contained in:
@@ -31,6 +31,7 @@ and this project adheres to
|
||||
and descendants views #695
|
||||
- 🐛(action) fix notify-argocd workflow #713
|
||||
- 🚨(helm) fix helmfile lint #736
|
||||
- 🚚(frontend) redirect to 401 page when 401 error #759
|
||||
|
||||
|
||||
## [2.4.0] - 2025-03-06
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { expectLoginPage, keyCloakSignIn, mockedDocument } from './common';
|
||||
import {
|
||||
createDoc,
|
||||
expectLoginPage,
|
||||
keyCloakSignIn,
|
||||
mockedDocument,
|
||||
verifyDocName,
|
||||
} from './common';
|
||||
|
||||
test.describe('Doc Routing', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
@@ -50,6 +56,42 @@ test.describe('Doc Routing', () => {
|
||||
timeout: 15000,
|
||||
});
|
||||
});
|
||||
|
||||
test('checks 401 on docs/[id] page', async ({ page, browserName }) => {
|
||||
const [docTitle] = await createDoc(page, 'My new doc', browserName, 1);
|
||||
await verifyDocName(page, docTitle);
|
||||
|
||||
const responsePromise = page.route(
|
||||
/.*\/link-configuration\/$|users\/me\/$/,
|
||||
async (route) => {
|
||||
const request = route.request();
|
||||
|
||||
if (
|
||||
request.method().includes('PUT') ||
|
||||
request.method().includes('GET')
|
||||
) {
|
||||
await route.fulfill({
|
||||
status: 401,
|
||||
json: {
|
||||
detail: 'Log in to access the document',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await route.continue();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
|
||||
const selectVisibility = page.getByLabel('Visibility', { exact: true });
|
||||
await selectVisibility.click();
|
||||
await page.getByLabel('Connected').click();
|
||||
|
||||
await responsePromise;
|
||||
|
||||
await expect(page.getByText('Log in to access the document')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Doc Routing: Not loggued', () => {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { CunninghamProvider } from '@openfun/cunningham-react';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useCunninghamTheme } from '@/cunningham';
|
||||
import { Auth } from '@/features/auth';
|
||||
import { Auth, KEY_AUTH, setAuthUrl } from '@/features/auth';
|
||||
import { useResponsiveStore } from '@/stores/';
|
||||
|
||||
import { ConfigProvider } from './config/';
|
||||
@@ -15,17 +16,19 @@ import { ConfigProvider } from './config/';
|
||||
* - global cache duration - we decided 3 minutes
|
||||
* - It can be overridden to each query
|
||||
*/
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
staleTime: 1000 * 60 * 3,
|
||||
retry: 1,
|
||||
},
|
||||
const defaultOptions = {
|
||||
queries: {
|
||||
staleTime: 1000 * 60 * 3,
|
||||
retry: 1,
|
||||
},
|
||||
};
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions,
|
||||
});
|
||||
|
||||
export function AppProvider({ children }: { children: React.ReactNode }) {
|
||||
const { theme } = useCunninghamTheme();
|
||||
const { replace } = useRouter();
|
||||
|
||||
const initializeResizeListener = useResponsiveStore(
|
||||
(state) => state.initializeResizeListener,
|
||||
@@ -36,6 +39,27 @@ export function AppProvider({ children }: { children: React.ReactNode }) {
|
||||
return cleanupResizeListener;
|
||||
}, [initializeResizeListener]);
|
||||
|
||||
useEffect(() => {
|
||||
queryClient.setDefaultOptions({
|
||||
...defaultOptions,
|
||||
mutations: {
|
||||
onError: (error) => {
|
||||
if (
|
||||
error instanceof Error &&
|
||||
'status' in error &&
|
||||
error.status === 401
|
||||
) {
|
||||
void queryClient.resetQueries({
|
||||
queryKey: [KEY_AUTH],
|
||||
});
|
||||
setAuthUrl();
|
||||
void replace(`/401`);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
}, [replace]);
|
||||
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<CunninghamProvider theme={theme}>
|
||||
|
||||
Reference in New Issue
Block a user