116 lines
3.1 KiB
TypeScript
116 lines
3.1 KiB
TypeScript
import {
|
|
FC,
|
|
useState,
|
|
useEffect,
|
|
createContext,
|
|
useContext,
|
|
useRef,
|
|
Dispatch,
|
|
SetStateAction,
|
|
} from 'react'
|
|
import {useLocation} from 'react-router-dom'
|
|
import {LayoutSplashScreen} from '../../../../_res/layout/core'
|
|
import {AuthModel, UserModel} from './_models'
|
|
import * as authHelper from './AuthHelpers'
|
|
import {getUserByToken} from './_requests'
|
|
import {WithChildren} from '../../../../_res/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 saveAuth = (auth: AuthModel | undefined) => {
|
|
setAuth(auth)
|
|
if (auth) {
|
|
authHelper.setAuth(auth)
|
|
} else {
|
|
authHelper.removeAuth()
|
|
}
|
|
}
|
|
|
|
const logout = () => {
|
|
saveAuth(undefined)
|
|
setCurrentUser(undefined)
|
|
}
|
|
|
|
return (
|
|
<AuthContext.Provider value={{auth, saveAuth, currentUser, setCurrentUser, logout}}>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
)
|
|
}
|
|
|
|
const AuthInit: FC<WithChildren> = ({children}) => {
|
|
const pathname = useLocation().pathname
|
|
const {auth, logout, setCurrentUser} = useAuth()
|
|
const didRequest = useRef(false)
|
|
const [showSplashScreen, setShowSplashScreen] = useState(true)
|
|
// We should request user by authToken (IN OUR EXAMPLE IT'S API_TOKEN) before rendering the application
|
|
useEffect(() => {
|
|
// function to expire session after 5 mins
|
|
let logoutSession = setTimeout(()=>{ //expire session after 5 mins
|
|
logout()
|
|
}, Number(process.env.REACT_APP_SESSION_TIMEOUT))
|
|
|
|
const requestUser = async (apiToken: string) => {
|
|
try {
|
|
if (!didRequest.current) {
|
|
// const {data} = await getUserByToken(apiToken)
|
|
// if (data) {
|
|
// setCurrentUser(data)
|
|
// }
|
|
if (localStorage.getItem('kt-auth-react-v')) {
|
|
setCurrentUser(auth.profile)
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(error)
|
|
if (!didRequest.current) {
|
|
logout()
|
|
}
|
|
} finally {
|
|
setShowSplashScreen(false)
|
|
}
|
|
|
|
return () => (didRequest.current = true)
|
|
}
|
|
|
|
if (auth && auth.session_token) {
|
|
requestUser(auth.session_token)
|
|
} else {
|
|
logout()
|
|
setShowSplashScreen(false)
|
|
}
|
|
// eslint-disable-next-line
|
|
|
|
return ()=>{ // clears session timeout side effect
|
|
clearInterval(logoutSession)
|
|
}
|
|
}, [pathname])
|
|
|
|
return showSplashScreen ? <LayoutSplashScreen /> : <>{children}</>
|
|
}
|
|
|
|
export {AuthProvider, AuthInit, useAuth}
|