Skip to content

Commit c2ad91b

Browse files
authored
fix: Redirect to '?redirect' query parameter after successful login (#307)
Fixes #304 Unblocks #298 After logging in, the login flow should redirect to a whatever path is specified by the `?redirect` query parameter. This is important for cases like #298 - where we need to set `?redirect=%2Fcli_auth`, but also really any case where the user is linked and might have to go back to the login screen. The fix is simple - just check if the `redirect` query parameter is set, and if it is, use that as the path to redirect to on success. Also adds a test case - we had one checking that we redirect to the default (root `/`) url, but not one of the `?redirect` param
1 parent d436993 commit c2ad91b

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

site/components/SignIn/SignInForm.test.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,29 @@ describe("SignInForm", () => {
5555
act(() => elem.click())
5656

5757
// Then
58-
// Should redirect because login was successfully
58+
// Should redirect because login was successful
5959
await waitFor(() => expect(singletonRouter).toMatchObject({ asPath: "/" }))
6060
})
61+
62+
it("respects ?redirect query parameter when complete", async () => {
63+
// Given
64+
const loginHandler = (_email: string, _password: string) => Promise.resolve()
65+
// Set a path to redirect to after login is successful
66+
mockRouter.setCurrentUrl("/login?redirect=%2Fsome%2Fother%2Fpath")
67+
68+
// When
69+
// Render the component
70+
const { container } = render(<SignInForm loginHandler={loginHandler} />)
71+
// Set user / password
72+
const inputs = container.querySelectorAll("input")
73+
fireEvent.change(inputs[0], { target: { value: "test@coder.com" } })
74+
fireEvent.change(inputs[1], { target: { value: "password" } })
75+
// Click sign-in
76+
const elem = await screen.findByText("Sign In")
77+
act(() => elem.click())
78+
79+
// Then
80+
// Should redirect to /some/other/path because ?redirect was specified and login was successful
81+
await waitFor(() => expect(singletonRouter).toMatchObject({ asPath: "/some/other/path" }))
82+
})
6183
})

site/components/SignIn/SignInForm.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { makeStyles } from "@material-ui/core/styles"
22
import { FormikContextType, useFormik } from "formik"
3-
import { useRouter } from "next/router"
3+
import { NextRouter, useRouter } from "next/router"
44
import React from "react"
55
import { useSWRConfig } from "swr"
66
import * as Yup from "yup"
@@ -9,6 +9,7 @@ import { Welcome } from "./Welcome"
99
import { FormTextField } from "../Form"
1010
import * as API from "./../../api"
1111
import { LoadingButton } from "./../Button"
12+
import { firstOrItem } from "../../util/array"
1213

1314
/**
1415
* BuiltInAuthFormValues describes a form using built-in (email/password)
@@ -61,7 +62,9 @@ export const SignInForm: React.FC<SignInProps> = ({
6162
await loginHandler(email, password)
6263
// Tell SWR to invalidate the cache for the user endpoint
6364
await mutate("/api/v2/users/me")
64-
await router.push("/")
65+
66+
const redirect = getRedirectFromRouter(router)
67+
await router.push(redirect)
6568
} catch (err) {
6669
helpers.setFieldError("password", "The username or password is incorrect.")
6770
}
@@ -117,3 +120,12 @@ export const SignInForm: React.FC<SignInProps> = ({
117120
</>
118121
)
119122
}
123+
124+
const getRedirectFromRouter = (router: NextRouter) => {
125+
const defaultRedirect = "/"
126+
if (router.query?.redirect) {
127+
return firstOrItem(router.query.redirect, defaultRedirect)
128+
} else {
129+
return defaultRedirect
130+
}
131+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy