203 lines
4.7 KiB
TypeScript
203 lines
4.7 KiB
TypeScript
import { createContext, ReactNode, useEffect, useReducer } from 'react';
|
|
// utils
|
|
import axios from '../utils/axios';
|
|
// import { isValidToken, setSession } from '../utils/jwt';
|
|
import { setSession, getSession, getUser } from '../utils/token';
|
|
// @types
|
|
import { ActionMap, AuthState, AuthUser, JWTContextType } from '../@types/auth';
|
|
// ----------------------------------------------------------------------
|
|
import { Navigate, useLocation } from 'react-router-dom';
|
|
|
|
enum Types {
|
|
Initial = 'INITIALIZE',
|
|
Login = 'LOGIN',
|
|
Logout = 'LOGOUT',
|
|
Register = 'REGISTER',
|
|
}
|
|
|
|
type JWTAuthPayload = {
|
|
[Types.Initial]: {
|
|
isAuthenticated: boolean;
|
|
user: AuthUser;
|
|
};
|
|
[Types.Login]: {
|
|
user: AuthUser;
|
|
};
|
|
[Types.Logout]: undefined;
|
|
[Types.Register]: {
|
|
user: AuthUser;
|
|
};
|
|
};
|
|
|
|
export type JWTActions = ActionMap<JWTAuthPayload>[keyof ActionMap<JWTAuthPayload>];
|
|
|
|
const initialState: AuthState = {
|
|
isAuthenticated: false,
|
|
isInitialized: false,
|
|
user: null,
|
|
};
|
|
|
|
const JWTReducer = (state: AuthState, action: JWTActions) => {
|
|
switch (action.type) {
|
|
case 'INITIALIZE':
|
|
return {
|
|
isAuthenticated: action.payload.isAuthenticated,
|
|
isInitialized: true,
|
|
user: action.payload.user,
|
|
};
|
|
case 'LOGIN':
|
|
return {
|
|
...state,
|
|
isAuthenticated: true,
|
|
user: action.payload.user,
|
|
};
|
|
case 'LOGOUT':
|
|
return {
|
|
...state,
|
|
isAuthenticated: false,
|
|
user: null,
|
|
};
|
|
|
|
case 'REGISTER':
|
|
return {
|
|
...state,
|
|
isAuthenticated: true,
|
|
user: action.payload.user,
|
|
};
|
|
|
|
default:
|
|
return state;
|
|
}
|
|
};
|
|
|
|
const AuthContext = createContext<JWTContextType | null>(null);
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
type AuthProviderProps = {
|
|
children: ReactNode;
|
|
};
|
|
|
|
function AuthProvider({ children }: AuthProviderProps) {
|
|
const [state, dispatch] = useReducer(JWTReducer, initialState);
|
|
let location = useLocation();
|
|
|
|
useEffect(() => {
|
|
const initialize = async () => {
|
|
try {
|
|
const accessToken = getSession();
|
|
if (accessToken) {
|
|
setSession(accessToken);
|
|
|
|
const response = await axios.get('/user');
|
|
const user = response.data;
|
|
|
|
dispatch({
|
|
type: Types.Initial,
|
|
payload: {
|
|
isAuthenticated: true,
|
|
user,
|
|
},
|
|
});
|
|
} else {
|
|
dispatch({
|
|
type: Types.Initial,
|
|
payload: {
|
|
isAuthenticated: false,
|
|
user: null,
|
|
},
|
|
});
|
|
}
|
|
} catch (err) {
|
|
dispatch({
|
|
type: Types.Initial,
|
|
payload: {
|
|
isAuthenticated: false,
|
|
user: null,
|
|
},
|
|
});
|
|
}
|
|
};
|
|
|
|
initialize();
|
|
}, []);
|
|
|
|
const login = async (email: string, password: string) => axios
|
|
.post('/login', { email, password })
|
|
.then((response) => {
|
|
const { user, token } = response.data;
|
|
setSession(token);
|
|
|
|
dispatch({
|
|
type: Types.Login,
|
|
payload: {
|
|
user,
|
|
}
|
|
});
|
|
})
|
|
.catch(error => {
|
|
if (error.response.status !== 404) throw error.response
|
|
if (error.response.status !== 422) throw error.response
|
|
});
|
|
|
|
const register = async (email: string, password: string, firstName: string, lastName: string) => {
|
|
const response = await axios.post('/api/register', {
|
|
email,
|
|
password,
|
|
firstName,
|
|
lastName,
|
|
});
|
|
const { accessToken, user } = response.data;
|
|
|
|
window.localStorage.setItem('accessToken', accessToken);
|
|
dispatch({
|
|
type: Types.Register,
|
|
payload: {
|
|
user,
|
|
},
|
|
});
|
|
};
|
|
|
|
const logout = async () => {
|
|
setSession(null);
|
|
dispatch({ type: Types.Logout });
|
|
};
|
|
|
|
return (<AuthContext.Provider
|
|
value={{
|
|
...state,
|
|
method: 'jwt',
|
|
login,
|
|
logout,
|
|
register,
|
|
}}
|
|
>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
);
|
|
|
|
// if (state.isInitialized) {
|
|
// return (!state.isAuthenticated && location.pathname !== '/auth/login') ?
|
|
// (<Navigate to="/auth/login" replace={true} />)
|
|
// : false && location.pathname == '/auth/login' ?
|
|
// (<Navigate to="/dashboard" replace={true} />)
|
|
// : (
|
|
// <AuthContext.Provider
|
|
// value={{
|
|
// ...state,
|
|
// method: 'jwt',
|
|
// login,
|
|
// logout,
|
|
// register,
|
|
// }}
|
|
// >
|
|
// {children}
|
|
// </AuthContext.Provider>
|
|
// );
|
|
// } else {
|
|
// return (<Navigate to="/auth/login" replace={true} />)
|
|
// }
|
|
}
|
|
|
|
export { AuthContext, AuthProvider };
|