diff --git a/Client/src/Features/Auth/authSlice.js b/Client/src/Features/Auth/authSlice.js index 9c1eea06c..98119ebd6 100644 --- a/Client/src/Features/Auth/authSlice.js +++ b/Client/src/Features/Auth/authSlice.js @@ -1,7 +1,6 @@ -import axios from "axios"; +import axiosInstance from "../../Utils/axiosConfig"; import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; import { jwtDecode } from "jwt-decode"; -const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL; const initialState = { isLoading: false, @@ -15,7 +14,7 @@ export const register = createAsyncThunk( "auth/register", async (form, thunkApi) => { try { - const res = await axios.post(`${BASE_URL}/auth/register`, form); + const res = await axiosInstance.post("/auth/register", form); return res.data; } catch (error) { if (error.response.data) { @@ -28,7 +27,7 @@ export const register = createAsyncThunk( export const login = createAsyncThunk("auth/login", async (form, thunkApi) => { try { - const res = await axios.post(`${BASE_URL}/auth/login`, form); + const res = await axiosInstance.post(`/auth/login`, form); return res.data; } catch (error) { if (error.response && error.response.data) { @@ -51,7 +50,7 @@ export const update = createAsyncThunk( fd.append("firstname", form.firstname); fd.append("lastname", form.lastname); if (form.file && form.file !== "") { - const imageResult = await axios.get(form.file, { + const imageResult = await axiosInstance.get(form.file, { responseType: "blob", }); fd.append("profileImage", imageResult.data); @@ -59,7 +58,7 @@ export const update = createAsyncThunk( form.deleteProfileImage && fd.append("deleteProfileImage", form.deleteProfileImage); - const res = await axios.post(`${BASE_URL}/auth/user/${user._id}`, fd, { + const res = await axiosInstance.post(`/auth/user/${user._id}`, fd, { headers: { Authorization: `Bearer ${token}`, "Content-Type": "multipart/form-data", diff --git a/Client/src/Features/Monitors/monitorsSlice.js b/Client/src/Features/Monitors/monitorsSlice.js index c2a4ad044..d5c257021 100644 --- a/Client/src/Features/Monitors/monitorsSlice.js +++ b/Client/src/Features/Monitors/monitorsSlice.js @@ -1,8 +1,6 @@ -import axios from "axios"; import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; import { jwtDecode } from "jwt-decode"; -const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL; - +import axiosInstance from "../../Utils/axiosConfig"; const initialState = { isLoading: false, monitors: [], @@ -16,7 +14,7 @@ export const createMonitor = createAsyncThunk( try { const { authToken, monitor } = data; - const res = await axios.post(`${BASE_URL}/monitors`, monitor, { + const res = await axiosInstance.post(`/monitors`, monitor, { headers: { Authorization: `Bearer ${authToken}`, "Content-Type": "application/json", @@ -36,9 +34,7 @@ export const getMonitors = createAsyncThunk( "monitors/getMonitors", async (token, thunkApi) => { try { - const res = await axios.get( - import.meta.env.VITE_APP_API_BASE_URL + "/monitors" - ); + const res = await axiosInstance.get("/monitors"); return res.data; } catch (error) { if (error.response && error.response.data) { @@ -54,14 +50,11 @@ export const getMonitorsByUserId = createAsyncThunk( async (token, thunkApi) => { const user = jwtDecode(token); try { - const res = await axios.get( - import.meta.env.VITE_APP_API_BASE_URL + "/monitors/user/" + user._id, - { - headers: { - Authorization: `Bearer ${token}`, - }, - } - ); + const res = await axiosInstance.get("/monitors/user/" + user._id, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); return res.data; } catch (error) { if (error.response && error.response.data) { diff --git a/Client/src/Pages/ForgotPassword/index.jsx b/Client/src/Pages/ForgotPassword/index.jsx index c5dbb0de3..5012b9d67 100644 --- a/Client/src/Pages/ForgotPassword/index.jsx +++ b/Client/src/Pages/ForgotPassword/index.jsx @@ -7,11 +7,9 @@ import Button from "../../Components/Button"; import LeftArrow from "../../assets/Images/arrow-left.png"; import { useState, useEffect } from "react"; import { recoveryValidation } from "../../Validation/validation"; -import axios from "axios"; +import axiosInstance from "../../Utils/axiosConfig"; import { useNavigate } from "react-router-dom"; -const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL; - const ForgotPassword = () => { const navigate = useNavigate(); @@ -50,7 +48,7 @@ const ForgotPassword = () => { if (error !== undefined) { throw error; } - await axios.post(`${BASE_URL}/auth/recovery/request`, form); + await axiosInstance.post(`/auth/recovery/request`, form); navigate("/check-email"); } catch (error) { //TODO display error (Toast?) diff --git a/Client/src/Pages/Login/index.jsx b/Client/src/Pages/Login/index.jsx index 4beb4d2c8..a9fcde0d5 100644 --- a/Client/src/Pages/Login/index.jsx +++ b/Client/src/Pages/Login/index.jsx @@ -9,12 +9,10 @@ import CheckBox from "../../Components/Checkbox/Checkbox"; import Button from "../../Components/Button"; import Google from "../../assets/Images/Google.png"; import PasswordTextField from "../../Components/TextFields/Password/PasswordTextField"; - +import axiosInstance from "../../Utils/axiosConfig"; import { loginValidation } from "../../Validation/validation"; import { login } from "../../Features/Auth/authSlice"; import { useDispatch } from "react-redux"; -import axios from "axios"; -const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL; const Login = () => { const dispatch = useDispatch(); @@ -33,8 +31,8 @@ const Login = () => { }); useEffect(() => { - axios - .get(BASE_URL + "/auth/users/admin") + axiosInstance + .get("/auth/users/admin") .then((response) => { if (response.data.data === false) { navigate("/register"); diff --git a/Client/src/Pages/Register/index.jsx b/Client/src/Pages/Register/index.jsx index 1760a5be2..617e04edd 100644 --- a/Client/src/Pages/Register/index.jsx +++ b/Client/src/Pages/Register/index.jsx @@ -11,12 +11,9 @@ import Check from "../../Components/Check/Check"; import Button from "../../Components/Button"; import Google from "../../assets/Images/Google.png"; import { registerValidation } from "../../Validation/validation"; - +import axiosInstance from "../../Utils/axiosConfig"; import { useDispatch } from "react-redux"; import { register } from "../../Features/Auth/authSlice"; -import axios from "axios"; - -const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL; const Register = () => { const dispatch = useDispatch(); @@ -41,8 +38,8 @@ const Register = () => { }); useEffect(() => { - axios - .get(BASE_URL + "/auth/users/admin") + axiosInstance + .get("/auth/users/admin") .then((response) => { if (response.data.data === true) { navigate("/login"); diff --git a/Client/src/Pages/SetNewPassword/index.jsx b/Client/src/Pages/SetNewPassword/index.jsx index d2360c7c5..d0b4242ee 100644 --- a/Client/src/Pages/SetNewPassword/index.jsx +++ b/Client/src/Pages/SetNewPassword/index.jsx @@ -8,8 +8,7 @@ import LeftArrow from "../../assets/Images/arrow-left.png"; import { useParams } from "react-router-dom"; import { useState, useEffect } from "react"; import { newPasswordValidation } from "../../Validation/validation"; -import axios from "axios"; -const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL; +import axiosInstance from "../../Utils/axiosConfig"; import { useNavigate } from "react-router-dom"; const SetNewPassword = () => { @@ -33,10 +32,10 @@ const SetNewPassword = () => { // TODO show loading spinner setIsLoading(true); try { - await axios.post(`${BASE_URL}/auth/recovery/validate`, { + await axiosInstance.post("/auth/recovery/validate", { recoveryToken: token, }); - await axios.post(`${BASE_URL}/auth/recovery/reset`, { + await axiosInstance.post("/auth/recovery/reset", { ...form, recoveryToken: token, }); diff --git a/Client/src/Utils/axiosConfig.js b/Client/src/Utils/axiosConfig.js new file mode 100644 index 000000000..8d3040028 --- /dev/null +++ b/Client/src/Utils/axiosConfig.js @@ -0,0 +1,27 @@ +import axios from "axios"; +import { clearAuthState } from "../Features/Auth/authSlice"; +const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL; + +let store; + +export const injectStore = (s) => { + store = s; +}; + +const axiosInstance = axios.create({ + baseURL: BASE_URL, +}); + +axiosInstance.interceptors.response.use( + (response) => response, + (error) => { + console.error(error); + if (error.response && error.response.status === 401) { + console.log("Invalid token revoked"); + store.dispatch(clearAuthState()); + } + return Promise.reject(error); + } +); + +export default axiosInstance; diff --git a/Client/src/main.jsx b/Client/src/main.jsx index 601dab68d..09754147d 100644 --- a/Client/src/main.jsx +++ b/Client/src/main.jsx @@ -8,6 +8,9 @@ import { ThemeProvider } from "@mui/material"; import { Provider } from "react-redux"; import { persistor, store } from "./store"; import { PersistGate } from "redux-persist/integration/react"; +import { injectStore } from "./Utils/axiosConfig.js"; + +injectStore(store); ReactDOM.createRoot(document.getElementById("root")).render(