Refine auth mechanics
This commit is contained in:
parent
01c8b5d22b
commit
2326a0ef8d
@ -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',
|
||||
)}>
|
||||
<div className="flex gap-x-3 xs:gap-x-4 grow flex-wrap">
|
||||
{isPathAdmin(pathname)
|
||||
{userEmail || userEmailEager
|
||||
? <>
|
||||
{userEmail === undefined &&
|
||||
<Spinner size={14} className="translate-y-[2px]" />}
|
||||
{userEmail && <>
|
||||
<div className={clsx(
|
||||
'truncate max-w-full',
|
||||
)}>
|
||||
{userEmail}
|
||||
</div>
|
||||
<form action={() => signOutAction()
|
||||
.then(clearAuthStateAndRedirectIfNecessary)}>
|
||||
<SubmitButtonWithStatus styleAs="link">
|
||||
Sign out
|
||||
</SubmitButtonWithStatus>
|
||||
</form>
|
||||
</>}
|
||||
<div className="truncate max-w-full">
|
||||
{userEmail || userEmailEager}
|
||||
</div>
|
||||
<form action={() => signOutAction()
|
||||
.then(clearAuthStateAndRedirectIfNecessary)}>
|
||||
<SubmitButtonWithStatus styleAs="link">
|
||||
Sign out
|
||||
</SubmitButtonWithStatus>
|
||||
</form>
|
||||
</>
|
||||
: <>
|
||||
<Link href={PATH_ADMIN_PHOTOS}>
|
||||
Admin
|
||||
</Link>
|
||||
{SHOW_REPO_LINK &&
|
||||
<RepoLink />}
|
||||
</>}
|
||||
: isCheckingAuth
|
||||
? <Spinner size={16} className="translate-y-[2px]" />
|
||||
: SHOW_REPO_LINK
|
||||
? <RepoLink />
|
||||
: <Link href={PATH_ADMIN_PHOTOS}>
|
||||
Admin
|
||||
</Link>}
|
||||
</div>
|
||||
<div className="flex items-center h-10">
|
||||
<ThemeSwitcher />
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@ export type AppStateContextType = {
|
||||
setRecipeModalProps?: Dispatch<SetStateAction<RecipeProps | undefined>>
|
||||
// AUTH
|
||||
userEmail?: string
|
||||
userEmailEager?: string
|
||||
setUserEmail?: Dispatch<SetStateAction<string | undefined>>
|
||||
isUserSignedIn?: boolean
|
||||
isUserSignedInEager?: boolean
|
||||
|
||||
@ -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<string>();
|
||||
const [isUserSignedInEager, setIsUserSignedInEager] =
|
||||
useState(false);
|
||||
const [userEmailEager, setUserEmailEager] =
|
||||
useState<string>();
|
||||
// ADMIN
|
||||
const [adminUpdateTimes, setAdminUpdateTimes] =
|
||||
useState<Date[]>([]);
|
||||
@ -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,
|
||||
|
||||
@ -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`;
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user