This commit is contained in:
giancarlo
2024-03-24 02:23:22 +08:00
parent 648d77b430
commit bce3479368
589 changed files with 37067 additions and 9596 deletions

View File

@@ -0,0 +1,96 @@
'use client';
import { useEffect } from 'react';
import { usePathname, useRouter } from 'next/navigation';
import { isBrowser } from '@supabase/ssr';
import { useSupabase } from '../hooks/use-supabase';
import {
useRevalidateUserSession,
useUserSession,
} from '../hooks/use-user-session';
function AuthRedirectListener({
children,
appHomePath,
}: React.PropsWithChildren<{
appHomePath: string;
}>) {
const client = useSupabase();
const pathName = usePathname();
const router = useRouter();
const revalidateUserSession = useRevalidateUserSession();
const session = useUserSession();
const accessToken = session.data?.access_token;
useEffect(() => {
// keep this running for the whole session unless the component was unmounted
const listener = client.auth.onAuthStateChange((_, user) => {
// log user out if user is falsy
// and if the current path is a private route
const shouldRedirectUser = !user && isPrivateRoute(pathName);
if (shouldRedirectUser) {
// send user away when signed out
window.location.assign('/');
return;
}
if (accessToken) {
const isOutOfSync = user?.access_token !== accessToken;
if (isOutOfSync) {
void router.refresh();
}
}
if (user && isPrivateRoute(pathName)) {
return revalidateUserSession();
}
});
// destroy listener on un-mounts
return () => listener.data.subscription.unsubscribe();
}, [
client.auth,
router,
accessToken,
revalidateUserSession,
pathName,
appHomePath,
]);
return <>{children}</>;
}
export function AuthChangeListener({
children,
appHomePath,
}: React.PropsWithChildren<{
appHomePath: string;
privateRoutes?: string[];
}>) {
const shouldActivateListener = isBrowser();
// we only activate the listener if
// we are rendering in the browser
if (!shouldActivateListener) {
return <>{children}</>;
}
return (
<AuthRedirectListener appHomePath={appHomePath}>
{children}
</AuthRedirectListener>
);
}
function isPrivateRoute(path: string) {
// TODO: use config
const prefixes = ['/home', '/admin', '/password-reset'];
return prefixes.some((prefix) => path.startsWith(prefix));
}