Files
WrenchAgents/src/app/modules/auth/core/Auth.tsx
T

148 lines
3.8 KiB
TypeScript

/* eslint-disable react-refresh/only-export-components */
import {
FC,
useState,
useEffect,
useCallback,
createContext,
useContext,
Dispatch,
SetStateAction,
} from "react";
import { LayoutSplashScreen } from "../../../../_metronic/layout/core";
import { AuthModel, UserModel } from "./_models";
import * as authHelper from "./AuthHelpers";
import { getUserByToken } from "./_requests";
import { WithChildren } from "../../../../_metronic/helpers";
type AuthContextProps = {
auth: AuthModel | undefined;
saveAuth: (auth: AuthModel | undefined) => void;
currentUser: UserModel | undefined;
setCurrentUser: Dispatch<SetStateAction<UserModel | undefined>>;
logout: () => void;
};
const initAuthContextPropsState = {
auth: authHelper.getAuth(),
saveAuth: () => {},
currentUser: undefined,
setCurrentUser: () => {},
logout: () => {},
};
const AuthContext = createContext<AuthContextProps>(initAuthContextPropsState);
const useAuth = () => {
return useContext(AuthContext);
};
const AuthProvider: FC<WithChildren> = ({ children }) => {
const [auth, setAuth] = useState<AuthModel | undefined>(authHelper.getAuth());
const [currentUser, setCurrentUser] = useState<UserModel | undefined>();
const [lastActivityTime, setLastActivityTime] = useState(Date.now());
let checkExpirationInMinutes: number = Number(
import.meta.env.VITE_APP_SESSION_EXPIRE_MINUTES
);
let expirationChecker: number = Number(
import.meta.env.VITE_APP_SESSION_EXPIRE_CHECKER
);
const saveAuth = (auth: AuthModel | undefined) => {
setAuth(auth);
if (auth) {
authHelper.setAuth(auth);
} else {
authHelper.removeAuth();
}
};
const logout = () => {
saveAuth(undefined);
setCurrentUser(undefined);
};
useEffect((): any => {
const expireSession = () => {
localStorage.removeItem("wrenchboard-agent-auth-details");
logout();
};
const checkInactivity = setInterval(() => {
let currentTime: number = Date.now();
let checkLastActivityTime: number = lastActivityTime;
if (currentTime - checkLastActivityTime > checkExpirationInMinutes) {
expireSession();
}
}, expirationChecker);
// cleaning up listeners
return () => {
clearInterval(checkInactivity);
};
}, [lastActivityTime]);
// Reset last activity time on user input
const resetTime = useCallback(() => {
setLastActivityTime(Date.now());
}, []);
useEffect(() => {
window.addEventListener("mousemove", resetTime);
window.addEventListener("keydown", resetTime);
return () => {
window.removeEventListener("mousemove", resetTime);
window.removeEventListener("keydown", resetTime);
};
}, [resetTime]);
return (
<AuthContext.Provider
value={{ auth, saveAuth, currentUser, setCurrentUser, logout }}
>
{children}
</AuthContext.Provider>
);
};
const AuthInit: FC<WithChildren> = ({ children }) => {
const { auth, currentUser, logout, setCurrentUser } = useAuth();
const [showSplashScreen, setShowSplashScreen] = useState(true);
// We should request user by authToken (IN OUR EXAMPLE IT'S API_TOKEN) before rendering the application
useEffect(() => {
const requestUser = async (apiToken: string) => {
try {
if (!currentUser) {
const { data } = await getUserByToken(apiToken);
if (data) {
setCurrentUser(data);
}
}
} catch (error) {
console.error(error);
if (currentUser) {
logout();
}
} finally {
setShowSplashScreen(false);
}
};
if (auth && auth.api_token) {
requestUser(auth.api_token);
} else {
logout();
setShowSplashScreen(false);
}
// eslint-disable-next-line
}, []);
return showSplashScreen ? <LayoutSplashScreen /> : <>{children}</>;
};
export { AuthProvider, AuthInit, useAuth };