From 06357af0dc9462602d30b1a5e9a8e2794ef17fbd Mon Sep 17 00:00:00 2001 From: Duke Manh Date: Thu, 27 Jan 2022 15:49:35 +0000 Subject: [PATCH] Fix signup page crash --- .gitpod.yml | 2 + src/web/src/components/AuthProvider.tsx | 101 +++++++++++++----------- src/web/src/pages/signup.tsx | 4 +- 3 files changed, 58 insertions(+), 49 deletions(-) diff --git a/.gitpod.yml b/.gitpod.yml index 230e83ff39..fd7a60b130 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -9,11 +9,13 @@ tasks: eval $(gp env -e API_URL=$(gp url 3000)) eval $(gp env -e WEB_URL=$(gp url 8000)) eval $(gp env -e API_HOST=$(gp url 8443)) + eval $(gp env -e LOGIN_URL=$(gp url 8081)) eval $(gp env -e SERVICES="status image sso search posts feed-discovery users redis elasticsearch login firebase") sed -r \ -e "s@(.+=)http://localhost:8000(/[^ ]*)*@\1$WEB_URL\2@g" \ -e "s@(.+=)http://localhost:3000(/[^ ]*)*@\1$API_URL\2@g" \ + -e "s@(.+=)http://localhost:8081(/[^ ]*)*@\1$LOGIN_URL\2@g" \ -e "s@(.+=)http://localhost([^:]*)@\1$API_HOST\2@g" \ -e "s@development\.yml@gitpod\.yml@" \ config/env.development > .env diff --git a/src/web/src/components/AuthProvider.tsx b/src/web/src/components/AuthProvider.tsx index 012261a9f5..d7051f786a 100644 --- a/src/web/src/components/AuthProvider.tsx +++ b/src/web/src/components/AuthProvider.tsx @@ -1,4 +1,4 @@ -import { createContext, ReactNode, useState, useEffect } from 'react'; +import { createContext, ReactNode, useState, useEffect, useCallback } from 'react'; import { useLocalStorage } from 'react-use'; import { useRouter } from 'next/router'; import { nanoid } from 'nanoid'; @@ -65,31 +65,67 @@ const AuthProvider = ({ children }: Props) => { console.error('Error parsing token for user', err); cleanup(); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [token]); - - const login = (returnTo?: string) => { - // Create and store some random state that we'll send along with this login request - const loginState = nanoid(); - setAuthState(loginState); - - // Set our return URL - const url = new URL(returnTo || '', webUrl); - window.location.href = `${loginUrl}?redirect_uri=${url.href}&state=${loginState}`; - }; + }, [removeAuthState, removeToken, token]); + + const login = useCallback( + (returnTo?: string) => { + // Create and store some random state that we'll send along with this login request + const loginState = nanoid(); + setAuthState(loginState); + + // Set our return URL + const url = new URL(returnTo || '', webUrl); + window.location.href = `${loginUrl}?redirect_uri=${url.href}&state=${loginState}`; + }, + [setAuthState] + ); - const logout = () => { + const logout = useCallback(() => { // Clear our existing token and state removeToken(); removeAuthState(); // Redirect to logout window.location.href = `${logoutUrl}?redirect_uri=${webUrl}`; - }; + }, [removeAuthState, removeToken]); + + const register = useCallback( + (receivedToken: string) => { + setToken(receivedToken); + }, + [setToken] + ); - const register = (receivedToken: string) => { - setToken(receivedToken); - }; + useEffect(() => { + // Browser-side rendering + try { + // Try to extract access_token and state query params from the URL, which may not be there + const params = new URL(asPath, document.location.href).searchParams; + const accessToken = params.get('access_token'); + const state = params.get('state'); + + if (!token && accessToken) { + // Remove the ?access_token=...&state=... from URL + router.replace(pathname, undefined, { shallow: true }); + + // Make sure we initiated the login flow. When we start the login + // we store some random state in localStorage. When we get redirected + // back with an access token, we should also get our original random state. + // If we do, all is well. If not, don't use this token, since it wasn't + // us who initiated the login. + if (authState !== state) { + throw new Error(`login state '${state}' doesn't match expected state '${authState}'`); + } + + // Store this token in localStorage and clear login state + setToken(accessToken); + removeAuthState(); + } + } catch (err) { + // TODO: should we do more in the error case? If so, what? + console.error('Error parsing access_token from URL', err); + } + }, [asPath, authState, pathname, removeAuthState, router, setToken, token]); // Server-side rendering. if (typeof window === 'undefined') { @@ -100,35 +136,6 @@ const AuthProvider = ({ children }: Props) => { ); } - // Browser-side rendering - try { - // Try to extract access_token and state query params from the URL, which may not be there - const params = new URL(asPath, document.location.href).searchParams; - const accessToken = params.get('access_token'); - const state = params.get('state'); - - if (!token && accessToken) { - // Remove the ?access_token=...&state=... from URL - router.replace(pathname, undefined, { shallow: true }); - - // Make sure we initiated the login flow. When we start the login - // we store some random state in localStorage. When we get redirected - // back with an access token, we should also get our original random state. - // If we do, all is well. If not, don't use this token, since it wasn't - // us who initiated the login. - if (authState !== state) { - throw new Error(`login state '${state}' doesn't match expected state '${authState}'`); - } - - // Store this token in localStorage and clear login state - setToken(accessToken); - removeAuthState(); - } - } catch (err) { - // TODO: should we do more in the error case? If so, what? - console.error('Error parsing access_token from URL', err); - } - return ( {children} diff --git a/src/web/src/pages/signup.tsx b/src/web/src/pages/signup.tsx index 9b29815845..c71c1a25f2 100644 --- a/src/web/src/pages/signup.tsx +++ b/src/web/src/pages/signup.tsx @@ -182,10 +182,10 @@ const SignUpPage = () => { useEffect(() => { if (user) { + setActiveStep(SIGN_UP_STEPS.BASIC_INFO); setLoggedIn(true); - handleNext(); } - }, [handleNext, user]); + }, [user]); const handleSubmit = async (values: SignUpForm, actions: FormikHelpers) => { if (activeStep < 4) {