@@ -60,7 +57,7 @@ const Register = () => {
diff --git a/Client/src/Pages/SetNewPassword/index.css b/Client/src/Pages/SetNewPassword/index.css
new file mode 100644
index 000000000..183e8d21f
--- /dev/null
+++ b/Client/src/Pages/SetNewPassword/index.css
@@ -0,0 +1,63 @@
+.set-new-password-page {
+ width: var(--env-var-width-1);
+ display: flex;
+ justify-content: center;
+ min-height: var(--env-var-height-1);
+}
+
+.set-new-password-form {
+ width: var(--env-var-width-2);
+ margin: 90px auto;
+}
+
+.set-new-password-form-header {
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+}
+
+.set-new-password-form-gap-large {
+ height: var(--env-var-spacing-3);
+}
+
+.set-new-password-form-gap-medium {
+ height: var(--env-var-spacing-2);
+}
+
+.set-new-password-form-gap-small {
+ height: var(--env-var-spacing-1);
+}
+
+.set-new-password-form-heading {
+ font-size: var(--env-var-font-size-large);
+ color: var(--env-var-color-1);
+ font-weight: 700;
+}
+
+.set-new-password-form-subheading {
+ font-size: var(--env-var-font-size-medium);
+ color: var(--env-var-color-2);
+ font-weight: 600;
+}
+
+.set-new-password-back-button {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+}
+
+.set-new-password-back-button-img {
+ width: var(--env-var-img-width-1);
+ height: var(--env-var-img-width-1);
+ margin-right: 5px;
+ align-items: center;
+}
+
+.set-new-password-back-button-text {
+ height: var(--env-var-img-width-1);
+ font-size: var(--env-var-font-size-medium);
+ color: var(--env-var-color-2);
+ font-weight: 600;
+ align-items: center;
+}
diff --git a/Client/src/Pages/SetNewPassword/index.jsx b/Client/src/Pages/SetNewPassword/index.jsx
new file mode 100644
index 000000000..31e213c10
--- /dev/null
+++ b/Client/src/Pages/SetNewPassword/index.jsx
@@ -0,0 +1,77 @@
+import BackgroundPattern from "../../Components/BackgroundPattern/BackgroundPattern";
+import "./index.css";
+import React from "react";
+import LockIcon from "../../assets/Images/lock-icon.png";
+import PasswordTextField from "../../Components/TextFields/Password/PasswordTextField";
+import Check from "../../Components/Check/Check";
+import Button from "../../Components/Button";
+import LeftArrow from "../../assets/Images/arrow-left.png";
+
+const SetNewPassword = () => {
+ return (
+
+
+
+
+

+
+
Set new password
+
+
+ Your new password must be different to previously used passwords.
+
+
+
+
+
+
+

+
+ Back to log in
+
+
+
+
+ );
+};
+
+export default SetNewPassword;
diff --git a/Client/src/Utils/Theme.js b/Client/src/Utils/Theme.js
index 068e24572..1f4e4de96 100644
--- a/Client/src/Utils/Theme.js
+++ b/Client/src/Utils/Theme.js
@@ -13,10 +13,20 @@ const labelPurple = "#6941C6";
const labelGreen = "#067647";
const labelRed = "#F04438";
-//Section colros
+// Section colors
const sectionBorder = "#D0D5DD";
const sectionBg = "#F8F9F8";
+// Other Colors
+const otherColorsBlackish = "#101828";
+const otherColorsBluishGray = "#344054";
+const otherColorsGraishWhite = "#eaecf0";
+const otherColorsPurple = "#7f56d9";
+const otherColorsWhite = "#fff";
+const otherColorsGraishWhiteLight = "#f2f2f2";
+const otherColorsStrongBlue = "#f2f2f2";
+
+
// Global Font Family
const fontFamilyDefault = '"Roboto", "Helvetica", "Arial", sans-serif';
@@ -51,6 +61,15 @@ const theme = createTheme({
borderColor: sectionBorder,
bgColor: sectionBg,
},
+ otherColors: {
+ blackish: otherColorsBlackish,
+ bluishGray: otherColorsBluishGray,
+ graishWhite: otherColorsGraishWhite,
+ purple: otherColorsPurple,
+ white: otherColorsWhite,
+ graishWhiteLight: otherColorsGraishWhiteLight,
+ strongBlue: otherColorsStrongBlue,
+ },
},
font :{
default: {
diff --git a/Client/src/assets/Images/arrow-left.png b/Client/src/assets/Images/arrow-left.png
new file mode 100644
index 000000000..0bd5b1268
Binary files /dev/null and b/Client/src/assets/Images/arrow-left.png differ
diff --git a/Client/src/assets/Images/email.png b/Client/src/assets/Images/email.png
new file mode 100644
index 000000000..40b1f8232
Binary files /dev/null and b/Client/src/assets/Images/email.png differ
diff --git a/Client/src/assets/Images/key-password.png b/Client/src/assets/Images/key-password.png
new file mode 100644
index 000000000..ed7fa6538
Binary files /dev/null and b/Client/src/assets/Images/key-password.png differ
diff --git a/Client/src/assets/Images/lock-icon.png b/Client/src/assets/Images/lock-icon.png
new file mode 100644
index 000000000..163adad87
Binary files /dev/null and b/Client/src/assets/Images/lock-icon.png differ
diff --git a/Client/src/assets/Images/success-icon.png b/Client/src/assets/Images/success-icon.png
new file mode 100644
index 000000000..43cdbbc2a
Binary files /dev/null and b/Client/src/assets/Images/success-icon.png differ
diff --git a/Client/src/index.css b/Client/src/index.css
index 18aa9a223..b44125b2e 100644
--- a/Client/src/index.css
+++ b/Client/src/index.css
@@ -11,6 +11,44 @@
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
+
+ /* Generalized Stylings */
+
+ --env-var-color-1: #101828;
+ --env-var-color-2: #475467;
+ --env-var-color-3: #1570ef;
+
+ --env-var-color-4: #d0d5dd;
+ --env-var-color-5: #344054;
+ --env-var-color-6: #eaecf0;
+ --env-var-color-7: #7f56d9;
+ --env-var-color-8: #fff;
+ --env-var-color-9: #f2f2f2;
+ --env-var-color-10: #175cd3;
+
+ --env-var-radius-1: 4px;
+ --env-var-radius-2: 8px;
+
+ --env-var-width-1: 100vw;
+ --env-var-width-2: 360px;
+
+ --env-var-height-1: 100vh;
+
+ --env-var-spacing-1: 12px;
+ --env-var-spacing-2: 24px;
+ --env-var-spacing-3: 32px;
+ --env-var-spacing-4: 40px;
+
+ --env-var-font-size-small: 11px;
+ --env-var-font-size-medium: 13px;
+ --env-var-font-size-medium-plus: 14px;
+ --env-var-font-size-large: 16px;
+ --env-var-font-size-xlarge: 30px;
+
+ --env-var-img-width-1: 20px;
+
+ --env-var-default-1: 24px;
+ --env-var-default-2: 40px;
}
a {
diff --git a/Client/src/main.jsx b/Client/src/main.jsx
index b39e60580..1955bdd29 100644
--- a/Client/src/main.jsx
+++ b/Client/src/main.jsx
@@ -5,12 +5,17 @@ import "./index.css";
import { BrowserRouter as Router, HashRouter } from "react-router-dom";
import theme from "./Utils/Theme.js";
import { ThemeProvider } from "@mui/material";
+import { Provider } from "react-redux";
+import store from "./store";
+
ReactDOM.createRoot(document.getElementById("root")).render(
-
-
-
-
-
+
+
+
+
+
+
+
);
diff --git a/Client/src/store.js b/Client/src/store.js
new file mode 100644
index 000000000..e8409d993
--- /dev/null
+++ b/Client/src/store.js
@@ -0,0 +1,6 @@
+import { configureStore } from "@reduxjs/toolkit";
+import monitorsReducer from "./Features/Monitors/monitorsSlice";
+
+export default configureStore({
+ reducer: { monitors: monitorsReducer },
+});
diff --git a/Client/vite.config.js.timestamp-1714807476723-44482001f0038.mjs b/Client/vite.config.js.timestamp-1714807476723-44482001f0038.mjs
deleted file mode 100644
index f54c5cbfe..000000000
--- a/Client/vite.config.js.timestamp-1714807476723-44482001f0038.mjs
+++ /dev/null
@@ -1,10 +0,0 @@
-// vite.config.js
-import { defineConfig } from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/vite/dist/node/index.js";
-import react from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/@vitejs/plugin-react/dist/index.mjs";
-var vite_config_default = defineConfig({
- plugins: [react()]
-});
-export {
- vite_config_default as default
-};
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJjOlxcXFxVc2Vyc1xcXFxjb3NtaVxcXFxPbmVEcml2ZVxcXFxEZXNrdG9wXFxcXEJsdWVXYXZlXFxcXFVwdGltZS1Nb25pdG9yXFxcXGJsdWV3YXZlLXVwdGltZVxcXFxDbGllbnRcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcImM6XFxcXFVzZXJzXFxcXGNvc21pXFxcXE9uZURyaXZlXFxcXERlc2t0b3BcXFxcQmx1ZVdhdmVcXFxcVXB0aW1lLU1vbml0b3JcXFxcYmx1ZXdhdmUtdXB0aW1lXFxcXENsaWVudFxcXFx2aXRlLmNvbmZpZy5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vYzovVXNlcnMvY29zbWkvT25lRHJpdmUvRGVza3RvcC9CbHVlV2F2ZS9VcHRpbWUtTW9uaXRvci9ibHVld2F2ZS11cHRpbWUvQ2xpZW50L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHJlYWN0IGZyb20gJ0B2aXRlanMvcGx1Z2luLXJlYWN0J1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuICBwbHVnaW5zOiBbcmVhY3QoKV0sXHJcbn0pXHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBOGEsU0FBUyxvQkFBb0I7QUFDM2MsT0FBTyxXQUFXO0FBR2xCLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzFCLFNBQVMsQ0FBQyxNQUFNLENBQUM7QUFDbkIsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K
diff --git a/Client/vite.config.js.timestamp-1714807479464-cc660fde72923.mjs b/Client/vite.config.js.timestamp-1714807479464-cc660fde72923.mjs
deleted file mode 100644
index f54c5cbfe..000000000
--- a/Client/vite.config.js.timestamp-1714807479464-cc660fde72923.mjs
+++ /dev/null
@@ -1,10 +0,0 @@
-// vite.config.js
-import { defineConfig } from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/vite/dist/node/index.js";
-import react from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/@vitejs/plugin-react/dist/index.mjs";
-var vite_config_default = defineConfig({
- plugins: [react()]
-});
-export {
- vite_config_default as default
-};
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJjOlxcXFxVc2Vyc1xcXFxjb3NtaVxcXFxPbmVEcml2ZVxcXFxEZXNrdG9wXFxcXEJsdWVXYXZlXFxcXFVwdGltZS1Nb25pdG9yXFxcXGJsdWV3YXZlLXVwdGltZVxcXFxDbGllbnRcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcImM6XFxcXFVzZXJzXFxcXGNvc21pXFxcXE9uZURyaXZlXFxcXERlc2t0b3BcXFxcQmx1ZVdhdmVcXFxcVXB0aW1lLU1vbml0b3JcXFxcYmx1ZXdhdmUtdXB0aW1lXFxcXENsaWVudFxcXFx2aXRlLmNvbmZpZy5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vYzovVXNlcnMvY29zbWkvT25lRHJpdmUvRGVza3RvcC9CbHVlV2F2ZS9VcHRpbWUtTW9uaXRvci9ibHVld2F2ZS11cHRpbWUvQ2xpZW50L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHJlYWN0IGZyb20gJ0B2aXRlanMvcGx1Z2luLXJlYWN0J1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuICBwbHVnaW5zOiBbcmVhY3QoKV0sXHJcbn0pXHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBOGEsU0FBUyxvQkFBb0I7QUFDM2MsT0FBTyxXQUFXO0FBR2xCLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzFCLFNBQVMsQ0FBQyxNQUFNLENBQUM7QUFDbkIsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K
diff --git a/Client/vite.config.js.timestamp-1714807482127-bba3249973ca6.mjs b/Client/vite.config.js.timestamp-1714807482127-bba3249973ca6.mjs
deleted file mode 100644
index e69de29bb..000000000
diff --git a/Client/vite.config.js.timestamp-1714807487371-43b917cc75e26.mjs b/Client/vite.config.js.timestamp-1714807487371-43b917cc75e26.mjs
deleted file mode 100644
index f54c5cbfe..000000000
--- a/Client/vite.config.js.timestamp-1714807487371-43b917cc75e26.mjs
+++ /dev/null
@@ -1,10 +0,0 @@
-// vite.config.js
-import { defineConfig } from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/vite/dist/node/index.js";
-import react from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/@vitejs/plugin-react/dist/index.mjs";
-var vite_config_default = defineConfig({
- plugins: [react()]
-});
-export {
- vite_config_default as default
-};
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJjOlxcXFxVc2Vyc1xcXFxjb3NtaVxcXFxPbmVEcml2ZVxcXFxEZXNrdG9wXFxcXEJsdWVXYXZlXFxcXFVwdGltZS1Nb25pdG9yXFxcXGJsdWV3YXZlLXVwdGltZVxcXFxDbGllbnRcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcImM6XFxcXFVzZXJzXFxcXGNvc21pXFxcXE9uZURyaXZlXFxcXERlc2t0b3BcXFxcQmx1ZVdhdmVcXFxcVXB0aW1lLU1vbml0b3JcXFxcYmx1ZXdhdmUtdXB0aW1lXFxcXENsaWVudFxcXFx2aXRlLmNvbmZpZy5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vYzovVXNlcnMvY29zbWkvT25lRHJpdmUvRGVza3RvcC9CbHVlV2F2ZS9VcHRpbWUtTW9uaXRvci9ibHVld2F2ZS11cHRpbWUvQ2xpZW50L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHJlYWN0IGZyb20gJ0B2aXRlanMvcGx1Z2luLXJlYWN0J1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuICBwbHVnaW5zOiBbcmVhY3QoKV0sXHJcbn0pXHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBOGEsU0FBUyxvQkFBb0I7QUFDM2MsT0FBTyxXQUFXO0FBR2xCLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzFCLFNBQVMsQ0FBQyxNQUFNLENBQUM7QUFDbkIsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K
diff --git a/Client/vite.config.js.timestamp-1714807494135-d5aa25dec011.mjs b/Client/vite.config.js.timestamp-1714807494135-d5aa25dec011.mjs
deleted file mode 100644
index e69de29bb..000000000
diff --git a/Client/vite.config.js.timestamp-1714807590920-36497efd2dbd1.mjs b/Client/vite.config.js.timestamp-1714807590920-36497efd2dbd1.mjs
deleted file mode 100644
index f54c5cbfe..000000000
--- a/Client/vite.config.js.timestamp-1714807590920-36497efd2dbd1.mjs
+++ /dev/null
@@ -1,10 +0,0 @@
-// vite.config.js
-import { defineConfig } from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/vite/dist/node/index.js";
-import react from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/@vitejs/plugin-react/dist/index.mjs";
-var vite_config_default = defineConfig({
- plugins: [react()]
-});
-export {
- vite_config_default as default
-};
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJjOlxcXFxVc2Vyc1xcXFxjb3NtaVxcXFxPbmVEcml2ZVxcXFxEZXNrdG9wXFxcXEJsdWVXYXZlXFxcXFVwdGltZS1Nb25pdG9yXFxcXGJsdWV3YXZlLXVwdGltZVxcXFxDbGllbnRcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcImM6XFxcXFVzZXJzXFxcXGNvc21pXFxcXE9uZURyaXZlXFxcXERlc2t0b3BcXFxcQmx1ZVdhdmVcXFxcVXB0aW1lLU1vbml0b3JcXFxcYmx1ZXdhdmUtdXB0aW1lXFxcXENsaWVudFxcXFx2aXRlLmNvbmZpZy5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vYzovVXNlcnMvY29zbWkvT25lRHJpdmUvRGVza3RvcC9CbHVlV2F2ZS9VcHRpbWUtTW9uaXRvci9ibHVld2F2ZS11cHRpbWUvQ2xpZW50L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHJlYWN0IGZyb20gJ0B2aXRlanMvcGx1Z2luLXJlYWN0J1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuICBwbHVnaW5zOiBbcmVhY3QoKV0sXHJcbn0pXHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBOGEsU0FBUyxvQkFBb0I7QUFDM2MsT0FBTyxXQUFXO0FBR2xCLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzFCLFNBQVMsQ0FBQyxNQUFNLENBQUM7QUFDbkIsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K
diff --git a/Client/vite.config.js.timestamp-1714807965878-e54134a7db9a9.mjs b/Client/vite.config.js.timestamp-1714807965878-e54134a7db9a9.mjs
deleted file mode 100644
index f54c5cbfe..000000000
--- a/Client/vite.config.js.timestamp-1714807965878-e54134a7db9a9.mjs
+++ /dev/null
@@ -1,10 +0,0 @@
-// vite.config.js
-import { defineConfig } from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/vite/dist/node/index.js";
-import react from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/@vitejs/plugin-react/dist/index.mjs";
-var vite_config_default = defineConfig({
- plugins: [react()]
-});
-export {
- vite_config_default as default
-};
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJjOlxcXFxVc2Vyc1xcXFxjb3NtaVxcXFxPbmVEcml2ZVxcXFxEZXNrdG9wXFxcXEJsdWVXYXZlXFxcXFVwdGltZS1Nb25pdG9yXFxcXGJsdWV3YXZlLXVwdGltZVxcXFxDbGllbnRcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcImM6XFxcXFVzZXJzXFxcXGNvc21pXFxcXE9uZURyaXZlXFxcXERlc2t0b3BcXFxcQmx1ZVdhdmVcXFxcVXB0aW1lLU1vbml0b3JcXFxcYmx1ZXdhdmUtdXB0aW1lXFxcXENsaWVudFxcXFx2aXRlLmNvbmZpZy5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vYzovVXNlcnMvY29zbWkvT25lRHJpdmUvRGVza3RvcC9CbHVlV2F2ZS9VcHRpbWUtTW9uaXRvci9ibHVld2F2ZS11cHRpbWUvQ2xpZW50L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHJlYWN0IGZyb20gJ0B2aXRlanMvcGx1Z2luLXJlYWN0J1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuICBwbHVnaW5zOiBbcmVhY3QoKV0sXHJcbn0pXHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBOGEsU0FBUyxvQkFBb0I7QUFDM2MsT0FBTyxXQUFXO0FBR2xCLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzFCLFNBQVMsQ0FBQyxNQUFNLENBQUM7QUFDbkIsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K
diff --git a/Client/vite.config.js.timestamp-1714807967318-789fa77657938.mjs b/Client/vite.config.js.timestamp-1714807967318-789fa77657938.mjs
deleted file mode 100644
index f54c5cbfe..000000000
--- a/Client/vite.config.js.timestamp-1714807967318-789fa77657938.mjs
+++ /dev/null
@@ -1,10 +0,0 @@
-// vite.config.js
-import { defineConfig } from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/vite/dist/node/index.js";
-import react from "file:///c:/Users/cosmi/OneDrive/Desktop/BlueWave/Uptime-Monitor/bluewave-uptime/Client/node_modules/@vitejs/plugin-react/dist/index.mjs";
-var vite_config_default = defineConfig({
- plugins: [react()]
-});
-export {
- vite_config_default as default
-};
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJjOlxcXFxVc2Vyc1xcXFxjb3NtaVxcXFxPbmVEcml2ZVxcXFxEZXNrdG9wXFxcXEJsdWVXYXZlXFxcXFVwdGltZS1Nb25pdG9yXFxcXGJsdWV3YXZlLXVwdGltZVxcXFxDbGllbnRcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcImM6XFxcXFVzZXJzXFxcXGNvc21pXFxcXE9uZURyaXZlXFxcXERlc2t0b3BcXFxcQmx1ZVdhdmVcXFxcVXB0aW1lLU1vbml0b3JcXFxcYmx1ZXdhdmUtdXB0aW1lXFxcXENsaWVudFxcXFx2aXRlLmNvbmZpZy5qc1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vYzovVXNlcnMvY29zbWkvT25lRHJpdmUvRGVza3RvcC9CbHVlV2F2ZS9VcHRpbWUtTW9uaXRvci9ibHVld2F2ZS11cHRpbWUvQ2xpZW50L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHJlYWN0IGZyb20gJ0B2aXRlanMvcGx1Z2luLXJlYWN0J1xyXG5cclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcclxuICBwbHVnaW5zOiBbcmVhY3QoKV0sXHJcbn0pXHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBOGEsU0FBUyxvQkFBb0I7QUFDM2MsT0FBTyxXQUFXO0FBR2xCLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzFCLFNBQVMsQ0FBQyxNQUFNLENBQUM7QUFDbkIsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K
diff --git a/README.md b/README.md
index a86b460e4..c93ee1434 100644
--- a/README.md
+++ b/README.md
@@ -13,15 +13,28 @@ BlueWave uptime monitoring application
- [Database](#databases)
- [Docker Images](#docker-images)
4. [Endpoints](#endpoints)
+ ###### Auth
-
POST [/api/v1/auth/register](#post-register)
-
POST [/api/v1/auth/login](#post-login)
-
POST [/api/v1/auth/user/{userId}](#post-auth-user-edit-id)
+ ###### Monitors
-
GET [/api/v1/monitors](#get-monitors)
-
GET [/api/v1/monitor/{id}](#get-monitor-id)
-
GET [/api/v1/monitors/user/{userId}](#get-monitors-user-userid)
-
POST [/api/v1/monitors](#post-monitors)
-
POST [/api/v1/monitors/delete/{monitorId}](#post-monitors-del-id)
-
POST [/api/v1/monitors/edit/{monitorId}](#post-monitors-edit-id)
+ ###### Checks
+ -
POST [/api/v1/checks/{monitorId}](#post-checks)
+ -
GET [/api/v1/checks/{monitorId}](#get-checks)
+ -
POST [/api/v1/checks/delete/{monitorId}](#delete-checks)
+ ###### Alerts
+ -
POST [/api/v1/alerts/{monitorId}](#create-alert)
+ -
GET [/api/v1/alerts/user/{userId}](#get-alerts-user-id)
+ -
GET [/api/v1/alerts/monitor/{monitorId}](#get-alerts-monitor-id)
+ -
GET [/api/v1/alerts/{alertId}](#get-alert-alert-id)
+ -
POST [/api/v1/alerts/edit/{alertId}](#edit-alert)
+ -
POST [/api/v1/alerts/delete/{alertId}](#delete-alert)
5. [Error Handling](#error-handling)
6. [Contributors](#contributors)
@@ -55,14 +68,14 @@ BlueWave uptime monitoring application
Configure the server with the following environmental variables:
-| ENV Variable Name | Required/Optional | Type | Description | Accepted Values |
-| -------------------- | ----------------- | --------- | ----------------------------------------------------- | ------------------- |
-| JWT_SECRET | Required | `string` | JWT secret | |
-| DB_TYPE | Optional | `string` | Specify DB to use | `MongoDB \| FakeDB` |
-| DB_CONNECTION_STRING | Required | `string` | Specifies URL for MongoDB Database | |
-| PORT | Optional | `integer` | Specifies Port for Server | |
-| MAILERSEND_API_KEY | Required | `string` | Specifies API KEY for MailerSend service | |
-| SYSTEM_EMAIL_ADDRESS | Required | `string` | Specifies System email to be used in emailing service | |
+| ENV Variable Name | Required/Optional | Type | Description | Accepted Values |
+| -------------------- | ----------------- | --------- | ------------------------------------------------------------------------------------------- | ------------------- |
+| JWT_SECRET | Required | `string` | JWT secret | |
+| DB_TYPE | Optional | `string` | Specify DB to use | `MongoDB \| FakeDB` |
+| DB_CONNECTION_STRING | Required | `string` | Specifies URL for MongoDB Database | |
+| PORT | Optional | `integer` | Specifies Port for Server | |
+| SENDGRID_API_KEY | Required | `string` | Specifies API KEY for SendGrid email service | |
+| SYSTEM_EMAIL_ADDRESS | Required | `string` | Specifies System email to be used in emailing service, must be a verified email by sendgrid | |
---
@@ -183,7 +196,9 @@ Example:
| Name | Type | Notes |
| ----------------- | --------- | ------------------------------------------------- |
-| checkId | `string` | Unique ID for the check |
+| checkId | `string` | Unique ID for the associated check |
+| monitorId | `string` | Unique ID for the associated monitor |
+| userId | `string` | Unique ID for the associated user |
| status | `boolean` | Indicates the service is Up or Down |
| message | `string` | Message for the user about the down service |
| notifiedStatus | `boolean` | Indicates whether the user is notified |
@@ -191,7 +206,11 @@ Example:
| updatedAt | `Date` | Last time the alert was updated |
| CreatedAt | `Date` | When the alert was created |
-##
+
+
+---
+
+###### Auth
POST /api/v1/auth/register
@@ -244,8 +263,6 @@ curl --request POST \
----
-
POST /api/v1/auth/login
@@ -293,8 +310,6 @@ curl --request POST \
----
-
POST/api/v1/auth/user/{userId}
@@ -356,6 +371,8 @@ curl --request POST \
---
+###### Monitors
+
GET /api/v1/monitors
@@ -367,9 +384,9 @@ curl --request POST \
##### Response Payload
-> | Type | Notes |
-> | ---------------- | ----------------- |
-> | `Array[Monitor]` | Array of monitors |
+> | Type | Notes |
+> | ---------------- | --------------------- |
+> | `Array` | Array of all monitors |
###### Sample cURL Request
@@ -416,8 +433,6 @@ curl --request GET \
----
-
GET /api/v1/monitor/{id}
@@ -464,8 +479,6 @@ curl --request GET \
----
-
GET /api/v1/monitors/user/{userId}
@@ -477,9 +490,9 @@ curl --request GET \
###### Response Payload
-> | Type | Notes |
-> | ---------------- | ------------------------------------------------------------------ |
-> | `Array[Monitor]` | Array of monitors created by user with userId specified in request |
+> | Type | Notes |
+> | ---------------- | ------------------------------------------------------- |
+> | `Array` | Array of monitors created by user with specified UserID |
###### Sample cURL Request
@@ -526,8 +539,6 @@ curl --request GET \
----
-
POST/api/v1/monitors
@@ -539,9 +550,9 @@ curl --request GET \
###### Response Payload
-> | Type | Notes |
-> | --------- | --------------------------------- |
-> | `Monitor` | Newly created monitor is returned |
+> | Type | Notes |
+> | --------- | ------------------------------- |
+> | `Monitor` | Returns newly created `Monitor` |
##### Sample CURL request
@@ -581,8 +592,6 @@ curl --request POST \
----
-
POST/api/v1/monitors/delete/{monitorId}
@@ -618,8 +627,6 @@ curl --request POST \
##
----
-
POST/api/v1/monitors/edit/{monitorId}
@@ -679,6 +686,942 @@ curl --request POST \
---
+###### Checks
+
+
+POST/api/v1/checks/{monitorId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | POST |
+
+###### Response Payload
+
+> | Type | Notes |
+> | ------- | --------------------------- |
+> | `Check` | Returns newly created check |
+
+###### Body
+
+> | Name | Type | Notes |
+> | ------------ | --------- | -------------------------------------- |
+> | monitorId | `string` | Monitor associated with Check |
+> | status | `boolean` | `true` for up and `false` for down |
+> | responseTime | `number` | How long it took the server to respond |
+> | statusCode | `number` | HTTP Status code of response |
+> | message | `string` | |
+
+##### Sample CURL request
+
+```
+curl --request POST \
+ --url http://localhost:5000/api/v1/checks/66562414035c4ce6a8a610ac \
+ --header 'Authorization: ' \
+ --header 'Content-Type: application/json' \
+ --data '{
+ "monitorId": "66562414035c4ce6a8a610ac",
+ "status": true,
+ "responseTime": 1,
+ "statusCode": 200,
+ "message": "good"
+}'
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Check created",
+ "data": {
+ "monitorId": "66562414035c4ce6a8a610ac",
+ "status": true,
+ "responseTime": 1,
+ "statusCode": 200,
+ "message": "good",
+ "_id": "66576decba9f70148ea1f354",
+ "createdAt": "2024-05-29T18:03:24.445Z",
+ "updatedAt": "2024-05-29T18:03:24.445Z",
+ "__v": 0
+ }
+}
+```
+
+
+
+
+GET/api/v1/checks/{monitorId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | GET |
+
+###### Response Payload
+
+> | Type | Notes |
+> | --------------- | ------------------------ |
+> | `Array` | Array of `Check` objects |
+
+##### Sample CURL request
+
+```
+curl --request GET \
+ --url http://localhost:5000/api/v1/checks/66562414035c4ce6a8a610ac \
+ --header 'Authorization: ' \
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Checks retrieved",
+ "data": [
+ {
+ "_id": "66576c0194e11c0d4409d3c1",
+ "monitorId": "66562414035c4ce6a8a610ac",
+ "status": true,
+ "responseTime": 1,
+ "statusCode": 200,
+ "message": "good",
+ "createdAt": "2024-05-29T17:55:13.581Z",
+ "updatedAt": "2024-05-29T17:55:13.581Z",
+ "__v": 0
+ },
+ {
+ "_id": "66576c0994e11c0d4409d3c5",
+ "monitorId": "66562414035c4ce6a8a610ac",
+ "status": true,
+ "responseTime": 2,
+ "statusCode": 200,
+ "message": "good",
+ "createdAt": "2024-05-29T17:55:21.127Z",
+ "updatedAt": "2024-05-29T17:55:21.127Z",
+ "__v": 0
+ }
+ ]
+}
+```
+
+
+
+
+POST/api/v1/checks/delete/{monitorId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | POST |
+
+###### Response Payload
+
+> | Type | Notes |
+> | -------- | -------------------------------------------------------------------- |
+> | `Object` | `{deletedCount: n}` Returns an object showing how many items deleted |
+
+##### Sample CURL request
+
+```
+curl --request POST \
+ --url http://localhost:5000/api/v1/checks/delete/66562414035c4ce6a8a610ac \
+ --header 'Authorization: ' \
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Checks deleted",
+ "data": {
+ "deletedCount": 3
+ }
+}
+```
+
+
+
+---
+
+###### Alerts
+
+
+POST/api/v1/alerts/{monitorId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | POST |
+
+###### Response Payload
+
+> | Type | Notes |
+> | ------- | ----------------------------- |
+> | `Alert` | Returns newly created `Alert` |
+
+###### Body
+
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": "false",
+ "acknowledgeStatus": false
+
+> | Name | Type | Notes |
+> | ----------------- | --------- | --------------------------------------- |
+> | checkId | `string` | Id of `Check` associated with `Alert` |
+> | monitorId | `string` | Id of `Monitor` associated with `Alert` |
+> | userId | `string` | Id of `User` associated with `Alert` |
+> | status | `boolean` | Status of `Alert` |
+> | message | `string` | `Alert` message |
+> | notifiedStatus | `boolean` | |
+> | acknowledgeStatus | `boolean` | |
+
+##### Sample CURL request
+
+```
+
+```
+
+###### Sample Response
+
+```json
+
+```
+
+
+
+
+GET/api/v1/alerts/user/{userId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | GET |
+
+###### Response Payload
+
+> | Type | Notes |
+> | -------------- | --------------------------------------- |
+> | `Array` | Returns all `Alert` created by a `User` |
+
+##### Sample CURL request
+
+```
+curl --request GET \
+ --url http://localhost:5000/api/v1/alerts/user/6654d1a2634754f789e1f115 \
+ --header 'Authorization: '
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Got alerts",
+ "data": [
+ {
+ "_id": "6657813d809adfded891a6b7",
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": false,
+ "acknowledgeStatus": false,
+ "createdAt": "2024-05-29T19:25:49.317Z",
+ "updatedAt": "2024-05-29T19:25:49.317Z",
+ "__v": 0
+ }
+ ]
+}
+```
+
+
+
+GET/api/v1/alerts/monitor/{monitorId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | GET |
+
+###### Response Payload
+
+> | Type | Notes |
+> | -------------- | -------------------------------------------------------------- |
+> | `Array` | Returns an array of `Alert` belonging to a specified `Monitor` |
+
+##### Sample CURL request
+
+```
+curl --request GET \
+ --url http://localhost:5000/api/v1/alerts/monitor/6657789ebf6766ee8e2d2edb \
+ --header 'Authorization: ' \
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Got alerts by Monitor",
+ "data": [
+ {
+ "_id": "6657813d809adfded891a6b7",
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": false,
+ "acknowledgeStatus": false,
+ "createdAt": "2024-05-29T19:25:49.317Z",
+ "updatedAt": "2024-05-29T19:25:49.317Z",
+ "__v": 0
+ }
+ ]
+}
+```
+
+
+
+
+GET/api/v1/alerts/{alertId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | GET |
+
+###### Response Payload
+
+> | Type | Notes |
+> | ------- | ------------------------- |
+> | `Alert` | Returns specified `Alert` |
+
+##### Sample CURL request
+
+```
+curl --request GET \
+ --url http://localhost:5000/api/v1/alerts/66577ddae5ff3c91437d0887 \
+ --header 'Authorization: ' \
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Got Alert By alertID",
+ "data": {
+ "_id": "66577ddae5ff3c91437d0887",
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": false,
+ "acknowledgeStatus": false,
+ "createdAt": "2024-05-29T19:11:22.205Z",
+ "updatedAt": "2024-05-29T19:11:22.205Z",
+ "__v": 0
+ }
+}
+```
+
+
+
+
+POST/api/v1/alerts/edit/{alertId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | POST |
+
+###### Response Payload
+
+> | Type | Notes |
+> | ------- | ---------------------- |
+> | `Alert` | Returns edited `Alert` |
+
+###### Body
+
+> | Name | Type | Notes |
+> | ----------------- | --------- | ------------------------------------------ |
+> | checkId | `string` | ID of `Check` associated with `Alert` |
+> | monitorId | `string` | ID of `Monitor` id associated with `Alert` |
+> | userId | `string` | ID of `User` associated with `Alert` |
+> | status | `boolean` | Alert status |
+> | message | `string` | Alert message |
+> | notifiedStatus | `boolean` | |
+> | acknowledgeStatus | `boolean` | |
+
+##### Sample CURL request
+
+```
+curl --request POST \
+ --url http://localhost:5000/api/v1/alerts/edit/66577ddae5ff3c91437d0887 \
+ --header 'Authorization: ' \
+ --header 'Content-Type: application/json' \
+ --data '{
+ "acknowledgeStatus": true
+}'
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Edited alert",
+ "data": {
+ "_id": "66577ddae5ff3c91437d0887",
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": false,
+ "acknowledgeStatus": true,
+ "createdAt": "2024-05-29T19:11:22.205Z",
+ "updatedAt": "2024-05-29T19:12:23.951Z",
+ "__v": 0
+ }
+}
+```
+
+
+
+POST/api/v1/alerts/delete/{alertId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | POST |
+
+###### Response Payload
+
+> | Type | Notes |
+> | ------- | --------------------------- |
+> | `Alert` | Returns the deleted `Alert` |
+
+##### Sample CURL request
+
+```
+curl --request POST \
+ --url http://localhost:5000/api/v1/alerts/delete/66577ddae5ff3c91437d0887 \
+ --header 'Authorization: ' \
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Deleted alert",
+ "data": {
+ "_id": "66577ddae5ff3c91437d0887",
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": false,
+ "acknowledgeStatus": true,
+ "createdAt": "2024-05-29T19:11:22.205Z",
+ "updatedAt": "2024-05-29T19:12:23.951Z",
+ "__v": 0
+ }
+}
+```
+
+
+
+---
+
+###### Checks
+
+
+POST/api/v1/checks/{monitorId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | POST |
+
+###### Response Payload
+
+> | Type | Notes |
+> | ------- | --------------------------- |
+> | `Check` | Returns newly created check |
+
+###### Body
+
+> | Name | Type | Notes |
+> | ------------ | --------- | -------------------------------------- |
+> | monitorId | `string` | Monitor associated with Check |
+> | status | `boolean` | `true` for up and `false` for down |
+> | responseTime | `number` | How long it took the server to respond |
+> | statusCode | `number` | HTTP Status code of response |
+> | message | `string` | |
+
+##### Sample CURL request
+
+```
+curl --request POST \
+ --url http://localhost:5000/api/v1/checks/66562414035c4ce6a8a610ac \
+ --header 'Authorization: ' \
+ --header 'Content-Type: application/json' \
+ --data '{
+ "monitorId": "66562414035c4ce6a8a610ac",
+ "status": true,
+ "responseTime": 1,
+ "statusCode": 200,
+ "message": "good"
+}'
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Check created",
+ "data": {
+ "monitorId": "66562414035c4ce6a8a610ac",
+ "status": true,
+ "responseTime": 1,
+ "statusCode": 200,
+ "message": "good",
+ "_id": "66576decba9f70148ea1f354",
+ "createdAt": "2024-05-29T18:03:24.445Z",
+ "updatedAt": "2024-05-29T18:03:24.445Z",
+ "__v": 0
+ }
+}
+```
+
+
+
+
+GET/api/v1/checks/{monitorId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | GET |
+
+###### Response Payload
+
+> | Type | Notes |
+> | --------------- | ------------------------ |
+> | `Array` | Array of `Check` objects |
+
+##### Sample CURL request
+
+```
+curl --request GET \
+ --url http://localhost:5000/api/v1/checks/66562414035c4ce6a8a610ac \
+ --header 'Authorization: ' \
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Checks retrieved",
+ "data": [
+ {
+ "_id": "66576c0194e11c0d4409d3c1",
+ "monitorId": "66562414035c4ce6a8a610ac",
+ "status": true,
+ "responseTime": 1,
+ "statusCode": 200,
+ "message": "good",
+ "createdAt": "2024-05-29T17:55:13.581Z",
+ "updatedAt": "2024-05-29T17:55:13.581Z",
+ "__v": 0
+ },
+ {
+ "_id": "66576c0994e11c0d4409d3c5",
+ "monitorId": "66562414035c4ce6a8a610ac",
+ "status": true,
+ "responseTime": 2,
+ "statusCode": 200,
+ "message": "good",
+ "createdAt": "2024-05-29T17:55:21.127Z",
+ "updatedAt": "2024-05-29T17:55:21.127Z",
+ "__v": 0
+ }
+ ]
+}
+```
+
+
+
+
+POST/api/v1/checks/delete/{monitorId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | POST |
+
+###### Response Payload
+
+> | Type | Notes |
+> | -------- | -------------------------------------------------------------------- |
+> | `Object` | `{deletedCount: n}` Returns an object showing how many items deleted |
+
+##### Sample CURL request
+
+```
+curl --request POST \
+ --url http://localhost:5000/api/v1/checks/delete/66562414035c4ce6a8a610ac \
+ --header 'Authorization: ' \
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Checks deleted",
+ "data": {
+ "deletedCount": 3
+ }
+}
+```
+
+
+
+---
+
+###### Alerts
+
+
+POST/api/v1/alerts/{monitorId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | POST |
+
+###### Response Payload
+
+> | Type | Notes |
+> | ------- | ----------------------------- |
+> | `Alert` | Returns newly created `Alert` |
+
+###### Body
+
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": "false",
+ "acknowledgeStatus": false
+
+> | Name | Type | Notes |
+> | ----------------- | --------- | --------------------------------------- |
+> | checkId | `string` | Id of `Check` associated with `Alert` |
+> | monitorId | `string` | Id of `Monitor` associated with `Alert` |
+> | userId | `string` | Id of `User` associated with `Alert` |
+> | status | `boolean` | Status of `Alert` |
+> | message | `string` | `Alert` message |
+> | notifiedStatus | `boolean` | |
+> | acknowledgeStatus | `boolean` | |
+
+##### Sample CURL request
+
+```
+
+```
+
+###### Sample Response
+
+```json
+
+```
+
+
+
+
+GET/api/v1/alerts/user/{userId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | GET |
+
+###### Response Payload
+
+> | Type | Notes |
+> | -------------- | --------------------------------------- |
+> | `Array` | Returns all `Alert` created by a `User` |
+
+##### Sample CURL request
+
+```
+curl --request GET \
+ --url http://localhost:5000/api/v1/alerts/user/6654d1a2634754f789e1f115 \
+ --header 'Authorization: '
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Got alerts",
+ "data": [
+ {
+ "_id": "6657813d809adfded891a6b7",
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": false,
+ "acknowledgeStatus": false,
+ "createdAt": "2024-05-29T19:25:49.317Z",
+ "updatedAt": "2024-05-29T19:25:49.317Z",
+ "__v": 0
+ }
+ ]
+}
+```
+
+
+
+GET/api/v1/alerts/monitor/{monitorId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | GET |
+
+###### Response Payload
+
+> | Type | Notes |
+> | -------------- | -------------------------------------------------------------- |
+> | `Array` | Returns an array of `Alert` belonging to a specified `Monitor` |
+
+##### Sample CURL request
+
+```
+curl --request GET \
+ --url http://localhost:5000/api/v1/alerts/monitor/6657789ebf6766ee8e2d2edb \
+ --header 'Authorization: ' \
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Got alerts by Monitor",
+ "data": [
+ {
+ "_id": "6657813d809adfded891a6b7",
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": false,
+ "acknowledgeStatus": false,
+ "createdAt": "2024-05-29T19:25:49.317Z",
+ "updatedAt": "2024-05-29T19:25:49.317Z",
+ "__v": 0
+ }
+ ]
+}
+```
+
+
+
+
+GET/api/v1/alerts/{alertId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | GET |
+
+###### Response Payload
+
+> | Type | Notes |
+> | ------- | ------------------------- |
+> | `Alert` | Returns specified `Alert` |
+
+##### Sample CURL request
+
+```
+curl --request GET \
+ --url http://localhost:5000/api/v1/alerts/66577ddae5ff3c91437d0887 \
+ --header 'Authorization: ' \
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Got Alert By alertID",
+ "data": {
+ "_id": "66577ddae5ff3c91437d0887",
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": false,
+ "acknowledgeStatus": false,
+ "createdAt": "2024-05-29T19:11:22.205Z",
+ "updatedAt": "2024-05-29T19:11:22.205Z",
+ "__v": 0
+ }
+}
+```
+
+
+
+
+POST/api/v1/alerts/edit/{alertId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | POST |
+
+###### Response Payload
+
+> | Type | Notes |
+> | ------- | ---------------------- |
+> | `Alert` | Returns edited `Alert` |
+
+###### Body
+
+> | Name | Type | Notes |
+> | ----------------- | --------- | ------------------------------------------ |
+> | checkId | `string` | ID of `Check` associated with `Alert` |
+> | monitorId | `string` | ID of `Monitor` id associated with `Alert` |
+> | userId | `string` | ID of `User` associated with `Alert` |
+> | status | `boolean` | Alert status |
+> | message | `string` | Alert message |
+> | notifiedStatus | `boolean` | |
+> | acknowledgeStatus | `boolean` | |
+
+##### Sample CURL request
+
+```
+curl --request POST \
+ --url http://localhost:5000/api/v1/alerts/edit/66577ddae5ff3c91437d0887 \
+ --header 'Authorization: ' \
+ --header 'Content-Type: application/json' \
+ --data '{
+ "acknowledgeStatus": true
+}'
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Edited alert",
+ "data": {
+ "_id": "66577ddae5ff3c91437d0887",
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": false,
+ "acknowledgeStatus": true,
+ "createdAt": "2024-05-29T19:11:22.205Z",
+ "updatedAt": "2024-05-29T19:12:23.951Z",
+ "__v": 0
+ }
+}
+```
+
+
+
+POST/api/v1/alerts/delete/{alertId}
+
+###### Method/Headers
+
+> | Method/Headers | Value |
+> | -------------- | ----- |
+> | Method | POST |
+
+###### Response Payload
+
+> | Type | Notes |
+> | ------- | --------------------------- |
+> | `Alert` | Returns the deleted `Alert` |
+
+##### Sample CURL request
+
+```
+curl --request POST \
+ --url http://localhost:5000/api/v1/alerts/delete/66577ddae5ff3c91437d0887 \
+ --header 'Authorization: ' \
+```
+
+###### Sample Response
+
+```json
+{
+ "success": true,
+ "msg": "Deleted alert",
+ "data": {
+ "_id": "66577ddae5ff3c91437d0887",
+ "checkId": "66577a3fd16dcf7c1ce35148",
+ "monitorId": "6657789ebf6766ee8e2d2edb",
+ "userId": "6654d1a2634754f789e1f115",
+ "status": false,
+ "message": "This is a test alert",
+ "notifiedStatus": false,
+ "acknowledgeStatus": true,
+ "createdAt": "2024-05-29T19:11:22.205Z",
+ "updatedAt": "2024-05-29T19:12:23.951Z",
+ "__v": 0
+ }
+}
+```
+
+
+
+---
+
### Error handling
Errors are returned in a standard format:
diff --git a/Server/controllers/alertController.js b/Server/controllers/alertController.js
new file mode 100644
index 000000000..f0c3df5dd
--- /dev/null
+++ b/Server/controllers/alertController.js
@@ -0,0 +1,185 @@
+const express = require("express");
+const logger = require("../utils/logger");
+require("dotenv").config();
+const {
+ createAlertParamValidation,
+ createAlertBodyValidation,
+ getAlertsByUserIdParamValidation,
+ getAlertsByMonitorIdParamValidation,
+ getAlertByIdParamValidation,
+ editAlertParamValidation,
+ editAlertBodyValidation,
+ deleteAlertParamValidation,
+} = require("../validation/joi");
+const { get } = require("mongoose");
+
+const SERVICE_NAME = "alerts";
+
+/**
+ * Creates an alert for a monitor
+ * @async
+ * @param {Express.Request} req
+ * @param {Express.Response} res
+ * @returns {Promise}
+ * @throws {Error}
+ */
+const createAlert = async (req, res, next) => {
+ try {
+ await createAlertParamValidation.validateAsync(req.params);
+ await createAlertBodyValidation.validateAsync(req.body);
+ } catch (error) {
+ error.status = 422;
+ error.message = error.details[0].message;
+ error.service = SERVICE_NAME;
+ next(error);
+ return;
+ }
+
+ try {
+ const alertData = { ...req.body };
+ const alert = await req.db.createAlert(alertData);
+ return res
+ .status(200)
+ .json({ success: true, msg: "Alert created", data: alert });
+ } catch (error) {
+ error.service = SERVICE_NAME;
+ next(error);
+ }
+};
+
+/**
+ * Gets all alerts for a user
+ * @async
+ * @param {Express.Request} req
+ * @param {Express.Response} res
+ * @returns {Promise}
+ * @throws {Error}
+ */
+const getAlertsByUserId = async (req, res, next) => {
+ try {
+ await getAlertsByUserIdParamValidation.validateAsync(req.params);
+ } catch (error) {
+ error.status = 422;
+ error.message = error.details[0].message;
+ error.service = SERVICE_NAME;
+ next(error);
+ return;
+ }
+
+ try {
+ const alerts = await req.db.getAlertsByUserId(req.params.userId);
+ return res
+ .status(200)
+ .json({ success: true, msg: "Got alerts", data: alerts });
+ } catch (error) {
+ error.service = SERVICE_NAME;
+ next(error);
+ }
+};
+
+const getAlertsByMonitorId = async (req, res, next) => {
+ try {
+ await getAlertsByMonitorIdParamValidation.validateAsync(req.params);
+ } catch (error) {
+ error.status = 422;
+ error.message = error.details[0].message;
+ error.service = SERVICE_NAME;
+ next(error);
+ return;
+ }
+
+ try {
+ const alerts = await req.db.getAlertsByMonitorId(req.params.monitorId);
+ return res.status(200).json({
+ success: true,
+ msg: "Got alerts by Monitor",
+ data: alerts,
+ });
+ } catch (error) {
+ error.service = SERVICE_NAME;
+ next(error);
+ }
+};
+
+const getAlertById = async (req, res, next) => {
+ try {
+ await getAlertByIdParamValidation.validateAsync(req.params);
+ } catch (error) {
+ error.status = 422;
+ error.message = error.details[0].message;
+ error.service = SERVICE_NAME;
+ next(error);
+ return;
+ }
+
+ try {
+ const alert = await req.db.getAlertById(req.params.alertId);
+ return res.status(200).json({
+ success: true,
+ msg: "Got Alert By alertID",
+ data: alert,
+ });
+ } catch (error) {
+ error.service = SERVICE_NAME;
+ next(error);
+ }
+};
+
+const editAlert = async (req, res, next) => {
+ try {
+ await editAlertParamValidation.validateAsync(req.params);
+ await editAlertBodyValidation.validateAsync(req.body);
+ } catch (error) {
+ console.log(error);
+ error.status = 422;
+ error.message = error.details[0].message;
+ error.service = SERVICE_NAME;
+ next(error);
+ return;
+ }
+
+ try {
+ const alertData = { ...req.body };
+ const alert = await req.db.editAlert(req.params.alertId, alertData);
+ return res.status(200).json({
+ success: true,
+ msg: "Edited alert",
+ data: alert,
+ });
+ } catch (error) {
+ error.service = SERVICE_NAME;
+ next(error);
+ }
+};
+const deleteAlert = async (req, res, next) => {
+ try {
+ await deleteAlertParamValidation.validateAsync(req.params);
+ } catch (error) {
+ error.status = 422;
+ error.message = error.details[0].message;
+ error.service = SERVICE_NAME;
+ next(error);
+ return;
+ }
+
+ try {
+ const deleted = await req.db.deleteAlert(req.params.alertId);
+ return res.status(200).json({
+ success: true,
+ msg: "Deleted alert",
+ data: deleted,
+ });
+ } catch (error) {
+ error.service = SERVICE_NAME;
+ next(error);
+ }
+};
+
+module.exports = {
+ createAlert,
+ getAlertsByUserId,
+ getAlertsByMonitorId,
+ getAlertById,
+ editAlert,
+ deleteAlert,
+};
diff --git a/Server/controllers/authController.js b/Server/controllers/authController.js
index cc476ab54..257048937 100644
--- a/Server/controllers/authController.js
+++ b/Server/controllers/authController.js
@@ -17,7 +17,7 @@ const SERVICE_NAME = "auth";
* @returns {String}
*/
const issueToken = (payload) => {
- return jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: "1h" });
+ return jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: "99d" });
};
/**
@@ -31,7 +31,7 @@ const registerController = async (req, res, next) => {
try {
await registerValidation.validateAsync(req.body);
} catch (error) {
- error.status = 400;
+ error.status = 422;
error.service = SERVICE_NAME;
error.message = error.details[0].message;
next(error);
diff --git a/Server/controllers/checkController.js b/Server/controllers/checkController.js
new file mode 100644
index 000000000..7734da45b
--- /dev/null
+++ b/Server/controllers/checkController.js
@@ -0,0 +1,81 @@
+const {
+ createCheckParamValidation,
+ createCheckBodyValidation,
+ getChecksParamValidation,
+ deleteChecksParamValidation,
+} = require("../validation/joi");
+const SERVICE_NAME = "check";
+
+const createCheck = async (req, res, next) => {
+ try {
+ await createCheckParamValidation.validateAsync(req.params);
+ await createCheckBodyValidation.validateAsync(req.body);
+ } catch (error) {
+ error.status = 422;
+ error.service = SERVICE_NAME;
+ error.message = error.details[0].message;
+ next(error);
+ return;
+ }
+
+ try {
+ const checkData = { ...req.body };
+ const check = await req.db.createCheck(checkData);
+ return res
+ .status(200)
+ .json({ success: true, msg: "Check created", data: check });
+ } catch (error) {
+ error.service = SERVICE_NAME;
+ next(error);
+ }
+};
+
+const getChecks = async (req, res, next) => {
+ try {
+ await getChecksParamValidation.validateAsync(req.params);
+ } catch (error) {
+ error.status = 422;
+ error.service = SERVICE_NAME;
+ error.message = error.details[0].message;
+ next(error);
+ return;
+ }
+
+ try {
+ const checks = await req.db.getChecks(req.params.monitorId);
+ return res
+ .status(200)
+ .json({ success: true, msg: "Checks retrieved", data: checks });
+ } catch (error) {
+ error.service = SERVICE_NAME;
+ next(error);
+ }
+};
+
+const deleteChecks = async (req, res, next) => {
+ try {
+ await deleteChecksParamValidation.validateAsync(req.params);
+ } catch (error) {
+ error.status = 422;
+ error.service = SERVICE_NAME;
+ error.message = error.details[0].message;
+ next(error);
+ return;
+ }
+
+ try {
+ const deletedCount = await req.db.deleteChecks(req.params.monitorId);
+ return res
+ .status(200)
+ .json({ success: true, msg: "Checks deleted", data: { deletedCount } });
+ } catch (error) {
+ error.service = SERVICE_NAME;
+ next(error);
+ }
+};
+
+module.exports = {
+ createCheck,
+ getChecks,
+ deleteChecks,
+};
diff --git a/Server/db/MongoDB.js b/Server/db/MongoDB.js
index 71b6fe44a..aabd3c384 100644
--- a/Server/db/MongoDB.js
+++ b/Server/db/MongoDB.js
@@ -1,6 +1,8 @@
const Monitor = require("../models/Monitor");
const mongoose = require("mongoose");
const UserModel = require("../models/user");
+const Check = require("../models/Check");
+const Alert = require("../models/Alert");
const verifyId = (userId, monitorId) => {
return userId.toString() === monitorId.toString();
@@ -16,6 +18,10 @@ const connect = async () => {
}
};
+//****************************************
+// Users
+//****************************************
+
/**
* Insert a User
* @async
@@ -80,6 +86,10 @@ const updateUser = async (req, res) => {
}
};
+//****************************************
+// Monitors
+//****************************************
+
/**
* Get all monitors
* @async
@@ -194,6 +204,190 @@ const editMonitor = async (req, res) => {
}
};
+//****************************************
+// Checks
+//****************************************
+
+/**
+ * Create a check for a monitor
+ * @async
+ * @param {Object} checkData
+ * @param {string} checkData.monitorId
+ * @param {boolean} checkData.status
+ * @param {number} checkData.responseTime
+ * @param {number} checkData.statusCode
+ * @param {string} checkData.message
+ * @returns {Promise}
+ * @throws {Error}
+ */
+
+const createCheck = async (checkData) => {
+ try {
+ console.log(checkData);
+ const check = await new Check({ ...checkData }).save();
+ return check;
+ } catch (error) {
+ throw error;
+ }
+};
+
+/**
+ * Get all checks for a monitor
+ * @async
+ * @param {string} monitorId
+ * @returns {Promise>}
+ * @throws {Error}
+ */
+
+const getChecks = async (monitorId) => {
+ try {
+ const checks = await Check.find({ monitorId });
+ return checks;
+ } catch (error) {
+ throw error;
+ }
+};
+
+/**
+ * Delete all checks for a monitor
+ * @async
+ * @param {string} monitorId
+ * @returns {number}
+ * @throws {Error}
+ */
+
+const deleteChecks = async (monitorId) => {
+ try {
+ const result = await Check.deleteMany({ monitorId });
+ if (result.deletedCount > 0) {
+ return result.deletedCount;
+ } else {
+ throw new Error(`No checks found for monitor with id ${monitorId}`);
+ }
+ } catch (error) {
+ throw error;
+ }
+};
+
+//****************************************
+// Alerts
+//****************************************
+
+/**
+ * Creates an Alert associated with a Monitor and User
+ * @async
+ * @param {Object} alertData
+ * @param {string} alertData.checkId
+ * @param {string} alert.monitorId
+ * @param {string} alert.userId
+ * @param {boolean} alert.status
+ * @param {string} alert.message
+ * @param {boolean} alert.notifiedStatus
+ * @param {boolean} alert.acknowledgeStatus
+ * @returns {>}
+ * @throws {Error}
+ */
+const createAlert = async (alertData) => {
+ try {
+ const alert = await new Alert({ ...alertData }).save();
+ return alert;
+ } catch (error) {
+ throw error;
+ }
+};
+
+/**
+ * Gets all alerts a User has set
+ * @async
+ * @param {string} userId
+ * @returns {>}
+ * @throws {Error}
+ */
+const getAlertsByUserId = async (userId) => {
+ try {
+ const alerts = await Alert.find({ userId });
+ return alerts;
+ } catch (error) {
+ throw error;
+ }
+};
+
+/**
+ * Gets all alerts a for an associated Monitor
+ * @async
+ * @param {string} monitorId
+ * @returns {>}
+ * @throws {Error}
+ */
+const getAlertsByMonitorId = async (monitorId) => {
+ try {
+ const alerts = await Alert.find({ monitorId });
+ return alerts;
+ } catch (error) {
+ throw error;
+ }
+};
+
+/**
+ * Returns an alert with specified ID
+ * @async
+ * @param {string} alertId
+ * @returns {Promise}
+ * @throws {Error}
+ */
+const getAlertById = async (alertId) => {
+ try {
+ const alert = await Alert.findById(alertId);
+ return alert;
+ } catch (error) {
+ throw error;
+ }
+};
+
+/**
+ * Returns an edited alert with the specified ID
+ * @async
+ * @param {string} alertId
+ * @param {Object} alertData
+ * @param {string} alertData.checkId
+ * @param {string} alertData.monitorId
+ * @param {string} alertData.userId
+ * @param {boolean} alertData.status
+ * @param {string} alertData.message
+ * @param {boolean} alertData.notifiedStatus
+ * @param {boolean} alertData.acknowledgeStatus
+ * @param {Express.Response} res
+ * @returns {Promise>}
+ * @throws {Error}
+ */
+const editAlert = async (alertId, alertData) => {
+ try {
+ const editedAlert = await Alert.findByIdAndUpdate(alertId, alertData, {
+ new: true,
+ });
+ return editedAlert;
+ } catch (error) {
+ throw error;
+ }
+};
+
+/**
+ * Deletes an alert with the specified ID
+ * @async
+ * @param {string} alertId
+ * @throws {Error}
+ */
+const deleteAlert = async (alertId) => {
+ try {
+ const result = await Alert.findByIdAndDelete(alertId);
+ if (result) {
+ return result;
+ } else throw new Error(`Alert with id ${alertId} not found`);
+ } catch (error) {
+ throw error;
+ }
+};
+
module.exports = {
connect,
insertUser,
@@ -205,4 +399,13 @@ module.exports = {
createMonitor,
deleteMonitor,
editMonitor,
+ createCheck,
+ getChecks,
+ deleteChecks,
+ createAlert,
+ getAlertsByUserId,
+ getAlertsByMonitorId,
+ getAlertById,
+ editAlert,
+ deleteAlert,
};
diff --git a/Server/index.js b/Server/index.js
index 63d919b8d..f1b8c1a63 100644
--- a/Server/index.js
+++ b/Server/index.js
@@ -3,14 +3,14 @@ const helmet = require("helmet");
const cors = require("cors");
const authRouter = require("./routes/authRoute");
const monitorRouter = require("./routes/monitorRoute");
+const checkRouter = require("./routes/checkRoute");
+const alertRouter = require("./routes/alertRoute");
const { connectDbAndRunServer } = require("./configs/db");
require("dotenv").config();
const logger = require("./utils/logger");
const { verifyJWT } = require("./middleware/verifyJWT");
const { handleErrors } = require("./middleware/handleErrors");
-// const { sendEmail } = require('./utils/sendEmail')
-
// **************************
// Here is where we can swap out DBs easily. Spin up a mongoDB instance and try it out.
// Simply comment out the FakeDB and uncomment the MongoDB or vice versa.
@@ -33,11 +33,6 @@ const db = DB_TYPE[process.env.DB_TYPE]
? DB_TYPE[process.env.DB_TYPE]()
: require("./db/FakeDb");
-/**
- * NOTES
- * Email Service will be added
- * Logger Service will be added (Winston or similar)
- */
const app = express();
@@ -61,13 +56,10 @@ app.use((req, res, next) => {
//routes
app.use("/api/v1/auth", authRouter);
-app.use("/api/v1/monitors", verifyJWT, monitorRouter);
+app.use("/api/v1/monitors", monitorRouter);
+app.use("/api/v1/checks", verifyJWT, checkRouter);
+app.use("/api/v1/alerts", verifyJWT, alertRouter);
-// Testing email service
-// app.use('/sendEmail', async (req, res) => {
-// const response = sendEmail(['veysel.boybay@bluewavelabs.ca'], 'Testing email service', 'Testing Bluewavelabs
');
-// console.log(response);
-// })
//health check
app.use("/api/v1/healthy", (req, res) => {
diff --git a/Server/models/Alert.js b/Server/models/Alert.js
index 72705d947..758a7eba2 100644
--- a/Server/models/Alert.js
+++ b/Server/models/Alert.js
@@ -7,6 +7,16 @@ const AlertSchema = mongoose.Schema(
ref: 'Check',
immutable: true,
},
+ monitorId: {
+ type: mongoose.Schema.Types.ObjectId,
+ ref: 'Monitor',
+ immutable: true,
+ },
+ userId: {
+ type: mongoose.Schema.Types.ObjectId,
+ ref: 'User',
+ immutable: true,
+ },
status: {
type: Boolean,
},
diff --git a/Server/package-lock.json b/Server/package-lock.json
index 9ee830ebd..c8c366248 100644
--- a/Server/package-lock.json
+++ b/Server/package-lock.json
@@ -9,6 +9,7 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
+ "@sendgrid/mail": "^8.1.3",
"bcrypt": "^5.1.1",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
@@ -96,6 +97,41 @@
"sparse-bitfield": "^3.0.3"
}
},
+ "node_modules/@sendgrid/client": {
+ "version": "8.1.3",
+ "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.3.tgz",
+ "integrity": "sha512-mRwTticRZIdUTsnyzvlK6dMu3jni9ci9J+dW/6fMMFpGRAJdCJlivFVYQvqk8kRS3RnFzS7sf6BSmhLl1ldDhA==",
+ "dependencies": {
+ "@sendgrid/helpers": "^8.0.0",
+ "axios": "^1.6.8"
+ },
+ "engines": {
+ "node": ">=12.*"
+ }
+ },
+ "node_modules/@sendgrid/helpers": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz",
+ "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==",
+ "dependencies": {
+ "deepmerge": "^4.2.2"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/@sendgrid/mail": {
+ "version": "8.1.3",
+ "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.3.tgz",
+ "integrity": "sha512-Wg5iKSUOER83/cfY6rbPa+o3ChnYzWwv1OcsR8gCV8SKi+sUPIMroildimlnb72DBkQxcbylxng1W7f0RIX7MQ==",
+ "dependencies": {
+ "@sendgrid/client": "^8.1.3",
+ "@sendgrid/helpers": "^8.0.0"
+ },
+ "engines": {
+ "node": ">=12.*"
+ }
+ },
"node_modules/@sideway/address": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz",
@@ -229,6 +265,21 @@
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
"integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/axios": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
+ "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -422,6 +473,17 @@
"text-hex": "1.0.x"
}
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -484,6 +546,14 @@
"ms": "2.0.0"
}
},
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
@@ -500,6 +570,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@@ -689,6 +767,38 @@
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@@ -1703,6 +1813,11 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"node_modules/pstree.remy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
diff --git a/Server/package.json b/Server/package.json
index 60777f7a5..9b5f08737 100644
--- a/Server/package.json
+++ b/Server/package.json
@@ -11,6 +11,7 @@
"author": "",
"license": "ISC",
"dependencies": {
+ "@sendgrid/mail": "^8.1.3",
"bcrypt": "^5.1.1",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
diff --git a/Server/routes/alertRoute.js b/Server/routes/alertRoute.js
new file mode 100644
index 000000000..be252e8c4
--- /dev/null
+++ b/Server/routes/alertRoute.js
@@ -0,0 +1,27 @@
+const router = require("express").Router();
+const alertController = require("../controllers/alertController");
+const { verifyOwnership } = require("../middleware/verifyOwnership");
+const Alert = require("../models/Alert");
+
+// Create alert
+router.post("/:monitorId", alertController.createAlert);
+// Get all alerts for a user
+router.get("/user/:userId", alertController.getAlertsByUserId);
+// Get all alerts for a monitor
+router.get("/monitor/:monitorId", alertController.getAlertsByMonitorId);
+// Get a single alert
+router.get("/:alertId", alertController.getAlertById);
+// Edit
+router.post(
+ "/edit/:alertId",
+ verifyOwnership(Alert, "alertId"),
+ alertController.editAlert
+);
+//Delete
+router.post(
+ "/delete/:alertId",
+ verifyOwnership(Alert, "alertId"),
+ alertController.deleteAlert
+);
+
+module.exports = router;
diff --git a/Server/routes/checkRoute.js b/Server/routes/checkRoute.js
new file mode 100644
index 000000000..6569dd49a
--- /dev/null
+++ b/Server/routes/checkRoute.js
@@ -0,0 +1,24 @@
+const router = require("express").Router();
+const checkController = require("../controllers/checkController");
+const { verifyOwnership } = require("../middleware/verifyOwnership");
+const Monitor = require("../models/Monitor");
+
+router.post(
+ "/:monitorId",
+ verifyOwnership(Monitor, "monitorId"),
+ checkController.createCheck
+);
+
+router.get(
+ "/:monitorId",
+ verifyOwnership(Monitor, "monitorId"),
+ checkController.getChecks
+);
+
+router.post(
+ "/delete/:monitorId",
+ verifyOwnership(Monitor, "monitorId"),
+ checkController.deleteChecks
+);
+
+module.exports = router;
diff --git a/Server/utils/sendEmail.js b/Server/utils/sendEmail.js
index 712a651bd..d60900383 100644
--- a/Server/utils/sendEmail.js
+++ b/Server/utils/sendEmail.js
@@ -1,43 +1,36 @@
-const { MailerSend, EmailParams, Sender, Recipient } = require('mailersend')
-const logger = require('../utils/logger')
-
-
-const mailersend = new MailerSend({
- apiKey: process.env.MAILERSEND_API_KEY,
-})
+const sgMail = require('@sendgrid/mail')
+const logger = require('./logger')
+sgMail.setApiKey(process.env.SENDGRID_API_KEY)
+const SERVICE_NAME = 'Email_Service';
/**
+ * @async
* @function
- * @param {[string]} receivers - takes an array of strings
- * @param {string} subject - takes a single string
- * @param {string} contentHTML - takes a single string that contains HTML
- * @returns {JSON}
- * @example
- * sendEmail(['veysel@bluewavelabs.ca','alex@bluewavelabs.ca','monzer@bluewavelabs.ca'],'Testing Email Servide','BlueWaveLabs
')
+ * @param {[String]} receivers - takes an array of strings
+ * @param {String} subject - takes a single string
+ * @param {String} contentHTML - takes a single string that contains HTML
+ * @param {String} contentText - takes a string to be used if contentHTML is not compatible
+ * @example
+ * await sendEmail(['veysel@bluewavelabs.ca','alex@bluewavelabs.ca'],'Testing Email Service','BlueWaveLabs
','Testing Email Service')
*/
-// TODO: from email should be in .env file
-const sendEmail = async (receivers,subject,contentHTML) => {
- // Sender
- const from = process.env.SYSTEM_EMAIL_ADDRESS;
- const sender = new Sender(from);
- // receivers
- let recipients = []
- receivers.map(email => recipients.push(new Recipient(email)));
- // Set params
- const emailParams = new EmailParams()
- .setFrom(sender)
- .setTo(recipients)
- .setSubject(subject)
- .setHtml(contentHTML);
-
+const sendEmail = async (receivers,subject, contentHTML, contentText = null ) => {
+ const msg = {
+ to: receivers,
+ from: {
+ name: 'Uptime System',
+ email: process.env.SYSTEM_EMAIL_ADDRESS // must be verified email by sendgrid
+ },
+ subject: subject,
+ text: contentText || contentHTML,
+ html: contentHTML,
+ }
try {
- const response = await mailersend.email.send(emailParams);
- logger.info("Email sent to receivers!",{"service":"Email"})
- return response;
-
+ await sgMail.send(msg);
+ logger.info(`Emails sent to receivers:${receivers} with the subject:${subject}`,{service:SERVICE_NAME})
} catch (error) {
- logger.error(error.body,{"service":"email"})
- console.log(error.body)
+ logger.error(`Sending Email action failed, ERROR:${error}`, { service: SERVICE_NAME });
}
}
+
+
module.exports = {sendEmail}
\ No newline at end of file
diff --git a/Server/validation/joi.js b/Server/validation/joi.js
index 399c243dc..75cd48cd1 100644
--- a/Server/validation/joi.js
+++ b/Server/validation/joi.js
@@ -1,5 +1,9 @@
const joi = require("joi");
+//****************************************
+// Auth
+//****************************************
+
const loginValidation = joi.object({
email: joi.string().email().required(),
password: joi.string().min(8).required(),
@@ -11,6 +15,20 @@ const registerValidation = joi.object({
password: joi.string().min(8).required(),
});
+const editUserParamValidation = joi.object({
+ userId: joi.string().required(),
+});
+
+const editUserBodyValidation = joi.object({
+ firstname: joi.string(),
+ lastname: joi.string(),
+ profilePicUrl: joi.string(),
+});
+
+//****************************************
+// Monitors
+//****************************************
+
const getMonitorByIdValidation = joi.object({
monitorId: joi.string().required(),
});
@@ -29,14 +47,73 @@ const monitorValidation = joi.object({
interval: joi.number(),
});
-const editUserParamValidation = joi.object({
+//****************************************
+// Alerts
+//****************************************
+
+const createAlertParamValidation = joi.object({
+ monitorId: joi.string().required(),
+});
+
+const createAlertBodyValidation = joi.object({
+ checkId: joi.string().required(),
+ monitorId: joi.string().required(),
+ userId: joi.string().required(),
+ status: joi.boolean(),
+ message: joi.string(),
+ notifiedStatus: joi.boolean(),
+ acknowledgeStatus: joi.boolean(),
+});
+
+const getAlertsByUserIdParamValidation = joi.object({
userId: joi.string().required(),
});
-const editUserBodyValidation = joi.object({
- firstname: joi.string(),
- lastname: joi.string(),
- profilePicUrl: joi.string(),
+const getAlertsByMonitorIdParamValidation = joi.object({
+ monitorId: joi.string().required(),
+});
+
+const getAlertByIdParamValidation = joi.object({
+ alertId: joi.string().required(),
+});
+
+const editAlertParamValidation = joi.object({
+ alertId: joi.string().required(),
+});
+
+const editAlertBodyValidation = joi.object({
+ status: joi.boolean(),
+ message: joi.string(),
+ notifiedStatus: joi.boolean(),
+ acknowledgeStatus: joi.boolean(),
+});
+
+const deleteAlertParamValidation = joi.object({
+ alertId: joi.string().required(),
+});
+
+//****************************************
+// Checks
+//****************************************
+
+const createCheckParamValidation = joi.object({
+ monitorId: joi.string().required(),
+});
+
+const createCheckBodyValidation = joi.object({
+ monitorId: joi.string().required(),
+ status: joi.boolean().required(),
+ responseTime: joi.number().required(),
+ statusCode: joi.number().required(),
+ message: joi.string().required(),
+});
+
+const getChecksParamValidation = joi.object({
+ monitorId: joi.string().required(),
+});
+
+const deleteChecksParamValidation = joi.object({
+ monitorId: joi.string().required(),
});
module.exports = {
@@ -47,4 +124,16 @@ module.exports = {
monitorValidation,
editUserParamValidation,
editUserBodyValidation,
+ createAlertParamValidation,
+ createAlertBodyValidation,
+ getAlertsByUserIdParamValidation,
+ getAlertsByMonitorIdParamValidation,
+ getAlertByIdParamValidation,
+ editAlertParamValidation,
+ editAlertBodyValidation,
+ deleteAlertParamValidation,
+ createCheckParamValidation,
+ createCheckBodyValidation,
+ getChecksParamValidation,
+ deleteChecksParamValidation,
};