Files
parcer/src/context/auth.tsx

141 lines
4.2 KiB
TypeScript
Raw Normal View History

2024-09-24 12:07:32 +05:30
import { useReducer, createContext, useEffect } from 'react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
2024-11-11 20:21:12 +05:30
import { jwtDecode } from 'jwt-decode';
2024-11-01 08:26:00 +05:30
import { apiUrl } from "../apiConfig";
2024-09-24 12:07:32 +05:30
2024-09-25 12:15:38 +05:30
interface AuthProviderProps {
2024-09-24 12:10:04 +05:30
children: React.ReactNode;
2024-09-24 12:07:32 +05:30
}
2024-09-24 12:08:19 +05:30
interface ActionType {
type: 'LOGIN' | 'LOGOUT';
payload?: any;
2024-09-24 12:10:04 +05:30
}
2024-09-24 12:08:19 +05:30
2024-09-24 12:07:32 +05:30
type InitialStateType = {
2024-09-24 12:10:04 +05:30
user: any;
2024-09-24 12:07:32 +05:30
};
const initialState = {
2024-09-24 12:10:04 +05:30
user: null,
2024-09-24 12:07:32 +05:30
};
2024-09-25 12:07:24 +05:30
const AuthContext = createContext<{
2024-09-24 12:10:04 +05:30
state: InitialStateType;
dispatch: React.Dispatch<ActionType>;
2024-09-24 12:07:32 +05:30
}>({
2024-09-24 12:10:04 +05:30
state: initialState,
dispatch: () => null,
2024-09-24 12:07:32 +05:30
});
2024-09-24 12:08:19 +05:30
const reducer = (state: InitialStateType, action: ActionType) => {
2024-09-24 12:10:04 +05:30
switch (action.type) {
case 'LOGIN':
return {
...state,
user: action.payload,
};
case 'LOGOUT':
return {
...state,
user: null,
};
default:
return state;
}
2024-09-24 12:07:32 +05:30
};
2024-09-25 12:15:38 +05:30
const AuthProvider = ({ children }: AuthProviderProps) => {
2024-09-24 12:10:04 +05:30
const [state, dispatch] = useReducer(reducer, initialState);
const navigate = useNavigate();
axios.defaults.withCredentials = true;
2024-09-24 12:07:32 +05:30
2024-11-07 21:56:41 +05:30
const logoutUser = () => {
dispatch({ type: 'LOGOUT' });
window.localStorage.removeItem('user');
2024-11-11 20:21:12 +05:30
window.localStorage.removeItem('logoutTimeout');
2024-11-07 21:56:41 +05:30
navigate('/login');
};
const checkTokenExpiration = (token: string) => {
2024-11-11 19:59:51 +05:30
if (!token) return;
try {
const decodedToken: any = jwtDecode(token);
const currentTime = Date.now();
2024-11-11 19:59:51 +05:30
const tokenExpiryTime = decodedToken.exp * 1000;
2024-11-07 21:56:41 +05:30
if (tokenExpiryTime > currentTime) {
2024-11-11 20:21:12 +05:30
// Calculate remaining time until token expires
const remainingTime = tokenExpiryTime - currentTime;
// Check if a logout timeout already exists in local storage
const existingTimeout = window.localStorage.getItem('logoutTimeout');
if (!existingTimeout) {
// Set a timeout for auto-logout
const timeoutId = setTimeout(logoutUser, remainingTime);
window.localStorage.setItem('logoutTimeout', JSON.stringify(timeoutId));
}
} else {
logoutUser(); // Immediately logout if token is expired
}
} catch (error) {
console.error("Error decoding token:", error);
2024-11-11 19:59:51 +05:30
logoutUser();
2024-11-07 21:56:41 +05:30
}
};
2024-09-24 12:10:04 +05:30
useEffect(() => {
const storedUser = window.localStorage.getItem('user');
if (storedUser) {
2024-11-07 21:56:41 +05:30
const userData = JSON.parse(storedUser);
dispatch({ type: 'LOGIN', payload: userData });
2024-11-11 19:59:51 +05:30
// Run expiration check only if a token exists
if (userData.token) {
checkTokenExpiration(userData.token);
}
}
2024-11-11 20:21:12 +05:30
// Clean up timeout on component unmount
return () => {
const timeoutId = window.localStorage.getItem('logoutTimeout');
if (timeoutId) {
clearTimeout(JSON.parse(timeoutId));
window.localStorage.removeItem('logoutTimeout');
}
};
2024-11-11 19:59:51 +05:30
}, []); // Only run this effect once on mount
2024-09-24 12:10:04 +05:30
axios.interceptors.response.use(
2024-11-11 19:59:51 +05:30
(response) => response,
(error) => {
const res = error.response;
2024-11-11 19:59:51 +05:30
if (res?.status === 401 && !res.config.__isRetryRequest) {
2024-09-24 12:10:04 +05:30
return new Promise((resolve, reject) => {
axios
2024-11-01 08:26:00 +05:30
.get(`${apiUrl}/auth/logout`)
.then(() => {
2024-09-24 12:10:04 +05:30
console.log('/401 error > logout');
2024-11-07 21:56:41 +05:30
logoutUser();
2024-09-24 12:10:04 +05:30
})
.catch((err) => {
console.error('AXIOS INTERCEPTORS ERROR:', err);
2024-09-24 12:10:04 +05:30
reject(error);
});
});
}
return Promise.reject(error);
}
);
2024-09-24 12:10:04 +05:30
return (
<AuthContext.Provider value={{ state, dispatch }}>
{children}
</AuthContext.Provider>
2024-09-24 12:10:04 +05:30
);
2024-09-24 12:07:32 +05:30
};
2024-11-11 19:59:51 +05:30
export { AuthContext, AuthProvider };