💄(frontend) add page 401
Add a 401 page when user try to access a doc that need authentication.
This commit is contained in:
@@ -8,6 +8,10 @@ and this project adheres to
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- 💄(frontend) add error pages #643
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
- 🛂(frontend) Restore version visibility #629
|
- 🛂(frontend) Restore version visibility #629
|
||||||
|
|||||||
@@ -100,7 +100,9 @@ test.describe('Doc Visibility: Restricted', () => {
|
|||||||
|
|
||||||
await page.goto(urlDoc);
|
await page.goto(urlDoc);
|
||||||
|
|
||||||
await expect(page.getByRole('textbox', { name: 'password' })).toBeVisible();
|
await expect(
|
||||||
|
page.getByText('Log in to access the document.'),
|
||||||
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('A doc is not accessible when authentified but not member.', async ({
|
test('A doc is not accessible when authentified but not member.', async ({
|
||||||
@@ -379,7 +381,10 @@ test.describe('Doc Visibility: Authenticated', () => {
|
|||||||
await page.goto(urlDoc);
|
await page.goto(urlDoc);
|
||||||
|
|
||||||
await expect(page.locator('h2').getByText(docTitle)).toBeHidden();
|
await expect(page.locator('h2').getByText(docTitle)).toBeHidden();
|
||||||
await expect(page.getByRole('textbox', { name: 'password' })).toBeVisible();
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('Log in to access the document.'),
|
||||||
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('It checks a authenticated doc in read only mode', async ({
|
test('It checks a authenticated doc in read only mode', async ({
|
||||||
|
|||||||
BIN
src/frontend/apps/impress/src/assets/icons/icon-401.png
Normal file
BIN
src/frontend/apps/impress/src/assets/icons/icon-401.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 258 KiB |
@@ -14,7 +14,11 @@ export const ButtonLogin = () => {
|
|||||||
|
|
||||||
if (!authenticated) {
|
if (!authenticated) {
|
||||||
return (
|
return (
|
||||||
<Button onClick={gotoLogin} color="primary-text" aria-label={t('Login')}>
|
<Button
|
||||||
|
onClick={() => gotoLogin()}
|
||||||
|
color="primary-text"
|
||||||
|
aria-label={t('Login')}
|
||||||
|
>
|
||||||
{t('Login')}
|
{t('Login')}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
@@ -32,7 +36,7 @@ export const ProConnectButton = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<BoxButton
|
<BoxButton
|
||||||
onClick={gotoLogin}
|
onClick={() => gotoLogin()}
|
||||||
aria-label={t('Proconnect Login')}
|
aria-label={t('Proconnect Login')}
|
||||||
$css={css`
|
$css={css`
|
||||||
background-color: var(--c--theme--colors--primary-text);
|
background-color: var(--c--theme--colors--primary-text);
|
||||||
|
|||||||
@@ -16,8 +16,11 @@ export const setAuthUrl = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const gotoLogin = () => {
|
export const gotoLogin = (withRedirect = true) => {
|
||||||
setAuthUrl();
|
if (withRedirect) {
|
||||||
|
setAuthUrl();
|
||||||
|
}
|
||||||
|
|
||||||
window.location.replace(LOGIN_URL);
|
window.location.replace(LOGIN_URL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export default function HomeBanner() {
|
|||||||
<ProConnectButton />
|
<ProConnectButton />
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
onClick={gotoLogin}
|
onClick={() => gotoLogin()}
|
||||||
icon={
|
icon={
|
||||||
<Text $isMaterialIcon $color="white">
|
<Text $isMaterialIcon $color="white">
|
||||||
bolt
|
bolt
|
||||||
|
|||||||
57
src/frontend/apps/impress/src/pages/401.tsx
Normal file
57
src/frontend/apps/impress/src/pages/401.tsx
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import { Button } from '@openfun/cunningham-react';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { ReactElement, useEffect } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import img401 from '@/assets/icons/icon-401.png';
|
||||||
|
import { Box, Text } from '@/components';
|
||||||
|
import { gotoLogin, useAuth } from '@/features/auth';
|
||||||
|
import { PageLayout } from '@/layouts';
|
||||||
|
import { NextPageWithLayout } from '@/types/next';
|
||||||
|
|
||||||
|
const Page: NextPageWithLayout = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { authenticated } = useAuth();
|
||||||
|
const { replace } = useRouter();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (authenticated) {
|
||||||
|
void replace(`/`);
|
||||||
|
}
|
||||||
|
}, [authenticated, replace]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
$align="center"
|
||||||
|
$margin="auto"
|
||||||
|
$gap="1rem"
|
||||||
|
$padding={{ bottom: '2rem' }}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={img401}
|
||||||
|
alt={t('Image 401')}
|
||||||
|
style={{
|
||||||
|
maxWidth: '100%',
|
||||||
|
height: 'auto',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Box $align="center" $gap="0.8rem">
|
||||||
|
<Text as="p" $textAlign="center" $maxWidth="350px" $theme="primary">
|
||||||
|
{t('Log in to access the document.')}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Button onClick={() => gotoLogin(false)} aria-label={t('Login')}>
|
||||||
|
{t('Login')}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Page.getLayout = function getLayout(page: ReactElement) {
|
||||||
|
return <PageLayout withFooter={false}>{page}</PageLayout>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Page;
|
||||||
@@ -5,7 +5,7 @@ import { useRouter } from 'next/router';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { Box, Text, TextErrors } from '@/components';
|
import { Box, Text, TextErrors } from '@/components';
|
||||||
import { gotoLogin } from '@/features/auth';
|
import { setAuthUrl } from '@/features/auth';
|
||||||
import { DocEditor } from '@/features/docs/doc-editor';
|
import { DocEditor } from '@/features/docs/doc-editor';
|
||||||
import {
|
import {
|
||||||
Doc,
|
Doc,
|
||||||
@@ -110,7 +110,8 @@ const DocPage = ({ id }: DocProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error.status === 401) {
|
if (error.status === 401) {
|
||||||
gotoLogin();
|
setAuthUrl();
|
||||||
|
void replace(`/401`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user