From 87a49190eb4ebce9aea0a7248155ccd2681ac364 Mon Sep 17 00:00:00 2001 From: Michael Fatemi Date: Wed, 11 Aug 2021 17:29:39 -0400 Subject: [PATCH] add login continue --- src/components/App.tsx | 23 +++++++++++++-- .../Authentication/AuthenticationContext.ts | 3 ++ .../Authentication/AuthenticationWrapper.tsx | 29 +++++++++---------- src/components/loginContinueUrl.ts | 17 +++++++++++ 4 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 src/components/loginContinueUrl.ts diff --git a/src/components/App.tsx b/src/components/App.tsx index 6de316d..52b4e8c 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,8 +1,13 @@ -import { CSSProperties, lazy, Suspense } from 'react'; +import { CSSProperties, lazy, Suspense, useContext, useEffect } from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; import NotificationsProvider from '../state/Notifications/NotificationsProvider'; +import AuthenticationContext from './Authentication/AuthenticationContext'; import Header from './Header/Header'; -import { useMe } from './hooks'; +import { + hasLoginContinueURL, + popLoginContinueURL, + setLoginContinueURL, +} from './loginContinueUrl'; import WheelShare from './WheelShare'; import WheelShareLoggedOut from './WheelShareLoggedOut'; @@ -22,7 +27,19 @@ const style: CSSProperties = { }; export default function App() { - const user = useMe(); + const { user, loaded } = useContext(AuthenticationContext); + + useEffect(() => { + if (!loaded) return; + + if (!user) { + if (!window.location.pathname.startsWith('/auth/')) { + setLoginContinueURL(window.location.href); + } + } else if (hasLoginContinueURL()) { + window.location.href = popLoginContinueURL()!; + } + }, [loaded, user]); return (
diff --git a/src/components/Authentication/AuthenticationContext.ts b/src/components/Authentication/AuthenticationContext.ts index bac9ad6..cf62a1f 100644 --- a/src/components/Authentication/AuthenticationContext.ts +++ b/src/components/Authentication/AuthenticationContext.ts @@ -13,12 +13,15 @@ export type AuthenticationContextProps = { * Function that can be used to trigger an auth state refresh. */ refresh: () => void; + + loaded: boolean; }; const AuthenticationContext = createContext({ user: null, refresh: () => console.warn('calling refresh on default AuthenticationContext'), + loaded: false, }); export default AuthenticationContext; diff --git a/src/components/Authentication/AuthenticationWrapper.tsx b/src/components/Authentication/AuthenticationWrapper.tsx index e4cbdd2..a550550 100644 --- a/src/components/Authentication/AuthenticationWrapper.tsx +++ b/src/components/Authentication/AuthenticationWrapper.tsx @@ -7,32 +7,29 @@ export default function AuthenticationWrapper({ }: { children: React.ReactNode; }) { - // Prevent race conditions const [user, setUser] = useState(null); + const [loaded, setLoaded] = useState(false); const refresh = useCallback(() => { - const none = () => setUser(null); - const sessionToken = localStorage.getItem('session_token'); + async function refresh_() { + const sessionToken = localStorage.getItem('session_token'); - if (sessionToken) { - getMe() - .then((user) => { - if ('status' in user && user.status === 'error') { - setUser(null); - } else { - setUser(user); - } - }) - .catch(() => none()); - } else { - none(); + if (sessionToken) { + const user = await getMe(); + if (!('status' in user && user.status === 'error')) { + setUser(user); + return; + } + } + setUser(null); } + refresh_().finally(() => setLoaded(true)); }, []); useEffect(refresh, [refresh]); return ( - + {children} ); diff --git a/src/components/loginContinueUrl.ts b/src/components/loginContinueUrl.ts new file mode 100644 index 0000000..8f3d49f --- /dev/null +++ b/src/components/loginContinueUrl.ts @@ -0,0 +1,17 @@ +const KEY = 'ws_login_continue_url'; + +export function setLoginContinueURL(url: string) { + localStorage.setItem(KEY, url); +} + +export function hasLoginContinueURL() { + return localStorage.getItem(KEY) !== null; +} + +export function popLoginContinueURL() { + const value = localStorage.getItem(KEY); + + localStorage.removeItem(KEY); + + return value; +}