-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAuthContext.tsx
85 lines (77 loc) · 2.13 KB
/
AuthContext.tsx
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
78
79
80
81
82
83
84
85
import { createContext, createSignal, useContext } from "solid-js";
import { User } from "~/lib/auth";
export const AuthContext = createContext<{
me: () => User | null;
signIn: (user: User) => void;
signOut: () => void;
isSignedIn: () => boolean;
}>();
const [me, setMe] = createSignal<User | null>(null);
export const useAuth = () => useContext(AuthContext)!;
// auth.rs sets the informative cookie for the client
function get_me_from_cookie(): {
me_from_cookie: User | null;
expiry_date: Date | null;
} {
const cookiePayload = document?.cookie
? document.cookie
?.split(";")
.map((v) => v.trim())
.find((v) => v.startsWith("authenticated_user_js"))
?.split("=")[1]
: null;
let me_from_cookie = null;
let expiry_date = null;
if (cookiePayload) {
try {
let parsed_cookie = JSON.parse(cookiePayload);
me_from_cookie = parsed_cookie.user;
expiry_date = new Date(parsed_cookie.expiry_date);
} catch (e) {}
}
return {
me_from_cookie,
expiry_date,
};
}
let refreshTimeout: any;
// keeps me() updated with the cookie
// sets a timeout to refresh itself when the cookie expires
// if another request refreshed the cookie the timeout is cleared and reset
// api requests should refresh the cookie
// if no activity happens, the client will reactively "sign out" on expiry
function setMeFromCookie() {
const { me_from_cookie, expiry_date } = get_me_from_cookie();
if (me_from_cookie) {
setMe(me_from_cookie);
clearTimeout(refreshTimeout);
refreshTimeout = setTimeout(
setMeFromCookie,
expiry_date!.getTime() - new Date().getTime()
);
} else if (me()) {
setMe(null);
}
}
export const AuthProvider = (props: any) => {
setMeFromCookie();
const authContext = {
me: () => me(),
signIn: (_user: User) => {
setMeFromCookie();
},
signOut: async () => {
fetch("/signout", {
method: "POST",
}).then(() => {
setMeFromCookie();
});
},
isSignedIn: () => !!me(),
};
return (
<AuthContext.Provider value={authContext}>
{props.children}
</AuthContext.Provider>
);
};