-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathuseRouteProtection.ts
77 lines (69 loc) · 2.14 KB
/
useRouteProtection.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import { usePrevious } from "@axelarjs/utils/react";
import { useCallback, useEffect } from "react";
import { signOut, useSession } from "next-auth/react";
import { useRouter } from "next/router";
import { useAccount, useDisconnect } from "~/lib/hooks";
import type { AccountStatus } from "~/services/db/kv";
import { logger } from "../logger";
export type UseRouteProtectionProps = {
/**
* The route to redirect to if the user is not logged in.
*
* @default "/"
* */
redirectTo?: string;
/**
* The account statuses that are allowed to access the route.
*
* @default ["enabled", "privileged"]
* */
accountStatuses?: AccountStatus[];
};
export function useRouteProtection({
redirectTo = "/",
accountStatuses = ["enabled", "privileged"],
}: UseRouteProtectionProps) {
const { address } = useAccount();
const { disconnect } = useDisconnect();
const { data: session, status: sessionStatus } = useSession();
const router = useRouter();
const prevAddress = usePrevious(address);
const handleSignout = useCallback(async () => {
await signOut({ callbackUrl: "/" });
disconnect();
}, [disconnect]);
/**
* redirect rules rules:
*
* If the user is not logged in, redirect to the homepage.
* If the user is logged in but does not have an address, redirect to the homepage.
* If the user is logged in and has an address, but the address is not in the session, redirect to the homepage.
*/
useEffect(() => {
if (sessionStatus === "loading" || !session) return;
if (
// sign out if the user is not logged in
(!address && prevAddress) ||
// or the session is authenticated but the user has no address
(sessionStatus === "authenticated" && (!session.address || !address)) ||
// or the account status is not allowed
!accountStatuses.includes(session.accountStatus)
) {
handleSignout()
.then(() => router.push(redirectTo))
.catch((err) => {
logger.error(err);
});
}
}, [
accountStatuses,
address,
handleSignout,
prevAddress,
redirectTo,
router,
session,
sessionStatus,
]);
return handleSignout;
}