Cleanup
This commit is contained in:
96
packages/supabase/src/components/auth-change-listener.tsx
Normal file
96
packages/supabase/src/components/auth-change-listener.tsx
Normal 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));
|
||||
}
|
||||
Reference in New Issue
Block a user