From 2326a0ef8dc73a8409a444bebf10f000a61259c9 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sun, 27 Apr 2025 21:31:05 -0500 Subject: [PATCH] Refine auth mechanics --- src/app/Footer.tsx | 49 +++++++++++++++++----------------- src/auth/index.ts | 7 +++-- src/state/AppState.ts | 1 + src/state/AppStateProvider.tsx | 18 +++++++------ src/utility/cookie.ts | 9 ++++--- 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/src/app/Footer.tsx b/src/app/Footer.tsx index ba9930fc..baebe14e 100644 --- a/src/app/Footer.tsx +++ b/src/app/Footer.tsx @@ -10,14 +10,19 @@ import { usePathname } from 'next/navigation'; import { PATH_ADMIN_PHOTOS, isPathAdmin, isPathSignIn } from './paths'; import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus'; import { signOutAction } from '@/auth/actions'; -import Spinner from '@/components/Spinner'; import AnimateItems from '@/components/AnimateItems'; import { useAppState } from '@/state/AppState'; +import Spinner from '@/components/Spinner'; export default function Footer() { const pathname = usePathname(); - const { userEmail, clearAuthStateAndRedirectIfNecessary } = useAppState(); + const { + userEmail, + userEmailEager, + isCheckingAuth, + clearAuthStateAndRedirectIfNecessary, + } = useAppState(); const showFooter = !isPathSignIn(pathname); @@ -38,31 +43,25 @@ export default function Footer() { 'text-dim min-h-10', )}>
- {isPathAdmin(pathname) + {userEmail || userEmailEager ? <> - {userEmail === undefined && - } - {userEmail && <> -
- {userEmail} -
-
signOutAction() - .then(clearAuthStateAndRedirectIfNecessary)}> - - Sign out - -
- } +
+ {userEmail || userEmailEager} +
+
signOutAction() + .then(clearAuthStateAndRedirectIfNecessary)}> + + Sign out + +
- : <> - - Admin - - {SHOW_REPO_LINK && - } - } + : isCheckingAuth + ? + : SHOW_REPO_LINK + ? + : + Admin + }
diff --git a/src/auth/index.ts b/src/auth/index.ts index 84c1b8be..75b1f855 100644 --- a/src/auth/index.ts +++ b/src/auth/index.ts @@ -13,12 +13,15 @@ const KEY_AUTH_EMAIL = 'authjs.email'; export const storeAuthEmailCookie = (email: string) => storeCookie(KEY_AUTH_EMAIL, email); -export const clearAuthEmailCookie = () => - deleteCookie(KEY_AUTH_EMAIL); +export const getAuthEmailCookie = () => + getCookie(KEY_AUTH_EMAIL); export const hasAuthEmailCookie = () => Boolean(getCookie(KEY_AUTH_EMAIL)); +export const clearAuthEmailCookie = () => + deleteCookie(KEY_AUTH_EMAIL); + export const isCredentialsSignInError = (error: any) => (error.message || `${error}`).includes(KEY_CREDENTIALS_SIGN_IN_ERROR); diff --git a/src/state/AppState.ts b/src/state/AppState.ts index 871ba518..d6b97292 100644 --- a/src/state/AppState.ts +++ b/src/state/AppState.ts @@ -39,6 +39,7 @@ export type AppStateContextType = { setRecipeModalProps?: Dispatch> // AUTH userEmail?: string + userEmailEager?: string setUserEmail?: Dispatch> isUserSignedIn?: boolean isUserSignedInEager?: boolean diff --git a/src/state/AppStateProvider.tsx b/src/state/AppStateProvider.tsx index d47a365d..79023db7 100644 --- a/src/state/AppStateProvider.tsx +++ b/src/state/AppStateProvider.tsx @@ -18,11 +18,11 @@ import { AdminData, getAdminDataAction } from '@/admin/actions'; import { storeAuthEmailCookie, clearAuthEmailCookie, - hasAuthEmailCookie, isCredentialsSignInError, + getAuthEmailCookie, } from '@/auth'; import { useRouter, usePathname } from 'next/navigation'; -import { isPathAdmin, PATH_ROOT } from '@/app/paths'; +import { isPathProtected, PATH_ROOT } from '@/app/paths'; import { INITIAL_UPLOAD_STATE, UploadState } from '@/admin/upload'; import { RecipeProps } from '@/recipe'; import { getCountsForCategoriesCachedAction } from '@/category/actions'; @@ -75,8 +75,8 @@ export default function AppStateProvider({ // AUTH const [userEmail, setUserEmail] = useState(); - const [isUserSignedInEager, setIsUserSignedInEager] = - useState(false); + const [userEmailEager, setUserEmailEager] = + useState(); // ADMIN const [adminUpdateTimes, setAdminUpdateTimes] = useState([]); @@ -121,12 +121,12 @@ export default function AppStateProvider({ isLoading: isCheckingAuth, } = useSWR('getAuth', getAuthAction); useEffect(() => { - setIsUserSignedInEager(hasAuthEmailCookie()); + setUserEmailEager(getAuthEmailCookie()); }, []); useEffect(() => { if (authError) { - setIsUserSignedInEager(false); setUserEmail(undefined); + setUserEmailEager(undefined); if (isCredentialsSignInError(authError)) { clearAuthEmailCookie(); } @@ -135,6 +135,7 @@ export default function AppStateProvider({ } }, [auth, authError]); const isUserSignedIn = Boolean(userEmail); + const isUserSignedInEager = Boolean(userEmailEager); const { data: adminData, @@ -166,9 +167,9 @@ export default function AppStateProvider({ const clearAuthStateAndRedirectIfNecessary = useCallback(() => { setUserEmail(undefined); - setIsUserSignedInEager(false); + setUserEmailEager(undefined); clearAuthEmailCookie(); - if (isPathAdmin(pathname)) { router.push(PATH_ROOT); } + if (isPathProtected(pathname)) { router.push(PATH_ROOT); } }, [router, pathname]); // Returns false when upload is cancelled @@ -216,6 +217,7 @@ export default function AppStateProvider({ // AUTH isCheckingAuth, userEmail, + userEmailEager, setUserEmail, isUserSignedIn, isUserSignedInEager, diff --git a/src/utility/cookie.ts b/src/utility/cookie.ts index 124d2134..bec62ea2 100644 --- a/src/utility/cookie.ts +++ b/src/utility/cookie.ts @@ -1,11 +1,14 @@ +const DEFAULT_PATH = '/'; + export const storeCookie = ( name: string, value: string, - path= '/', + path = DEFAULT_PATH, maxAge = 63158400, sameSite = 'Lax', ) => { if (typeof document !== 'undefined') { + console.log('storeCookie', name, value); document.cookie = `${name}=${value};Path=${path};Max-Age=${maxAge};SameSite=${sameSite}`; } @@ -22,8 +25,8 @@ export const getCookie = (name: string) => { } }; -export const deleteCookie = (name: string) => { +export const deleteCookie = (name: string, path = DEFAULT_PATH) => { if (typeof document !== 'undefined') { - document.cookie = `${name}=;Max-Age=0`; + document.cookie = `${name}=;Path=${path};Max-Age=0`; } };