107 lines
2.8 KiB
TypeScript
107 lines
2.8 KiB
TypeScript
import { sleep } from "@/lib/utils";
|
|
import { PermissionEnum } from "@/types/permission";
|
|
import React, { useContext, useEffect, useMemo } from "react";
|
|
import { useCallback, useState } from "react";
|
|
|
|
export interface IAuthContext {
|
|
isAuthenticated: boolean;
|
|
setAuthenticated: (value: boolean) => void;
|
|
logout: () => Promise<void>;
|
|
login: (username: string) => void;
|
|
username: string;
|
|
token: string;
|
|
name: string;
|
|
acs: number[];
|
|
hasPermission: (permission: PermissionEnum) => boolean;
|
|
role: {
|
|
roleName: string;
|
|
priority: number;
|
|
};
|
|
}
|
|
|
|
const AuthContext = React.createContext<IAuthContext | null>(null);
|
|
|
|
const key = "accesscontrol.auth.user";
|
|
|
|
function getStoredUser() {
|
|
return localStorage.getItem(key);
|
|
}
|
|
|
|
function setStoredUser(user: string | null) {
|
|
if (user) {
|
|
localStorage.setItem(key, user);
|
|
} else {
|
|
localStorage.removeItem(key);
|
|
}
|
|
}
|
|
|
|
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
|
const [user, setUser] = useState<string>(getStoredUser() || "");
|
|
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(!!user);
|
|
const token = localStorage.getItem("token") || "";
|
|
const name = localStorage.getItem("name") || "";
|
|
const acsString = localStorage.getItem("acs");
|
|
const acs = useMemo(() => (acsString ? acsString.split(",").map(Number) : []), [acsString]);
|
|
const roleName = localStorage.getItem("role") || "";
|
|
const priority = localStorage.getItem("priority") || "-1";
|
|
|
|
const setAuthenticated = useCallback((value: boolean) => {
|
|
setIsAuthenticated(value);
|
|
}, []);
|
|
|
|
const login = useCallback((username: string) => {
|
|
setStoredUser(username);
|
|
setUser(username);
|
|
}, []);
|
|
|
|
const hasPermission = useCallback(
|
|
(permission: PermissionEnum) => {
|
|
return acs.some((a) => a === permission);
|
|
},
|
|
[acs]
|
|
);
|
|
|
|
const logout = useCallback(async () => {
|
|
await sleep(250);
|
|
setAuthenticated(false);
|
|
setStoredUser("");
|
|
setUser("");
|
|
localStorage.removeItem("token");
|
|
localStorage.removeItem("name");
|
|
localStorage.removeItem("acs");
|
|
localStorage.removeItem("role");
|
|
localStorage.removeItem("priority");
|
|
}, [setAuthenticated]);
|
|
|
|
useEffect(() => {
|
|
setUser(getStoredUser() || "");
|
|
}, []);
|
|
|
|
return (
|
|
<AuthContext.Provider
|
|
value={{
|
|
isAuthenticated,
|
|
setAuthenticated,
|
|
login,
|
|
logout,
|
|
username: user,
|
|
token,
|
|
name,
|
|
acs,
|
|
role: { roleName, priority: Number(priority) },
|
|
hasPermission
|
|
}}>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
);
|
|
}
|
|
|
|
// eslint-disable-next-line react-refresh/only-export-components
|
|
export function useAuth() {
|
|
const context = useContext(AuthContext);
|
|
if (!context) {
|
|
throw new Error("useAuth must be used within an AuthProvider");
|
|
}
|
|
return context;
|
|
}
|