refactor: update axios client and auth repository for public/private route handling

This commit is contained in:
Pramod Mahajan 2025-06-16 21:10:25 +05:30 committed by Vikas Nale
parent 8ac9c64bf4
commit 39ee2d58ce
3 changed files with 48 additions and 38 deletions

View File

@ -67,9 +67,13 @@ const ResetPasswordPage = () => {
navigate("/auth/login", { replace: true });
// setLoading(false);
} catch (error) {
showToast("Link is expries or Invalid ", "error");
setTokenExpired(true);
debugger;
setLoading(false);
if (error?.response?.status === 400) {
showToast("Please check valid Credentials", "error");
} else {
setTokenExpired(true);
}
}
};
@ -77,7 +81,10 @@ const ResetPasswordPage = () => {
return (
<AuthWrapper>
<h4 className="mb-2 ">Invalid Link 🔒</h4>
<p className="mb-4" style={{fontSize: "12px"}}>This link appears to be invalid or expired. Please use the 'Forgot Password' feature to set your new password.</p>
<p className="mb-4" style={{ fontSize: "12px" }}>
This link appears to be invalid or expired. Please use the 'Forgot
Password' feature to set your new password.
</p>
<div className="text-center mb-4">
<Link to="/auth/forgot-password" className="btn btn-outline-primary">
Go to Forgot Password
@ -142,7 +149,6 @@ const ResetPasswordPage = () => {
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0,
borderLeft: 0,
}}
>
{hidepass ? (
@ -185,7 +191,6 @@ const ResetPasswordPage = () => {
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0,
borderLeft: 0,
}}
>
{hidepass1 ? (

View File

@ -1,18 +1,20 @@
import { api } from "../utils/axiosClient";
const AuthRepository = {
login: (data) => api.post("/api/auth/login", data),
refreshToken: (data) => api.post("/api/auth/refresh-token", data),
// Public routes (no auth token required)
login: (data) => api.postPublic("/api/auth/login", data),
refreshToken: (data) => api.postPublic("/api/auth/refresh-token", data),
forgotPassword: (data) => api.postPublic("/api/auth/forgot-password", data),
resetPassword: (data) => api.postPublic("/api/auth/reset-password", data),
sendOTP: (data) => api.postPublic("/api/auth/send-otp", data),
verifyOTP: (data) => api.postPublic("/api/auth/login-otp", data),
register: (data) => api.postPublic("/api/auth/register", data),
sendMail: (data) => api.postPublic("/api/auth/sendmail", data),
// Protected routes (require auth token)
logout: (data) => api.post("/api/auth/logout", data),
profile: () => api.get(`/api/user/profile`),
register: (data) => api.post("api/auth/register", data),
resetPassword: (data) => api.post("/api/auth/reset-password", data),
forgotPassword: (data) => api.post("/api/auth/forgot-password", data),
sendMail: (data) => api.post("/api/auth/sendmail", data),
changepassword: ( data ) => api.post( "/api/auth/change-password", data ),
sendOTP: ( data ) => api.post( 'api/auth/send-otp', data ),
verifyOTP:(data)=>api.post("api/auth/login-otp",data)
profile: () => api.get("/api/user/profile"),
changepassword: (data) => api.post("/api/auth/change-password", data),
};
export default AuthRepository;

View File

@ -5,18 +5,22 @@ import showToast from "../services/toastService";
const base_Url = process.env.VITE_BASE_URL;
// const base_Url = "https://api.marcoaiot.com";
export const axiosClient = axios.create({
baseURL: base_Url, // Your Web API URL
withCredentials: false, // Required if the API uses cookies
baseURL: base_Url,
withCredentials: false,
headers: {
"Content-Type": "application/json", // Specify the content type
"Content-Type": "application/json",
},
});
// Auto retry failed requests (e.g., network issues)
axiosRetry(axiosClient, { retries: 3 });
// Request interceptor to add Bearer token
// Request Interceptor Add Bearer token if required
axiosClient.interceptors.request.use(
async (config) => {
if (config.authRequired) {
const requiresAuth = config.authRequired !== false; // default to true
if (requiresAuth) {
const token = localStorage.getItem("jwtToken");
if (token) {
config.headers["Authorization"] = `Bearer ${token}`;
@ -25,25 +29,24 @@ axiosClient.interceptors.request.use(
config._retry = false;
}
}
return config;
},
(error) => Promise.reject(error)
);
// // Response interceptor to handle responses globally (optional)
// Add an interceptor to handle expired tokens
// 🔄 Response Interceptor Handle 401, refresh token, etc.
axiosClient.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
// Prevent infinite loop
if (!originalRequest || originalRequest._retry) {
// Skip retry for public requests or already retried ones
if (!originalRequest || originalRequest._retry || originalRequest.authRequired === false) {
return Promise.reject(error);
}
// Only show one toast per request
// Avoid showing multiple toasts
if (!originalRequest._toastShown) {
originalRequest._toastShown = true;
@ -59,7 +62,6 @@ axiosClient.interceptors.response.use(
const isRefreshRequest = error.config.url.includes("refresh-token");
if (status === 401 && !isRefreshRequest) {
// Mark as retried to avoid loops
originalRequest._retry = true;
const refreshToken = localStorage.getItem("refreshToken");
@ -70,7 +72,7 @@ axiosClient.interceptors.response.use(
}
try {
// Refresh token
// Refresh token call
const res = await axiosClient.post("/api/Auth/refresh-token", {
token: localStorage.getItem("jwtToken"),
refreshToken,
@ -78,15 +80,13 @@ axiosClient.interceptors.response.use(
const { token, refreshToken: newRefreshToken } = res.data.data;
// Save new tokens
// Save updated tokens
localStorage.setItem("jwtToken", token);
localStorage.setItem("refreshToken", newRefreshToken);
// Set Authorization header
// Retry original request with new token
originalRequest.headers["Authorization"] = `Bearer ${token}`;
// Optional: Instead of retrying, you may choose to reload app or go to home
return axiosClient(originalRequest); // <== only retry once
return axiosClient(originalRequest);
} catch (refreshError) {
redirectToLogin();
return Promise.reject(refreshError);
@ -96,11 +96,12 @@ axiosClient.interceptors.response.use(
showToast("An unknown error occurred.", "error");
}
}
return Promise.reject(error);
}
);
// Generic API Call
// Generic API function
const apiRequest = async (method, url, data = {}, config = {}) => {
try {
const response = await axiosClient({
@ -116,15 +117,16 @@ const apiRequest = async (method, url, data = {}, config = {}) => {
}
};
// Exported API wrapper
export const api = {
// For public routes like login, set authRequired: false
// Public routes (no token required)
postPublic: (url, data = {}, customHeaders = {}) =>
apiRequest("post", url, data, {
headers: { ...customHeaders },
authRequired: false,
}),
// For protected routes, authRequired defaults to true
// Authenticated routes
get: (url, params = {}, customHeaders = {}) =>
apiRequest("get", url, params, {
headers: { ...customHeaders },
@ -149,7 +151,8 @@ export const api = {
authRequired: true,
}),
};
//export default axiosClient;
// Redirect helper
function redirectToLogin() {
window.location.href = "/auth/login";
}
}