Passport/view/src/stores/userinfo.tsx
2024-01-30 17:57:23 +08:00

90 lines
2.1 KiB
TypeScript

import Cookie from "universal-cookie";
import { createContext, useContext } from "solid-js";
import { createStore } from "solid-js/store";
export interface Userinfo {
isLoggedIn: boolean,
displayName: string,
profiles: any,
meta: any
}
const UserinfoContext = createContext<Userinfo>();
const defaultUserinfo: Userinfo = {
isLoggedIn: false,
displayName: "Citizen",
profiles: null,
meta: null
};
const [userinfo, setUserinfo] = createStore<Userinfo>(structuredClone(defaultUserinfo));
export function getAtk(): string {
return new Cookie().get("access_token");
}
export async function refreshAtk() {
const rtk = new Cookie().get("refresh_token");
const res = await fetch("/api/auth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
refresh_token: rtk,
grant_type: "refresh_token"
})
});
if (res.status !== 200) {
throw new Error(await res.text());
} else {
const data = await res.json();
new Cookie().set("access_token", data["access_token"], { path: "/" });
new Cookie().set("refresh_token", data["refresh_token"], { path: "/" });
}
}
function checkLoggedIn(): boolean {
return new Cookie().get("access_token");
}
export async function readProfiles() {
if (!checkLoggedIn()) return;
const res = await fetch("/api/users/me", {
headers: { "Authorization": `Bearer ${getAtk()}` }
});
if (res.status !== 200) {
// Auto retry after refresh access token
await refreshAtk();
return await readProfiles();
}
const data = await res.json();
setUserinfo({
isLoggedIn: true,
displayName: data["nick"],
profiles: null,
meta: data
});
}
export function clearUserinfo() {
new Cookie().remove("access_token", { path: "/" });
new Cookie().remove("refresh_token", { path: "/" });
setUserinfo(defaultUserinfo);
}
export function UserinfoProvider(props: any) {
return (
<UserinfoContext.Provider value={userinfo}>
{props.children}
</UserinfoContext.Provider>
);
}
export function useUserinfo() {
return useContext(UserinfoContext);
}