all repos — caroster @ a9d0686cf07dbe09780984ed5efe5cc12fdaed49

[Octree] Group carpool to your event https://caroster.io

fix: :lipstick: Add human readable error page for invalid confirmation token

#452
Tim Izzo tim@5ika.ch
Fri, 23 Aug 2024 11:52:34 +0200
commit

a9d0686cf07dbe09780984ed5efe5cc12fdaed49

parent

ceda4c783969e70cbca2e5d932085b1d544319dd

M frontend/locales/en.jsonfrontend/locales/en.json

@@ -213,6 +213,8 @@ "signin.password": "Password",

"signin.register": "$t(menu.register)", "signin.title": "Sign in", "signin.withGoogle": "Use a Google account", + "emailConfirmation.invalidMessage": "This confirmation link is no longer valid because it has already been used or has expired.", + "emailConfirmation.toLogin": "Go to login page", "signup.account_already": "Do you already have an account ?", "signup.create": "Create an account", "signup.createForm": "Create an account\ninformation to fullfill",
M frontend/locales/fr.jsonfrontend/locales/fr.json

@@ -213,6 +213,8 @@ "signin.password": "Mot de passe",

"signin.register": "$t(menu.register)", "signin.title": "Se connecter", "signin.withGoogle": "Continuer avec Google", + "emailConfirmation.invalidMessage": "Ce lien de confirmation n'est plus valide car il a déjà été utilisé ou est échue.", + "emailConfirmation.toLogin": "Vers la page de connexion", "signup.account_already": "Vous avez déjà un compte ?", "signup.create": "Créer un compte", "signup.createForm": "Créer un compte\ninformations à remplir",
M frontend/middleware.tsfrontend/middleware.ts

@@ -19,7 +19,8 @@ PUBLIC_FILE.test(req.nextUrl.pathname);

if (isIgnoredPath) return null; - const locale = await getRegisteredUserLanguage(req) || + const locale = + (await getRegisteredUserLanguage(req)) || getCookie('NEXT_LOCALE', req.headers.get('cookie')) || getBrowserPreferredSupportedLanguage(req) || FALLBACK_LANGUAGE;

@@ -34,7 +35,7 @@ );

} } -const getRegisteredUserLanguage = async (req) => { +const getRegisteredUserLanguage = async req => { const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET,

@@ -50,7 +51,7 @@ },

body: JSON.stringify({query: print(ProfileDocument)}), }) .then(async response => { - const {data} = await response.json(); + const {data} = await response.json(); return data?.me?.profile?.lang; }) .catch(console.error);
M frontend/next.config.jsfrontend/next.config.js

@@ -54,8 +54,8 @@ source: '/content-manager/:slug*',

destination: `${STRAPI_URL}/content-manager/:slug*`, }, { - source: '/email-designer/:slug*', - destination: `${STRAPI_URL}/email-designer/:slug*`, + source: '/api/auth/email-confirmation', + destination: '/api/auth/email-confirmation', }, ]; },
A frontend/pages/api/auth/email-confirmation.tsx

@@ -0,0 +1,22 @@

+import type {NextApiRequest, NextApiResponse} from 'next'; + +const {STRAPI_URL = 'http://localhost:1337'} = process.env; + +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + const confirmation = req.query.confirmation; + + try { + const response = await fetch( + `${STRAPI_URL}/api/auth/email-confirmation?confirmation=${confirmation}` + ); + if (response.redirected) return res.redirect(302, response.url); + const result = await response.json(); + if (result.error) throw new Error(result.error.name); + } catch (error) { + console.error(error); + return res.redirect(302, '/auth/email-confirmation'); + } +}
A frontend/pages/auth/email-confirmation.tsx

@@ -0,0 +1,59 @@

+import { + Button, + Card, + CardActions, + CardMedia, + Container, + Typography, +} from '@mui/material'; +import {useTranslation} from 'next-i18next'; +import Layout from '../../layouts/Centered'; +import Logo from '../../components/Logo'; +import NextLink from 'next/link'; +import pageUtils from '../../lib/pageUtils'; +import {getSession} from 'next-auth/react'; + +const EmailConfirmation = () => { + const {t} = useTranslation(); + + return ( + <Layout displayMenu={false}> + <Container maxWidth="xs"> + <Card sx={{pt: 2, width: '100%'}}> + <CardMedia component={Logo} /> + <Typography sx={{p: 2}} variant="body2" align="center"> + {t(`emailConfirmation.invalidMessage`)} + </Typography> + <CardActions + sx={{ + flexDirection: 'column', + justifyContent: 'center', + textAlign: 'center', + mb: 2, + px: 2, + }} + > + <NextLink href="/auth/login" passHref> + <Button size="small">{t('emailConfirmation.toLogin')}</Button> + </NextLink> + </CardActions> + </Card> + </Container> + </Layout> + ); +}; + +export const getServerSideProps = async (context: any) => { + const session = await getSession(context); + + if (session) + return { + redirect: { + destination: '/', + permanent: false, + }, + }; + else return pageUtils.getServerSideProps()(context); +}; + +export default EmailConfirmation;