diff --git a/Client/src/Components/TabPanels/Account/ProfilePanel.jsx b/Client/src/Components/TabPanels/Account/ProfilePanel.jsx
index 355b09ca6..398c10c54 100644
--- a/Client/src/Components/TabPanels/Account/ProfilePanel.jsx
+++ b/Client/src/Components/TabPanels/Account/ProfilePanel.jsx
@@ -19,6 +19,7 @@ import ProgressUpload from "../../ProgressBars";
import { formatBytes } from "../../../Utils/fileUtils";
import { clearUptimeMonitorState } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import { createToast } from "../../../Utils/toastUtils";
+import { logger } from "../../../Utils/Logger";
/**
* ProfilePanel component displays a form for editing user profile information
@@ -256,7 +257,7 @@ const ProfilePanel = () => {
placeholder="Enter your email"
autoComplete="email"
// TODO - add onChange
- onChange={() => console.log("Disabled.")}
+ onChange={() => logger.warn("disabled")}
// error={errors[idToName["edit-email"]]}
disabled={true}
/>
diff --git a/Client/src/Components/TabPanels/Account/TeamPanel.jsx b/Client/src/Components/TabPanels/Account/TeamPanel.jsx
index 07bbf6e68..95df3e294 100644
--- a/Client/src/Components/TabPanels/Account/TeamPanel.jsx
+++ b/Client/src/Components/TabPanels/Account/TeamPanel.jsx
@@ -16,7 +16,7 @@ import { useEffect, useState } from "react";
import EditSvg from "../../../assets/icons/edit.svg?react";
import Field from "../../Inputs/Field";
import { credentials } from "../../../Validation/validation";
-import axiosInstance from "../../../Utils/axiosConfig";
+import { networkService } from "../../../main";
import { createToast } from "../../../Utils/toastUtils";
import { useSelector } from "react-redux";
import BasicTable from "../../BasicTable";
@@ -52,10 +52,7 @@ const TeamPanel = () => {
useEffect(() => {
const fetchTeam = async () => {
try {
- const response = await axiosInstance.get("/auth/users", {
- headers: { Authorization: `Bearer ${authToken}` },
- });
-
+ const response = await networkService.getAllUsers(authToken);
setMembers(response.data.data);
} catch (error) {
createToast({
@@ -179,13 +176,10 @@ const TeamPanel = () => {
setErrors((prev) => ({ ...prev, email: error.details[0].message }));
} else
try {
- await axiosInstance.post(
- "/auth/invite",
- {
- email: toInvite.email,
- role: toInvite.role,
- },
- { headers: { Authorization: `Bearer ${authToken}` } }
+ await networkService.requestInvitationToken(
+ authToken,
+ toInvite.email,
+ toInvite.role
);
closeInviteModal();
diff --git a/Client/src/Features/Auth/authSlice.js b/Client/src/Features/Auth/authSlice.js
index 6da315fc4..fa1f0471e 100644
--- a/Client/src/Features/Auth/authSlice.js
+++ b/Client/src/Features/Auth/authSlice.js
@@ -1,4 +1,4 @@
-import axiosInstance from "../../Utils/axiosConfig";
+import { networkService } from "../../main";
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { jwtDecode } from "jwt-decode";
@@ -14,7 +14,7 @@ export const register = createAsyncThunk(
"auth/register",
async (form, thunkApi) => {
try {
- const res = await axiosInstance.post("/auth/register", form);
+ const res = await networkService.registerUser(form);
return res.data;
} catch (error) {
if (error.response.data) {
@@ -31,7 +31,7 @@ export const register = createAsyncThunk(
export const login = createAsyncThunk("auth/login", async (form, thunkApi) => {
try {
- const res = await axiosInstance.post(`/auth/login`, form);
+ const res = await networkService.loginUser(form);
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -51,16 +51,13 @@ export const update = createAsyncThunk(
const { authToken: token, localData: form } = data;
const user = jwtDecode(token);
try {
- //1.5s delay to show loading spinner
- await new Promise((resolve) => setTimeout(resolve, 1500));
-
const fd = new FormData();
form.firstName && fd.append("firstName", form.firstName);
form.lastName && fd.append("lastName", form.lastName);
form.password && fd.append("password", form.password);
form.newPassword && fd.append("newPassword", form.newPassword);
if (form.file && form.file !== "") {
- const imageResult = await axiosInstance.get(form.file, {
+ const imageResult = await networkService.get(form.file, {
responseType: "blob",
baseURL: "",
});
@@ -69,12 +66,8 @@ export const update = createAsyncThunk(
form.deleteProfileImage &&
fd.append("deleteProfileImage", form.deleteProfileImage);
- const res = await axiosInstance.put(`/auth/user/${user._id}`, fd, {
- headers: {
- Authorization: `Bearer ${token}`,
- "Content-Type": "multipart/form-data",
- },
- });
+ const res = await networkService.updateUser(token, user._id, fd);
+
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -95,9 +88,7 @@ export const deleteUser = createAsyncThunk(
const user = jwtDecode(data);
try {
- const res = await axiosInstance.delete(`/auth/user/${user._id}`, {
- headers: { Authorization: `Bearer ${data}` },
- });
+ const res = await networkService.deleteUser(data, user._id);
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -116,7 +107,7 @@ export const forgotPassword = createAsyncThunk(
"auth/forgotPassword",
async (form, thunkApi) => {
try {
- const res = await axiosInstance.post("/auth/recovery/request", form);
+ const res = await networkService.forgotPassword(form);
return res.data;
} catch (error) {
if (error.response.data) {
@@ -136,13 +127,8 @@ export const setNewPassword = createAsyncThunk(
async (data, thunkApi) => {
const { token, form } = data;
try {
- await axiosInstance.post("/auth/recovery/validate", {
- recoveryToken: token,
- });
- const res = await axiosInstance.post("/auth/recovery/reset", {
- ...form,
- recoveryToken: token,
- });
+ await networkService.validateRecoveryToken(token);
+ const res = await networkService.setNewPassword(token, form);
return res.data;
} catch (error) {
if (error.response.data) {
diff --git a/Client/src/Features/PageSpeedMonitor/pageSpeedMonitorSlice.js b/Client/src/Features/PageSpeedMonitor/pageSpeedMonitorSlice.js
index 6af825a37..22e2b3324 100644
--- a/Client/src/Features/PageSpeedMonitor/pageSpeedMonitorSlice.js
+++ b/Client/src/Features/PageSpeedMonitor/pageSpeedMonitorSlice.js
@@ -1,6 +1,6 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { jwtDecode } from "jwt-decode";
-import axiosInstance from "../../Utils/axiosConfig";
+import { networkService } from "../../main";
const initialState = {
isLoading: false,
monitors: [],
@@ -13,32 +13,7 @@ export const createPageSpeed = createAsyncThunk(
async (data, thunkApi) => {
try {
const { authToken, monitor } = data;
-
- const res = await axiosInstance.post(`/monitors`, monitor, {
- headers: {
- Authorization: `Bearer ${authToken}`,
- "Content-Type": "application/json",
- },
- });
- return res.data;
- } catch (error) {
- if (error.response && error.response.data) {
- return thunkApi.rejectWithValue(error.response.data);
- }
- const payload = {
- status: false,
- msg: error.message ? error.message : "Unknown error",
- };
- return thunkApi.rejectWithValue(payload);
- }
- }
-);
-
-export const getPageSpeedMonitors = createAsyncThunk(
- "pageSpeedMonitors/getPageSpeedMonitors",
- async (token, thunkApi) => {
- try {
- const res = await axiosInstance.get("/monitors");
+ const res = await networkService.createMonitor(authToken, monitor);
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -58,14 +33,16 @@ export const getPageSpeedByUserId = createAsyncThunk(
async (token, thunkApi) => {
const user = jwtDecode(token);
try {
- const res = await axiosInstance.get(
- `/monitors/user/${user._id}?limit=25&type=pagespeed&sortOrder=desc`,
- {
- headers: {
- Authorization: `Bearer ${token}`,
- },
- }
+ const res = await networkService.getMonitorsByUserId(
+ token,
+ user._id,
+ 25,
+ ["pagespeed"],
+ null,
+ "desc",
+ false
);
+
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -91,15 +68,10 @@ export const updatePageSpeed = createAsyncThunk(
interval: monitor.interval,
// notifications: monitor.notifications,
};
- const res = await axiosInstance.put(
- `/monitors/${monitor._id}`,
- updatedFields,
- {
- headers: {
- Authorization: `Bearer ${authToken}`,
- "Content-Type": "application/json",
- },
- }
+ const res = await networkService.updateMonitor(
+ authToken,
+ monitor._id,
+ updatedFields
);
return res.data;
} catch (error) {
@@ -120,12 +92,10 @@ export const deletePageSpeed = createAsyncThunk(
async (data, thunkApi) => {
try {
const { authToken, monitor } = data;
- const res = await axiosInstance.delete(`/monitors/${monitor._id}`, {
- headers: {
- Authorization: `Bearer ${authToken}`,
- "Content-Type": "application/json",
- },
- });
+ const res = await networkService.deleteMonitorById(
+ authToken,
+ monitor._id
+ );
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -153,25 +123,6 @@ const pageSpeedMonitorSlice = createSlice({
},
extraReducers: (builder) => {
builder
- // *****************************************************
- // All Monitors
- // *****************************************************
- .addCase(getPageSpeedMonitors.pending, (state) => {
- state.isLoading = true;
- })
- .addCase(getPageSpeedMonitors.fulfilled, (state, action) => {
- state.isLoading = false;
- state.success = action.payload.success;
- state.msg = action.payload.msg;
- state.monitors = action.payload.data;
- })
- .addCase(getPageSpeedMonitors.rejected, (state, action) => {
- state.isLoading = false;
- state.success = false;
- state.msg = action.payload
- ? action.payload.msg
- : "Getting montiors failed";
- })
// *****************************************************
// Monitors by userId
// *****************************************************
diff --git a/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js b/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js
index 27d616e1e..9ab7d385b 100644
--- a/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js
+++ b/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js
@@ -1,6 +1,6 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { jwtDecode } from "jwt-decode";
-import axiosInstance from "../../Utils/axiosConfig";
+import { networkService } from "../../main";
const initialState = {
isLoading: false,
monitors: [],
@@ -13,32 +13,7 @@ export const createUptimeMonitor = createAsyncThunk(
async (data, thunkApi) => {
try {
const { authToken, monitor } = data;
-
- const res = await axiosInstance.post(`/monitors`, monitor, {
- headers: {
- Authorization: `Bearer ${authToken}`,
- "Content-Type": "application/json",
- },
- });
- return res.data;
- } catch (error) {
- if (error.response && error.response.data) {
- return thunkApi.rejectWithValue(error.response.data);
- }
- const payload = {
- status: false,
- msg: error.message ? error.message : "Unknown error",
- };
- return thunkApi.rejectWithValue(payload);
- }
- }
-);
-
-export const getUptimeMonitors = createAsyncThunk(
- "monitors/getMonitors",
- async (token, thunkApi) => {
- try {
- const res = await axiosInstance.get("/monitors");
+ const res = await networkService.createMonitor(authToken, monitor);
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -58,13 +33,14 @@ export const getUptimeMonitorsByUserId = createAsyncThunk(
async (token, thunkApi) => {
const user = jwtDecode(token);
try {
- const res = await axiosInstance.get(
- `/monitors/user/${user._id}?limit=25&type=http&type=ping&sortOrder=desc&normalize=true`,
- {
- headers: {
- Authorization: `Bearer ${token}`,
- },
- }
+ const res = await networkService.getMonitorsByUserId(
+ token,
+ user._id,
+ 25,
+ ["http", "ping"],
+ null,
+ "desc",
+ true
);
return res.data;
} catch (error) {
@@ -91,15 +67,10 @@ export const updateUptimeMonitor = createAsyncThunk(
interval: monitor.interval,
notifications: monitor.notifications,
};
- const res = await axiosInstance.put(
- `/monitors/${monitor._id}`,
- updatedFields,
- {
- headers: {
- Authorization: `Bearer ${authToken}`,
- "Content-Type": "application/json",
- },
- }
+ const res = await networkService.updateMonitor(
+ authToken,
+ monitor._id,
+ updatedFields
);
return res.data;
} catch (error) {
@@ -120,12 +91,10 @@ export const deleteUptimeMonitor = createAsyncThunk(
async (data, thunkApi) => {
try {
const { authToken, monitor } = data;
- const res = await axiosInstance.delete(`/monitors/${monitor._id}`, {
- headers: {
- Authorization: `Bearer ${authToken}`,
- "Content-Type": "application/json",
- },
- });
+ const res = await networkService.deleteMonitorById(
+ authToken,
+ monitor._id
+ );
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -153,25 +122,6 @@ const uptimeMonitorsSlice = createSlice({
},
extraReducers: (builder) => {
builder
- // *****************************************************
- // All Monitors
- // *****************************************************
- .addCase(getUptimeMonitors.pending, (state) => {
- state.isLoading = true;
- })
- .addCase(getUptimeMonitors.fulfilled, (state, action) => {
- state.isLoading = false;
- state.success = action.payload.success;
- state.msg = action.payload.msg;
- state.monitors = action.payload.data;
- })
- .addCase(getUptimeMonitors.rejected, (state, action) => {
- state.isLoading = false;
- state.success = false;
- state.msg = action.payload
- ? action.payload.msg
- : "Getting uptime monitors failed";
- })
// *****************************************************
// Monitors by userId
// *****************************************************
diff --git a/Client/src/HOC/withAdminCheck.jsx b/Client/src/HOC/withAdminCheck.jsx
index 23ee5dc1f..30a767f36 100644
--- a/Client/src/HOC/withAdminCheck.jsx
+++ b/Client/src/HOC/withAdminCheck.jsx
@@ -1,21 +1,23 @@
import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom";
-import axiosInstance from "../Utils/axiosConfig";
+
+import { logger } from "../Utils/Logger";
+import { networkService } from "../main";
const withAdminCheck = (WrappedComponent) => {
const WithAdminCheck = (props) => {
const navigate = useNavigate();
useEffect(() => {
- axiosInstance
- .get("/auth/users/admin")
+ networkService
+ .doesAdminExist()
.then((response) => {
if (response.data.data === true) {
navigate("/login");
}
})
.catch((error) => {
- console.log(error);
+ logger.error(error);
});
}, [navigate]);
return ;
diff --git a/Client/src/Pages/Auth/Login.jsx b/Client/src/Pages/Auth/Login.jsx
index a928347b0..79e8d7e12 100644
--- a/Client/src/Pages/Auth/Login.jsx
+++ b/Client/src/Pages/Auth/Login.jsx
@@ -7,14 +7,14 @@ import { login } from "../../Features/Auth/authSlice";
import { useDispatch, useSelector } from "react-redux";
import { createToast } from "../../Utils/toastUtils";
import Button from "../../Components/Button";
-import axiosInstance from "../../Utils/axiosConfig";
+import { networkService } from "../../main";
import Field from "../../Components/Inputs/Field";
import background from "../../assets/Images/background_pattern_decorative.png";
import Logo from "../../assets/icons/bwu-icon.svg?react";
import Mail from "../../assets/icons/mail.svg?react";
import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded";
import PropTypes from "prop-types";
-
+import { logger } from "../../Utils/Logger";
import "./index.css";
/**
@@ -276,15 +276,15 @@ const Login = () => {
navigate("/monitors");
return;
}
- axiosInstance
- .get("/auth/users/admin")
+ networkService
+ .doesAdminExist()
.then((response) => {
if (response.data.data === false) {
navigate("/register");
}
})
.catch((error) => {
- console.log(error);
+ logger.error(error);
});
}, [authToken, navigate]);
diff --git a/Client/src/Pages/Auth/Register/Register.jsx b/Client/src/Pages/Auth/Register/Register.jsx
index 30b439f16..225fb16f0 100644
--- a/Client/src/Pages/Auth/Register/Register.jsx
+++ b/Client/src/Pages/Auth/Register/Register.jsx
@@ -15,8 +15,9 @@ import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded";
import Check from "../../../Components/Check/Check";
import Button from "../../../Components/Button";
import Field from "../../../Components/Inputs/Field";
-import axiosInstance from "../../../Utils/axiosConfig";
+import { networkService } from "../../../main";
import "../index.css";
+import { logger } from "../../../Utils/Logger";
/**
* Displays the initial landing page.
@@ -397,14 +398,11 @@ const Register = ({ isAdmin }) => {
const fetchInvite = async () => {
if (token !== undefined) {
try {
- const res = await axiosInstance.post(`/auth/invite/verify`, {
- token,
- });
+ const res = await networkService.verifyInvitationToken(token);
const { role, email } = res.data.data;
- console.log(role);
setForm({ ...form, email, role });
} catch (error) {
- console.log(error);
+ logger.error(error);
}
}
};
diff --git a/Client/src/Pages/Incidents/IncidentTable/index.jsx b/Client/src/Pages/Incidents/IncidentTable/index.jsx
index 44a30decc..705daa70c 100644
--- a/Client/src/Pages/Incidents/IncidentTable/index.jsx
+++ b/Client/src/Pages/Incidents/IncidentTable/index.jsx
@@ -18,8 +18,9 @@ import ArrowForwardRoundedIcon from "@mui/icons-material/ArrowForwardRounded";
import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
-import axiosInstance from "../../../Utils/axiosConfig";
+import { networkService } from "../../../main";
import { StatusLabel } from "../../../Components/Label";
+import { logger } from "../../../Utils/Logger";
const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
const { authToken, user } = useSelector((state) => state.auth);
@@ -43,21 +44,34 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
return;
}
try {
- let url = `/checks/${selectedMonitor}?sortOrder=desc&filter=${filter}&page=${paginationController.page}&rowsPerPage=${paginationController.rowsPerPage}`;
-
+ let res;
if (selectedMonitor === "0") {
- url = `/checks/user/${user._id}?sortOrder=desc&filter=${filter}&page=${paginationController.page}&rowsPerPage=${paginationController.rowsPerPage}`;
+ res = await networkService.getChecksByUser(
+ authToken,
+ user._id,
+ "desc",
+ null,
+ null,
+ filter,
+ paginationController.page,
+ paginationController.rowsPerPage
+ );
+ } else {
+ res = await networkService.getChecksByMonitor(
+ authToken,
+ selectedMonitor,
+ "desc",
+ null,
+ null,
+ filter,
+ paginationController.page,
+ paginationController.rowsPerPage
+ );
}
-
- const res = await axiosInstance.get(url, {
- headers: {
- Authorization: `Bearer ${authToken}`,
- },
- });
setChecks(res.data.data.checks);
setChecksCount(res.data.data.checksCount);
} catch (error) {
- console.log(error);
+ logger.error(error);
}
};
fetchPage();
@@ -72,7 +86,6 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => {
]);
const handlePageChange = (_, newPage) => {
- console.log(newPage);
setPaginationController({
...paginationController,
page: newPage - 1, // 0-indexed
diff --git a/Client/src/Pages/Incidents/index.jsx b/Client/src/Pages/Incidents/index.jsx
index f9d53f7c0..34768f7f9 100644
--- a/Client/src/Pages/Incidents/index.jsx
+++ b/Client/src/Pages/Incidents/index.jsx
@@ -2,7 +2,7 @@ import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import { ButtonGroup, Stack, Skeleton, Typography } from "@mui/material";
import Button from "../../Components/Button";
-import axiosInstance from "../../Utils/axiosConfig";
+import { networkService } from "../../main";
import { useTheme } from "@emotion/react";
import Select from "../../Components/Inputs/Select";
import IncidentTable from "./IncidentTable";
@@ -48,13 +48,14 @@ const Incidents = () => {
useEffect(() => {
const fetchMonitors = async () => {
setLoading(true);
- const res = await axiosInstance.get(
- `/monitors/user/${authState.user._id}?status=false&limit=1`,
- {
- headers: {
- Authorization: `Bearer ${authState.authToken}`,
- },
- }
+ const res = await networkService.getMonitorsByUserId(
+ authState.authToken,
+ authState.user._id,
+ 1,
+ null,
+ null,
+ null,
+ null
);
// Reduce to a lookup object for 0(1) lookup
diff --git a/Client/src/Pages/Monitors/Configure/index.jsx b/Client/src/Pages/Monitors/Configure/index.jsx
index 5a64f7167..6b809433d 100644
--- a/Client/src/Pages/Monitors/Configure/index.jsx
+++ b/Client/src/Pages/Monitors/Configure/index.jsx
@@ -19,6 +19,7 @@ import {
import Checkbox from "../../../Components/Inputs/Checkbox";
import Breadcrumbs from "../../../Components/Breadcrumbs";
import "./index.css";
+import { logger } from "../../../Utils/Logger";
/**
* Parses a URL string and returns a URL object.
@@ -108,7 +109,7 @@ const Configure = () => {
useEffect(() => {
const data = monitors.find((monitor) => monitor._id === monitorId);
if (!data) {
- console.error("Error fetching monitor of id: " + monitorId);
+ logger.error("Error fetching monitor of id: " + monitorId);
navigate("/not-found", { replace: true });
}
setMonitor({
@@ -337,7 +338,7 @@ const Configure = () => {
label="Notify via SMS (coming soon)"
isChecked={false}
value=""
- onChange={() => console.log("disabled")}
+ onChange={() => logger.warn("disabled")}
isDisabled={true}
/>
{
label="Also notify via email to multiple addresses (coming soon)"
isChecked={false}
value=""
- onChange={() => console.log("disabled")}
+ onChange={() => logger.warn("disabled")}
isDisabled={true}
/>
{monitor?.notifications?.some(
@@ -368,7 +369,7 @@ const Configure = () => {
type="text"
placeholder="name@gmail.com"
value=""
- onChange={() => console.log("disabled")}
+ onChange={() => logger.warn("disabled")}
/>
You can separate multiple emails with a comma
diff --git a/Client/src/Pages/Monitors/CreateMonitor/index.jsx b/Client/src/Pages/Monitors/CreateMonitor/index.jsx
index d0eafb476..442558f8e 100644
--- a/Client/src/Pages/Monitors/CreateMonitor/index.jsx
+++ b/Client/src/Pages/Monitors/CreateMonitor/index.jsx
@@ -13,6 +13,7 @@ import Select from "../../../Components/Inputs/Select";
import Checkbox from "../../../Components/Inputs/Checkbox";
import { createToast } from "../../../Utils/toastUtils";
import Breadcrumbs from "../../../Components/Breadcrumbs";
+import { logger } from "../../../Utils/Logger";
const CreateMonitor = () => {
const MS_PER_MINUTE = 60000;
@@ -267,7 +268,7 @@ const CreateMonitor = () => {
label="Notify via SMS (coming soon)"
isChecked={false}
value=""
- onChange={() => console.log("disabled")}
+ onChange={() => logger.warn("disabled")}
isDisabled={true}
/>
{
label="Also notify via email to multiple addresses (coming soon)"
isChecked={false}
value=""
- onChange={() => console.log("disabled")}
+ onChange={() => logger.warn("disabled")}
isDisabled={true}
/>
{monitor.notifications.some(
@@ -296,7 +297,7 @@ const CreateMonitor = () => {
type="text"
placeholder="name@gmail.com"
value=""
- onChange={() => console.log("disabled")}
+ onChange={() => logger.warn("disabled")}
/>
You can separate multiple emails with a comma
diff --git a/Client/src/Pages/Monitors/Details/PaginationTable/index.jsx b/Client/src/Pages/Monitors/Details/PaginationTable/index.jsx
index 28a668977..da4a0cb1e 100644
--- a/Client/src/Pages/Monitors/Details/PaginationTable/index.jsx
+++ b/Client/src/Pages/Monitors/Details/PaginationTable/index.jsx
@@ -13,10 +13,11 @@ import {
import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
-import axiosInstance from "../../../../Utils/axiosConfig";
+import { networkService } from "../../../../main";
import { StatusLabel } from "../../../../Components/Label";
import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded";
import ArrowForwardRoundedIcon from "@mui/icons-material/ArrowForwardRounded";
+import { logger } from "../../../../Utils/Logger";
const PaginationTable = ({ monitorId, dateRange }) => {
const { authToken } = useSelector((state) => state.auth);
@@ -37,18 +38,20 @@ const PaginationTable = ({ monitorId, dateRange }) => {
useEffect(() => {
const fetchPage = async () => {
try {
- const res = await axiosInstance.get(
- `/checks/${monitorId}?sortOrder=desc&dateRange=${dateRange}&page=${paginationController.page}&rowsPerPage=${paginationController.rowsPerPage}`,
- {
- headers: {
- Authorization: `Bearer ${authToken}`,
- },
- }
+ const res = await networkService.getChecksByMonitor(
+ authToken,
+ monitorId,
+ "desc",
+ null,
+ dateRange,
+ null,
+ paginationController.page,
+ paginationController.rowsPerPage
);
setChecks(res.data.data.checks);
setChecksCount(res.data.data.checksCount);
} catch (error) {
- console.log(error);
+ logger.error(error);
}
};
fetchPage();
diff --git a/Client/src/Pages/Monitors/Details/index.jsx b/Client/src/Pages/Monitors/Details/index.jsx
index 519f2991f..a931ac827 100644
--- a/Client/src/Pages/Monitors/Details/index.jsx
+++ b/Client/src/Pages/Monitors/Details/index.jsx
@@ -3,7 +3,7 @@ import PropTypes from "prop-types";
import { Box, Skeleton, Stack, Typography, useTheme } from "@mui/material";
import { useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
-import axiosInstance from "../../../Utils/axiosConfig";
+import { networkService } from "../../../main";
import MonitorDetailsAreaChart from "../../../Components/Charts/MonitorDetailsAreaChart";
import ButtonGroup from "@mui/material/ButtonGroup";
import Button from "../../../Components/Button";
@@ -18,6 +18,7 @@ import {
import "./index.css";
import MonitorDetails60MinChart from "../../../Components/Charts/MonitorDetails60MinChart";
import Breadcrumbs from "../../../Components/Breadcrumbs";
+import { logger } from "../../../Utils/Logger";
const StatBox = ({ title, value }) => {
return (
@@ -121,17 +122,18 @@ const DetailsPage = () => {
const fetchMonitor = useCallback(async () => {
try {
- const res = await axiosInstance.get(
- `/monitors/stats/${monitorId}?dateRange=${dateRange}&numToDisplay=50&normalize=true`,
- {
- headers: {
- Authorization: `Bearer ${authToken}`,
- },
- }
+ const res = await networkService.getStatsByMonitorId(
+ authToken,
+ monitorId,
+ null,
+ null,
+ dateRange,
+ 50,
+ true
);
setMonitor(res.data.data);
} catch (error) {
- console.error("Error fetching monitor of id: " + monitorId);
+ logger.error(error);
navigate("/not-found", { replace: true });
}
}, [authToken, monitorId, navigate, dateRange]);
@@ -142,13 +144,9 @@ const DetailsPage = () => {
useEffect(() => {
const fetchCertificate = async () => {
- const res = await axiosInstance.get(
- `/monitors/certificate/${monitorId}`,
- {
- headers: {
- Authorization: `Bearer ${authToken}`,
- },
- }
+ const res = await networkService.getCertificateExpiry(
+ authToken,
+ monitorId
);
setCertificateExpiry(res.data.data.certificateDate);
};
diff --git a/Client/src/Pages/Monitors/index.jsx b/Client/src/Pages/Monitors/index.jsx
index 1b541c72b..c33cf16dc 100644
--- a/Client/src/Pages/Monitors/index.jsx
+++ b/Client/src/Pages/Monitors/index.jsx
@@ -28,6 +28,7 @@ import {
import Settings from "../../assets/icons/settings-bold.svg?react";
import PropTypes from "prop-types";
+import { logger } from "../../Utils/Logger";
const ActionsMenu = ({ monitor }) => {
const [anchorEl, setAnchorEl] = useState(null);
@@ -36,7 +37,6 @@ const ActionsMenu = ({ monitor }) => {
const dispatch = useDispatch();
const theme = useTheme();
const authState = useSelector((state) => state.auth);
-
const handleRemove = async (event) => {
event.preventDefault();
event.stopPropagation();
diff --git a/Client/src/Pages/NotFound/index.jsx b/Client/src/Pages/NotFound/index.jsx
index 68120b0a3..ef4b37839 100644
--- a/Client/src/Pages/NotFound/index.jsx
+++ b/Client/src/Pages/NotFound/index.jsx
@@ -33,7 +33,6 @@ const DefaultValue = {
*/
const NotFound = ({ title = DefaultValue.title, desc = DefaultValue.desc }) => {
const navigate = useNavigate();
- console.log("NOT FOUND");
return (
diff --git a/Client/src/Pages/PageSpeed/Configure/index.jsx b/Client/src/Pages/PageSpeed/Configure/index.jsx
index ed91a2f3e..1cb164fcf 100644
--- a/Client/src/Pages/PageSpeed/Configure/index.jsx
+++ b/Client/src/Pages/PageSpeed/Configure/index.jsx
@@ -18,6 +18,7 @@ import PauseCircleOutlineIcon from "@mui/icons-material/PauseCircleOutline";
import GreenCheck from "../../../assets/icons/checkbox-green.svg?react";
import RedCheck from "../../../assets/icons/checkbox-red.svg?react";
import Breadcrumbs from "../../../Components/Breadcrumbs";
+import { logger } from "../../../Utils/Logger";
import "./index.css";
@@ -92,7 +93,7 @@ const PageSpeedConfigure = () => {
useEffect(() => {
const data = monitors.find((monitor) => monitor._id === monitorId);
if (!data) {
- console.error("Error fetching pagespeed monitor of id: " + monitorId);
+ logger.error("Error fetching pagespeed monitor of id: " + monitorId);
navigate("/not-found", { replace: true });
}
setMonitor({
@@ -278,7 +279,7 @@ const PageSpeedConfigure = () => {
id="notify-emails-list"
placeholder="notifications@gmail.com"
value=""
- onChange={() => console.log("disabled")}
+ onChange={() => logger.warn("disabled")}
error=""
/>
diff --git a/Client/src/Pages/PageSpeed/CreatePageSpeed/index.jsx b/Client/src/Pages/PageSpeed/CreatePageSpeed/index.jsx
index 6b9e6dbde..c707db319 100644
--- a/Client/src/Pages/PageSpeed/CreatePageSpeed/index.jsx
+++ b/Client/src/Pages/PageSpeed/CreatePageSpeed/index.jsx
@@ -12,6 +12,7 @@ import { createToast } from "../../../Utils/toastUtils";
import { createPageSpeed } from "../../../Features/PageSpeedMonitor/pageSpeedMonitorSlice";
import Breadcrumbs from "../../../Components/Breadcrumbs";
import "./index.css";
+import { logger } from "../../../Utils/Logger";
const CreatePageSpeed = () => {
const theme = useTheme();
@@ -175,7 +176,7 @@ const CreatePageSpeed = () => {
id="notify-emails-list"
placeholder="notifications@gmail.com"
value=""
- onChange={() => console.log("disabled")}
+ onChange={() => logger.warn("disabled")}
error=""
/>
diff --git a/Client/src/Pages/PageSpeed/Details/index.jsx b/Client/src/Pages/PageSpeed/Details/index.jsx
index 42ef4421e..41f5892f2 100644
--- a/Client/src/Pages/PageSpeed/Details/index.jsx
+++ b/Client/src/Pages/PageSpeed/Details/index.jsx
@@ -9,7 +9,7 @@ import {
formatDuration,
formatDurationRounded,
} from "../../../Utils/timeUtils";
-import axiosInstance from "../../../Utils/axiosConfig";
+import { networkService } from "../../../main";
import Button from "../../../Components/Button";
import SettingsIcon from "../../../assets/icons/settings-bold.svg?react";
import LastCheckedIcon from "../../../assets/icons/calendar-check.svg?react";
@@ -21,6 +21,7 @@ import PageSpeedLineChart from "../../../Components/Charts/PagespeedLineChart";
import Breadcrumbs from "../../../Components/Breadcrumbs";
import "./index.css";
import PropTypes from "prop-types";
+import { logger } from "../../../Utils/Logger";
const StatBox = ({ icon, title, value }) => {
const theme = useTheme();
@@ -198,19 +199,19 @@ const PageSpeedDetails = () => {
useEffect(() => {
const fetchMonitor = async () => {
try {
- const res = await axiosInstance.get(
- `/monitors/stats/${monitorId}?sortOrder=desc&limit=50`,
- {
- headers: {
- Authorization: `Bearer ${authToken}`,
- },
- }
+ const res = await networkService.getStatsByMonitorId(
+ authToken,
+ monitorId,
+ "desc",
+ 50,
+ null,
+ null,
+ null
);
-
setMonitor(res?.data?.data ?? {});
setAudits(res?.data?.data?.checks?.[0]?.audits ?? []);
} catch (error) {
- console.log(error);
+ logger.error(logger);
navigate("/not-found", { replace: true });
}
};
diff --git a/Client/src/Pages/Settings/index.jsx b/Client/src/Pages/Settings/index.jsx
index 3ee029675..2b6f40682 100644
--- a/Client/src/Pages/Settings/index.jsx
+++ b/Client/src/Pages/Settings/index.jsx
@@ -4,7 +4,7 @@ import Button from "../../Components/Button";
import Field from "../../Components/Inputs/Field";
import Link from "../../Components/Link";
import Select from "../../Components/Inputs/Select";
-
+import { logger } from "../../Utils/Logger";
import "./index.css";
const Settings = () => {
@@ -40,14 +40,14 @@ const Settings = () => {
id="display-timezone"
label="Display timezone"
value="est"
- onChange={() => console.log("disabled")}
+ onChange={() => logger.warn("disabled")}
items={[{ _id: "est", name: "America / Toronto" }]}
/>
@@ -74,7 +74,7 @@ const Settings = () => {
optionalLabel="0 for infinite"
placeholder="90"
value=""
- onChange={() => console.log("Disabled")}
+ onChange={() => logger.warn("Disabled")}
/>
Clear all stats. This is irreversible.
diff --git a/Client/src/Utils/Logger.js b/Client/src/Utils/Logger.js
new file mode 100644
index 000000000..02fffd6be
--- /dev/null
+++ b/Client/src/Utils/Logger.js
@@ -0,0 +1,30 @@
+const LOG_LEVEL = import.meta.env.VITE_APP_LOG_LEVEL;
+class Logger {
+ constructor(logLevel) {
+ const NO_OP = () => {};
+
+ if (logLevel === "none") {
+ this.error = NO_OP;
+ this.warn = NO_OP;
+ this.log = NO_OP;
+ return;
+ }
+
+ this.error = console.error.bind(console);
+
+ if (logLevel === "error") {
+ this.warn = NO_OP;
+ this.log = NO_OP;
+ return;
+ }
+ this.warn = console.warn.bind(console);
+
+ if (logLevel === "warn") {
+ this.log = NO_OP;
+ return;
+ }
+ this.log = console.log.bind(console);
+ }
+}
+
+export const logger = new Logger(LOG_LEVEL);
diff --git a/Client/src/Utils/NetworkService.js b/Client/src/Utils/NetworkService.js
new file mode 100644
index 000000000..21f1c1845
--- /dev/null
+++ b/Client/src/Utils/NetworkService.js
@@ -0,0 +1,434 @@
+import axios from "axios";
+import { clearAuthState } from "../Features/Auth/authSlice";
+const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL;
+
+class NetworkService {
+ constructor(store) {
+ this.store = store;
+ this.axiosInstance = axios.create({ baseURL: BASE_URL });
+ this.axiosInstance.interceptors.response.use(
+ (response) => response,
+ (error) => {
+ console.error(error);
+ if (error.response && error.response.status === 401) {
+ console.log("Invalid token revoked");
+ networkService;
+ }
+ return Promise.reject(error);
+ }
+ );
+ }
+
+ /**
+ *
+ * ************************************
+ * Create a new monitor
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {Object} monitor - The monitor object to be sent in the request body.
+ * @returns {Promise} The response from the axios POST request.
+ */
+ async createMonitor(authToken, monitor) {
+ return this.axiosInstance.post(`/monitors`, monitor, {
+ headers: {
+ Authorization: `Bearer ${authToken}`,
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ /**
+ * ************************************
+ * Get all uptime monitors for a user
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {string} userId - The ID of the user whose monitors are to be retrieved.
+ * @param {number} [limit] - The maximum number of monitors to retrieve.
+ * @param {Array} [types] - The types of monitors to retrieve.
+ * @param {string} [status] - The status of the monitors to retrieve.
+ * @param {string} [sortOrder] - The order in which to sort the retrieved monitors.
+ * @param {boolean} [normalize] - Whether to normalize the retrieved monitors.
+ * @returns {Promise} The response from the axios GET request.
+ */
+ async getMonitorsByUserId(
+ authToken,
+ userId,
+ limit,
+ types,
+ status,
+ sortOrder,
+ normalize
+ ) {
+ const params = new URLSearchParams();
+
+ if (limit) params.append("limit", limit);
+ if (types) {
+ types.forEach((type) => {
+ params.append("type", type);
+ });
+ }
+ if (status) params.append("status", status);
+ if (sortOrder) params.append("sortOrder", sortOrder);
+ if (normalize) params.append("normalize", normalize);
+
+ return this.axiosInstance.get(
+ `/monitors/user/${userId}?${params.toString()}`,
+ {
+ headers: {
+ Authorization: `Bearer ${authToken}`,
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ }
+
+ /**
+ * ************************************
+ * Get stats for a monitor
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {string} monitorId - The ID of the monitor whose statistics are to be retrieved.
+ * @param {string} [sortOrder] - The order in which to sort the retrieved statistics.
+ * @param {number} [limit] - The maximum number of statistics to retrieve.
+ * @param {string} [dateRange] - The date range for which to retrieve statistics.
+ * @param {number} [numToDisplay] - The number of statistics to display.
+ * @param {boolean} [normalize] - Whether to normalize the retrieved statistics.
+ * @returns {Promise} The response from the axios GET request.
+ */
+ async getStatsByMonitorId(
+ authToken,
+ monitorId,
+ sortOrder,
+ limit,
+ dateRange,
+ numToDisplay,
+ normalize
+ ) {
+ const params = new URLSearchParams();
+ if (sortOrder) params.append("sortOrder", sortOrder);
+ if (limit) params.append("limit", limit);
+ if (dateRange) params.append("dateRange", dateRange);
+ if (numToDisplay) params.append("numToDisplay", numToDisplay);
+ if (normalize) params.append("normalize", normalize);
+
+ return this.axiosInstance.get(
+ `/monitors/stats/${monitorId}?${params.toString()}`,
+ {
+ headers: {
+ Authorization: `Bearer ${authToken}`,
+ },
+ }
+ );
+ }
+
+ /**
+ * ************************************
+ * Updates a single monitor
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {string} monitorId - The ID of the monitor to be updated.
+ * @param {Object} updatedFields - The fields to be updated for the monitor.
+ * @returns {Promise} The response from the axios PUT request.
+ */
+ async updateMonitor(authToken, monitorId, updatedFields) {
+ return this.axiosInstance.put(`/monitors/${monitorId}`, updatedFields, {
+ headers: {
+ Authorization: `Bearer ${authToken}`,
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ /**
+ * ************************************
+ * Deletes a single monitor by its ID
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {string} monitorId - The ID of the monitor to be deleted.
+ * @returns {Promise} The response from the axios DELETE request.
+ */
+ async deleteMonitorById(authToken, monitorId) {
+ return this.axiosInstance.delete(`/monitors/${monitorId}`, {
+ headers: {
+ Authorization: `Bearer ${authToken}`,
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ /**
+ * ************************************
+ * Gets the certificate expiry for a monitor
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {string} monitorId - The ID of the monitor whose certificate expiry is to be retrieved.
+ * @returns {Promise} The response from the axios GET request.
+ *
+ */
+ async getCertificateExpiry(authToken, monitorId) {
+ return this.axiosInstance.get(`/monitors/certificate/${monitorId}`, {
+ headers: {
+ Authorization: `Bearer ${authToken}`,
+ },
+ });
+ }
+
+ /**
+ * ************************************
+ * Registers a new user
+ * ************************************
+ *
+ * @async
+ * @param {Object} form - The form data for the new user to be registered.
+ * @returns {Promise} The response from the axios POST request.
+ */
+ async registerUser(form) {
+ return this.axiosInstance.post(`/auth/register`, form);
+ }
+
+ /**
+ * ************************************
+ * Logs in a user
+ * ************************************
+ *
+ * @async
+ * @param {Object} form - The form data for the user to be logged in.
+ * @returns {Promise} The response from the axios POST request.
+ *
+ */
+ async loginUser(form) {
+ return this.axiosInstance.post(`/auth/login`, form);
+ }
+
+ /**
+ * ************************************
+ * Updates a user
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {string} userId - The ID of the user to be updated.
+ * @param {Object} form - The form data for the user to be updated.
+ * @returns {Promise} The response from the axios PUT request.
+ *
+ */
+ async updateUser(authToken, userId, form) {
+ return this.axiosInstance.put(`/auth/user/${userId}`, form, {
+ headers: {
+ Authorization: `Bearer ${authToken}`,
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
+ /**
+ * ************************************
+ * Forgot password request
+ * ************************************
+ *
+ * @async
+ * @param {Object} form - The form data for the password recovery request.
+ * @returns {Promise} The response from the axios POST request.
+ *
+ */
+ async forgotPassword(form) {
+ return this.axiosInstance.post(`/auth/recovery/request`, form);
+ }
+
+ /**
+ * ************************************
+ * Validates a recovery token
+ * ************************************
+ *
+ * @async
+ * @param {string} recoveryToken - The recovery token to be validated.
+ * @returns {Promise} The response from the axios POST request.
+ *
+ */
+ async validateRecoveryToken(recoveryToken) {
+ return this.axiosInstance.post("/auth/recovery/validate", {
+ recoveryToken,
+ });
+ }
+
+ /**
+ * ************************************
+ * Requests password recovery
+ * ************************************
+ *
+ * @async
+ * @param {Object} form - The form data for the password recovery request.
+ * @returns {Promise} The response from the axios POST request.
+ *
+ */
+ async setNewPassword(recoveryToken, form) {
+ return this.axiosInstance.post("/auth/recovery/reset", {
+ ...form,
+ recoveryToken,
+ });
+ }
+
+ /**
+ * ************************************
+ * Checks if an admin user exists
+ * ************************************
+ *
+ * @async
+ * @returns {Promise} The response from the axios GET request.
+ *
+ */
+ async doesAdminExist() {
+ return this.axiosInstance.get("/auth/users/admin");
+ }
+
+ /**
+ * ************************************
+ * Get all users
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @returns {Promise} The response from the axios GET request.
+ *
+ */
+ async getAllUsers(authToken) {
+ return this.axiosInstance.get("/auth/users", {
+ headers: { Authorization: `Bearer ${authToken}` },
+ });
+ }
+
+ /**
+ * ************************************
+ * Requests an invitation token
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {string} email - The email of the user to be invited.
+ * @param {string} role - The role of the user to be invited.
+ * @returns {Promise} The response from the axios POST request.
+ *
+ */
+ async requestInvitationToken(authToken, email, role) {
+ return this.axiosInstance.post(
+ `/auth/invite`,
+ { email, role },
+ {
+ headers: { Authorization: `Bearer ${authToken}` },
+ }
+ );
+ }
+
+ /**
+ * ************************************
+ * Verifies an invitation token
+ * ************************************
+ *
+ * @async
+ * @param {string} token - The invitation token to be verified.
+ * @returns {Promise} The response from the axios POST request.
+ *
+ */
+ async verifyInvitationToken(token) {
+ return this.axiosInstance.post(`/auth/invite/verify`, {
+ token,
+ });
+ }
+
+ /**
+ * ************************************
+ * Get all checks for a given monitor
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {string} monitorId - The ID of the monitor.
+ * @param {string} sortOrder - The order in which to sort the checks.
+ * @param {number} limit - The maximum number of checks to retrieve.
+ * @param {string} dateRange - The range of dates for which to retrieve checks.
+ * @param {string} filter - The filter to apply to the checks.
+ * @param {number} page - The page number to retrieve in a paginated list.
+ * @param {number} rowsPerPage - The number of rows per page in a paginated list.
+ * @returns {Promise} The response from the axios GET request.
+ *
+ */
+
+ async getChecksByMonitor(
+ authToken,
+ monitorId,
+ sortOrder,
+ limit,
+ dateRange,
+ filter,
+ page,
+ rowsPerPage
+ ) {
+ const params = new URLSearchParams();
+ if (sortOrder) params.append("sortOrder", sortOrder);
+ if (limit) params.append("limit", limit);
+ if (dateRange) params.append("dateRange", dateRange);
+ if (filter) params.append("filter", filter);
+ if (page) params.append("page", page);
+ if (rowsPerPage) params.append("rowsPerPage", rowsPerPage);
+
+ return this.axiosInstance.get(`/checks/${monitorId}?${params.toString()}`, {
+ headers: { Authorization: `Bearer ${authToken}` },
+ });
+ }
+
+ /**
+ * ************************************
+ * Get all checks for a given user
+ * ************************************
+ *
+ * @async
+ * @param {string} authToken - The authorization token to be used in the request header.
+ * @param {string} userId - The ID of the user.
+ * @param {string} sortOrder - The order in which to sort the checks.
+ * @param {number} limit - The maximum number of checks to retrieve.
+ * @param {string} dateRange - The range of dates for which to retrieve checks.
+ * @param {string} filter - The filter to apply to the checks.
+ * @param {number} page - The page number to retrieve in a paginated list.
+ * @param {number} rowsPerPage - The number of rows per page in a paginated list.
+ * @returns {Promise} The response from the axios GET request.
+ *
+ */
+ async getChecksByUser(
+ authToken,
+ userId,
+ sortOrder,
+ limit,
+ dateRange,
+ filter,
+ page,
+ rowsPerPage
+ ) {
+ const params = new URLSearchParams();
+ if (sortOrder) params.append("sortOrder", sortOrder);
+ if (limit) params.append("limit", limit);
+ if (dateRange) params.append("dateRange", dateRange);
+ if (filter) params.append("filter", filter);
+ if (page) params.append("page", page);
+ if (rowsPerPage) params.append("rowsPerPage", rowsPerPage);
+ return this.axiosInstance.get(
+ `/checks/user/${userId}?${params.toString()}`,
+ {
+ headers: { Authorization: `Bearer ${authToken}` },
+ }
+ );
+ }
+}
+
+export default NetworkService;
diff --git a/Client/src/Utils/axiosConfig.js b/Client/src/Utils/axiosConfig.js
deleted file mode 100644
index 8d3040028..000000000
--- a/Client/src/Utils/axiosConfig.js
+++ /dev/null
@@ -1,27 +0,0 @@
-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 f9fa3d640..00cec7d14 100644
--- a/Client/src/main.jsx
+++ b/Client/src/main.jsx
@@ -8,10 +8,8 @@ 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);
-
+import NetworkService from "./Utils/NetworkService.js";
+export const networkService = new NetworkService(store);
ReactDOM.createRoot(document.getElementById("root")).render(
diff --git a/README.md b/README.md
index 0a26a67b4..adb9bc68f 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ BlueWave Uptime is an open source server monitoring application used to track th
- [x] Ping monitoring
- [x] Incidents at a glance
- [x] Page speed monitoring
-- [x] E-mail notifications
+- [x] E-mail notifications
- [ ] Scheduled maintenance (in the works)
**Roadmap (short term):**
@@ -62,8 +62,7 @@ Made with [contrib.rocks](https://contrib.rocks).
[](https://star-history.com/#bluewave-labs/bluewave-uptime&Date)
-
-Also check other developer and contributor-friendly projects of BlueWave:
+Also check other developer and contributor-friendly projects of BlueWave:
- [BlueWave HRM](https://github.com/bluewave-labs/bluewave-hrm)
- [BlueWave Onboarding](https://github.com/bluewave-labs/bluewave-onboarding)
@@ -191,6 +190,7 @@ SYSTEM_EMAIL_PASSWORD=
```
VITE_APP_API_BASE_URL="http://localhost:5000/api/v1"
+VITE_APP_API_LOG_LEVEL="debug"
```
4. In the `Docker` directory run `docker compose up` to run the `docker-compose.yaml` file and start all four images.
@@ -211,9 +211,10 @@ That's it, the application is ready to use on port 80.
##### Environmental Variables
-| ENV Variable Name | Required/Optional | Type | Description | Accepted Values |
-| --------------------- | ----------------- | -------- | ------------------ | --------------- |
-| VITE_APP_API_BASE_URL | Required | `string` | Base URL of server | {host}/api/v1 |
+| ENV Variable Name | Required/Optional | Type | Description | Accepted Values |
+| --------------------- | ----------------- | -------- | ------------------ | ---------------------------------- |
+| VITE_APP_API_BASE_URL | Required | `string` | Base URL of server | {host}/api/v1 |
+| VITE_APP_LOG_LEVEL | Optional | `string` | Log level | `"none"`\|`"error"` \| `"warn"` \| |
diff --git a/Server/controllers/authController.js b/Server/controllers/authController.js
index 93c83c6b8..4b5f51121 100644
--- a/Server/controllers/authController.js
+++ b/Server/controllers/authController.js
@@ -450,6 +450,7 @@ const deleteUserController = async (req, res, next) => {
}
// 1. Find all the monitors associated with the user id
+
const monitors = await req.db.getMonitorsByUserId({
params: { userId: _id },
});
@@ -459,6 +460,7 @@ const deleteUserController = async (req, res, next) => {
await Promise.all(
monitors.map(async (monitor) => {
await req.jobQueue.deleteJob(monitor);
+
await req.db.deleteChecks(monitor._id);
await req.db.deleteAlertByMonitorId(monitor._id);
await req.db.deletePageSpeedChecksByMonitorId(monitor._id);
diff --git a/Server/db/mongo/modules/monitorModule.js b/Server/db/mongo/modules/monitorModule.js
index 0fc56c755..4d84700ca 100644
--- a/Server/db/mongo/modules/monitorModule.js
+++ b/Server/db/mongo/modules/monitorModule.js
@@ -294,7 +294,7 @@ const getMonitorById = async (monitorId) => {
*/
const getMonitorsByUserId = async (req, res) => {
try {
- let { limit, type, status, sortOrder, normalize } = req.query;
+ let { limit, type, status, sortOrder, normalize } = req.query || {};
const monitorQuery = { userId: req.params.userId };
if (type !== undefined) {
diff --git a/Server/db/mongo/modules/recoveryModule.js b/Server/db/mongo/modules/recoveryModule.js
index c1cc23b94..b643a1664 100644
--- a/Server/db/mongo/modules/recoveryModule.js
+++ b/Server/db/mongo/modules/recoveryModule.js
@@ -1,3 +1,4 @@
+const UserModel = require("../../../models/user");
const RecoveryToken = require("../../../models/RecoveryToken");
const crypto = require("crypto");
const { errorMessages } = require("../../../utils/messages");
diff --git a/Server/index.js b/Server/index.js
index 2cb941ed4..9a5f1797f 100644
--- a/Server/index.js
+++ b/Server/index.js
@@ -19,7 +19,7 @@ const JobQueue = require("./service/jobQueue");
const NetworkService = require("./service/networkService");
const EmailService = require("./service/emailService");
const PageSpeedService = require("./service/pageSpeedService");
-
+const SERVICE_NAME = "Server";
let cleaningUp = false;
// Need to wrap server setup in a function to handle async nature of JobQueue
diff --git a/Server/routes/checkRoute.js b/Server/routes/checkRoute.js
index 69aa682af..4bba24e79 100644
--- a/Server/routes/checkRoute.js
+++ b/Server/routes/checkRoute.js
@@ -15,12 +15,12 @@ router.get(
checkController.getChecks
);
+router.get("/user/:userId", checkController.getUserChecks);
+
router.delete(
"/:monitorId",
verifyOwnership(Monitor, "monitorId"),
checkController.deleteChecks
);
-router.get("/user/:userId", checkController.getUserChecks);
-
module.exports = router;