diff --git a/.changeset/quiet-wasps-draw.md b/.changeset/quiet-wasps-draw.md new file mode 100644 index 00000000000..07b3edfbf2b --- /dev/null +++ b/.changeset/quiet-wasps-draw.md @@ -0,0 +1,6 @@ +--- +'@keystone-6/auth': patch +--- + +When redirecting to the homepage, the `from` query parameter unnecessarily displayed `=/`. +This patch fixes that so it is only provided as a query parameter when needed. diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index c9bd28cc364..f2c9b4b364f 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -114,7 +114,8 @@ export function createAuth({ } if (!session && pathname !== '/signin') { - return { kind: 'redirect', to: `/signin?from=${encodeURIComponent(req!.url!)}` }; + let to = pathname === '/' ? '/signin' : `/signin?from=${encodeURIComponent(req!.url!)}`; + return { kind: 'redirect', to }; } }; diff --git a/packages/auth/src/lib/useFromRedirect.ts b/packages/auth/src/lib/useFromRedirect.ts new file mode 100644 index 00000000000..2828d52dbd8 --- /dev/null +++ b/packages/auth/src/lib/useFromRedirect.ts @@ -0,0 +1,15 @@ +import { useMemo } from 'react'; +import { useRouter } from '@keystone-6/core/admin-ui/router'; + +export const useRedirect = () => { + const router = useRouter(); + const redirect = useMemo( + () => + !Array.isArray(router.query.from) && router.query.from?.startsWith('/') + ? router.query.from + : '/', + [router] + ); + + return redirect; +}; diff --git a/packages/auth/src/pages/InitPage.tsx b/packages/auth/src/pages/InitPage.tsx index f26d6f0aaaf..a160f1ed98c 100644 --- a/packages/auth/src/pages/InitPage.tsx +++ b/packages/auth/src/pages/InitPage.tsx @@ -24,6 +24,7 @@ import { LoadingDots } from '@keystone-ui/loading'; import { guessEmailFromValue, validEmail } from '../lib/emailHeuristics'; import { IconTwitter, IconGithub } from '../components/Icons'; import { SigninContainer } from '../components/SigninContainer'; +import { useRedirect } from '../lib/useFromRedirect'; const signupURL = 'https://signup.keystonejs.cloud/api/newsletter-signup'; @@ -33,6 +34,8 @@ const Welcome = ({ value }: { value: any }) => { const [error, setError] = useState(null); const [loading, setLoading] = useState(false); const router = useRouter(); + const redirect = useRedirect(); + const onSubmit = (event: React.FormEvent) => { event.preventDefault(); setError(null); @@ -65,7 +68,7 @@ const Welcome = ({ value }: { value: any }) => { setLoading(false); }); } else { - router.push((router.query.from as string | undefined) || '/'); + router.push(redirect); } }) .catch(err => { @@ -80,7 +83,7 @@ const Welcome = ({ value }: { value: any }) => { return; } } - return router.push((router.query.from as string | undefined) || '/'); + return router.push(redirect); }; return ( @@ -195,6 +198,7 @@ const InitPage = ({ fieldPaths, listKey, enableWelcome }: InitPageProps) => { }`); const reinitContext = useReinitContext(); const router = useRouter(); + const redirect = useRedirect(); const rawKeystone = useRawKeystone(); useEffect(() => { @@ -210,10 +214,10 @@ const InitPage = ({ fieldPaths, listKey, enableWelcome }: InitPageProps) => { setMode('welcome'); } else { // otherwise we route them through to the admin dashboard - router.push((router.query.from as string | undefined) || '/'); + router.push(redirect); } } - }, [rawKeystone.authenticatedItem, enableWelcome, router]); + }, [rawKeystone.authenticatedItem, enableWelcome, router, redirect]); if (rawKeystone.authenticatedItem.state === 'authenticated' && !enableWelcome) { return ( diff --git a/packages/auth/src/pages/SigninPage.tsx b/packages/auth/src/pages/SigninPage.tsx index c1287352745..da6cd68c5c2 100644 --- a/packages/auth/src/pages/SigninPage.tsx +++ b/packages/auth/src/pages/SigninPage.tsx @@ -1,7 +1,7 @@ /** @jsxRuntime classic */ /** @jsx jsx */ -import { useState, Fragment, FormEvent, useRef, useEffect } from 'react'; +import { useState, Fragment, FormEvent, useRef, useEffect, useMemo } from 'react'; import { jsx, H1, Stack, VisuallyHidden, Center } from '@keystone-ui/core'; import { Button } from '@keystone-ui/button'; @@ -13,6 +13,7 @@ import { useRawKeystone, useReinitContext } from '@keystone-6/core/admin-ui/cont import { useRouter } from '@keystone-6/core/admin-ui/router'; import { LoadingDots } from '@keystone-ui/loading'; import { SigninContainer } from '../components/SigninContainer'; +import { useRedirect } from '../lib/useFromRedirect'; type SigninPageProps = { identityField: string; @@ -58,12 +59,14 @@ export const SigninPage = ({ const reinitContext = useReinitContext(); const router = useRouter(); const rawKeystone = useRawKeystone(); + const redirect = useRedirect(); + // This useEffect specifically handles ending up on the signin page from a SPA navigation useEffect(() => { if (rawKeystone.authenticatedItem.state === 'authenticated') { - router.push((router.query.from as string | undefined) || '/'); + router.push(redirect); } - }, [rawKeystone.authenticatedItem, router]); + }, [rawKeystone.authenticatedItem, router, redirect]); if (rawKeystone.authenticatedItem.state === 'authenticated') { return ( @@ -96,7 +99,7 @@ export const SigninPage = ({ return; } reinitContext(); - router.push((router.query.from as string | undefined) || '/'); + router.push(redirect); } }} >