From c468beac76add57dacaa3c44e5b661ac1b2e505d Mon Sep 17 00:00:00 2001 From: Daniel Cojocea Date: Thu, 18 Jul 2024 19:50:08 -0400 Subject: [PATCH 01/14] Initial design --- Client/src/Components/BasicTable/index.css | 3 + .../Charts/MonitorDetailsAreaChart/index.css | 19 +++ .../Charts/MonitorDetailsAreaChart/index.jsx | 6 +- Client/src/Pages/Monitors/Details/index.css | 51 +++++++ Client/src/Pages/Monitors/Details/index.jsx | 141 ++++++++++++------ Client/src/assets/icons/checkbox-green.svg | 5 + Client/src/assets/icons/checkbox-red.svg | 5 + Client/src/assets/icons/settings.svg | 4 + Client/src/index.css | 1 + 9 files changed, 189 insertions(+), 46 deletions(-) create mode 100644 Client/src/assets/icons/checkbox-green.svg create mode 100644 Client/src/assets/icons/checkbox-red.svg create mode 100644 Client/src/assets/icons/settings.svg diff --git a/Client/src/Components/BasicTable/index.css b/Client/src/Components/BasicTable/index.css index 637e5e6dd..221c66494 100644 --- a/Client/src/Components/BasicTable/index.css +++ b/Client/src/Components/BasicTable/index.css @@ -124,3 +124,6 @@ .MuiPaper-root + .MuiPagination-root .MuiPaginationItem-root.Mui-selected { background-color: var(--env-var-color-15); } +.MuiPaper-root + .MuiPagination-root div.MuiPaginationItem-root{ + user-select: none; +} diff --git a/Client/src/Components/Charts/MonitorDetailsAreaChart/index.css b/Client/src/Components/Charts/MonitorDetailsAreaChart/index.css index e69de29bb..f85a0bb04 100644 --- a/Client/src/Components/Charts/MonitorDetailsAreaChart/index.css +++ b/Client/src/Components/Charts/MonitorDetailsAreaChart/index.css @@ -0,0 +1,19 @@ +.area-tooltip { + background-color: white; + border: solid 1px var(--env-var-color-4); + border-radius: var(--env-var-radius-1); + padding: var(--env-var-spacing-1) var(--env-var-spacing-2); +} +.area-tooltip p { + margin: 0; + padding: 0; +} +.area-tooltip p:first-of-type { + color: var(--env-var-color-3); + font-size: var(--env-var-font-size-medium); +} +.area-tooltip p:last-of-type { + margin-top: 5px; + color: var(--env-var-color-5); + font-size: var(--env-var-font-size-small); +} diff --git a/Client/src/Components/Charts/MonitorDetailsAreaChart/index.jsx b/Client/src/Components/Charts/MonitorDetailsAreaChart/index.jsx index 1d1ea3758..02729a709 100644 --- a/Client/src/Components/Charts/MonitorDetailsAreaChart/index.jsx +++ b/Client/src/Components/Charts/MonitorDetailsAreaChart/index.jsx @@ -1,11 +1,12 @@ import PropTypes from "prop-types"; import { AreaChart, Area, XAxis, Tooltip, ResponsiveContainer } from "recharts"; import { NormalizeData } from "../ChartUtils"; +import "./index.css"; const CustomToolTip = ({ active, payload, label }) => { if (active && payload && payload.length) { return ( -
+

{new Date(label).toLocaleDateString("en-US", { weekday: "short", // Mon @@ -80,7 +81,7 @@ const MonitorDetailsAreaChart = ({ checks, filter }) => { data={normalizedChecks} margin={{ top: 10, - right: 30, + right: 0, left: 0, bottom: 0, }} @@ -89,6 +90,7 @@ const MonitorDetailsAreaChart = ({ checks, filter }) => { dataKey="createdAt" tickFormatter={formatDate} tick={{ fontSize: "13px" }} + tickLine={false} /> } /> { const seconds = Math.floor(ms / 1000); @@ -30,7 +35,7 @@ const formatDuration = (ms) => { const StatBox = ({ title, value }) => { return ( - + {title} {value} @@ -103,6 +108,7 @@ const DetailsPage = () => { }, [monitorId, authToken]); const theme = useTheme(); + const navigate = useNavigate(); /** * Function to calculate uptime duration based on the most recent check. @@ -163,52 +169,99 @@ const DetailsPage = () => { padding: `${theme.content.pY} ${theme.content.pX}`, }} > -

- - - -
-
} + onClick={() => navigate("/monitors")} + sx={{ + backgroundColor: "#f4f4f4", + mb: theme.gap.medium, + px: theme.gap.ml, + "& svg.MuiSvgIcon-root": { + pr: theme.gap.small, + }, }} - > - - Response Times - - + /> + + + + + + {monitor.url?.replace(/^https?:\/\//, "") || "..."} + + + Your site is up.{" "} + Checking every 5 minutes. Last time checked 2 minutes ago. + +
-
- -
- - History - - + + + + + + Response Times + + +
); }; diff --git a/Client/src/assets/icons/checkbox-green.svg b/Client/src/assets/icons/checkbox-green.svg new file mode 100644 index 000000000..dd5676298 --- /dev/null +++ b/Client/src/assets/icons/checkbox-green.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Client/src/assets/icons/checkbox-red.svg b/Client/src/assets/icons/checkbox-red.svg new file mode 100644 index 000000000..3c43a2042 --- /dev/null +++ b/Client/src/assets/icons/checkbox-red.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Client/src/assets/icons/settings.svg b/Client/src/assets/icons/settings.svg new file mode 100644 index 000000000..d8057286c --- /dev/null +++ b/Client/src/assets/icons/settings.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Client/src/index.css b/Client/src/index.css index 61c961dad..337e490f5 100644 --- a/Client/src/index.css +++ b/Client/src/index.css @@ -56,6 +56,7 @@ --env-var-width-2: 360px; --env-var-height-1: 100vh; + --env-var-height-2: 34px; --env-var-spacing-1: 12px; --env-var-spacing-1-plus: 16px; From e0539a6ae32ab4edc49148e4837d5f2cd94a9a3a Mon Sep 17 00:00:00 2001 From: Daniel Cojocea Date: Thu, 18 Jul 2024 20:05:28 -0400 Subject: [PATCH 02/14] Changed style to reflect data from monitor --- Client/src/Pages/Monitors/Details/index.css | 4 +- Client/src/Pages/Monitors/Details/index.jsx | 44 +++++++++++++++++++-- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/Client/src/Pages/Monitors/Details/index.css b/Client/src/Pages/Monitors/Details/index.css index 370f213fb..1abd12ef9 100644 --- a/Client/src/Pages/Monitors/Details/index.css +++ b/Client/src/Pages/Monitors/Details/index.css @@ -33,9 +33,7 @@ .monitor-details p.MuiTypography-root { color: var(--env-var-color-2); } -.monitor-details p.MuiTypography-root span.MuiTypography-root { - color: var(--env-var-color-17); -} + .monitor-details .stat-box { flex: 1; min-width: 100px; diff --git a/Client/src/Pages/Monitors/Details/index.jsx b/Client/src/Pages/Monitors/Details/index.jsx index 8f4d24422..8ccf15d01 100644 --- a/Client/src/Pages/Monitors/Details/index.jsx +++ b/Client/src/Pages/Monitors/Details/index.jsx @@ -33,6 +33,33 @@ const formatDuration = (ms) => { return dateStr; }; +const formatDurationRounded = (ms) => { + const seconds = Math.floor(ms / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + + let time = ""; + if (days > 0) { + time += `${days} day${days !== 1 ? "s" : ""}`; + return time; + } + if (hours > 0) { + time += `${hours} hour${hours !== 1 ? "s" : ""}`; + return time; + } + if (minutes > 0) { + time += `${minutes} minute${minutes !== 1 ? "s" : ""}`; + return time; + } + if (seconds > 0) { + time += `${seconds} second${seconds !== 1 ? "s" : ""}`; + return time; + } + + return time; +}; + const StatBox = ({ title, value }) => { return ( @@ -185,14 +212,25 @@ const DetailsPage = () => { /> - + {monitor?.status ? : } {monitor.url?.replace(/^https?:\/\//, "") || "..."} - Your site is up.{" "} - Checking every 5 minutes. Last time checked 2 minutes ago. + + Your site is {monitor?.status ? "up" : "down"}. + {" "} + Checking every {formatDurationRounded(monitor?.interval)}. Last + time checked{" "} + {formatDurationRounded(getLastChecked(monitor?.checks))} ago.
); }; - +Register.propTypes = { + isAdmin: PropTypes.bool, +}; export default Register; From 505c6bf5de52411732fab809a0ef3619555b2110 Mon Sep 17 00:00:00 2001 From: MuhammadKhalilzadeh Date: Fri, 19 Jul 2024 21:44:40 +0330 Subject: [PATCH 12/14] Nodemailer implemented --- Server/index.js | 113 ++++++++++++++++++ Server/package-lock.json | 51 ++++++++ Server/package.json | 1 + Server/templates/employeeActivation.mjml | 6 +- Server/templates/noIncidentsThisWeek.mjml | 4 +- Server/templates/passwordReset.mjml | 90 +++++++------- Server/templates/serverIsDown.mjml | 126 +++++++++----------- Server/templates/serverIsUp.mjml | 138 ++++++++++------------ Server/templates/welcomeEmail.mjml | 92 +++++++-------- 9 files changed, 371 insertions(+), 250 deletions(-) diff --git a/Server/index.js b/Server/index.js index 9cd8d57ec..cd25e8399 100644 --- a/Server/index.js +++ b/Server/index.js @@ -13,6 +13,80 @@ const { handleErrors } = require("./middleware/handleErrors"); const queueRouter = require("./routes/queueRoute"); const JobQueue = require("./service/jobQueue"); const pageSpeedCheckRouter = require("./routes/pageSpeedCheckRoute"); +const nodemailer = require("nodemailer"); + +const fs = require("fs"); +const path = require("path"); +const { compile } = require("handlebars"); +const { mjml2html } = require("mjml"); + +// Fetching Templates + +// Welcome Email Template +const welcomeEmailTemplatePath = path.join( + __dirname, + "./templates/welcomeEmail.mjml" +); +const welcomeEmailTemplateContent = fs.readFileSync( + welcomeEmailTemplatePath, + "utf8" +); +const welcomeEmailTemplate = compile(welcomeEmailTemplateContent); + +// Employee Activation Email Template +const employeeActivationTemplatePath = path.join( + __dirname, + "./templates/employeeActivation.mjml" +); +const employeeActivationTemplateContent = fs.readFileSync( + employeeActivationTemplatePath, + "utf8" +); +const employeeActivation = compile(employeeActivationTemplateContent); + +// No Incident This Week Template +const noIncidentsThisWeekTemplatePath = path.join( + __dirname, + "./templates/noIncidentsThisWeek.mjml" +); +const noIncidentsThisWeekTemplateContent = fs.readFileSync( + noIncidentsThisWeekTemplatePath, + "utf8" +); +const noIncidentsThisWeek = compile(noIncidentsThisWeekTemplateContent); + +// Server is Down Template +const serverIsDownTemplatePath = path.join( + __dirname, + "./templates/serverIsDown.mjml" +); +const serverIsDownTemplateContent = fs.readFileSync( + serverIsDownTemplatePath, + "utf8" +); +const serverIsDown = compile(serverIsDownTemplateContent); + +// Server is Up Template +const serverIsUpTemplatePath = path.join( + __dirname, + "./templates/serverIsUp.mjml" +); +const serverIsUpTemplateContent = fs.readFileSync( + serverIsUpTemplatePath, + "utf8" +); +const serverIsUp = compile(serverIsUpTemplateContent); + +// Password Reset Template +const passwordResetTemplatePath = path.join( + __dirname, + "./templates/passwordReset.mjml" +); +const passwordResetTemplateContent = fs.readFileSync( + passwordResetTemplatePath, + "utf8" +); +const passwordReset = compile(passwordResetTemplateContent); // Need to wrap server setup in a function to handle async nature of JobQueue const startApp = async () => { @@ -87,6 +161,45 @@ const startApp = async () => { } }); + // Nodemailer code here + const transporter = nodemailer.createTransport({ + host: "127.0.0.1", + port: 1025, + auth: { + user: "project.1", + pass: "secret.1", + }, + }); + + app.use("/api/v1/mail", (req, res) => { + console.log("Started"); + // Replacing varibales + const context = { name: "Alex" }; + + // The Template must be replaced according to the scenario and the response we need to give + const mjml = welcomeEmailTemplate(context); + const html = mjml2html(mjml); + + // Define mail options + const mailOptions = { + from: "BlueWave Uptime ", // sender address + to: "muhammadkhalilzadeh1998@gmailc.com", // list of receivers + subject: "Testing template emails", // Subject line + html: html, // html body + }; + + // Send mail with defined transport object + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + return res + .status(500) + .send({ message: "Error sending email", error: error }); + } + console.log(info); + res.status(200).send({ message: "Email sent successfully", info: info }); + }); + }); + /** * Error handler middleware * Should be called last diff --git a/Server/package-lock.json b/Server/package-lock.json index 8c437da48..17f15fc81 100644 --- a/Server/package-lock.json +++ b/Server/package-lock.json @@ -16,6 +16,7 @@ "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", + "handlebars": "^4.7.8", "helmet": "^7.1.0", "joi": "^17.13.1", "jsonwebtoken": "9.0.2", @@ -2405,6 +2406,51 @@ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==" }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/handlebars/node_modules/uglify-js": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.0.tgz", + "integrity": "sha512-wNKHUY2hYYkf6oSFfhwwiHo4WCHzHmzcXsqXYTN9ja3iApYIFbb2U6ics9hBcYLHcYGQoAlwnZlTrf3oF+BL/Q==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/handlebars/node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -3703,6 +3749,11 @@ "node": ">= 0.6" } }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", diff --git a/Server/package.json b/Server/package.json index d6d8c8d72..879aa80b5 100644 --- a/Server/package.json +++ b/Server/package.json @@ -18,6 +18,7 @@ "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", + "handlebars": "^4.7.8", "helmet": "^7.1.0", "joi": "^17.13.1", "jsonwebtoken": "9.0.2", diff --git a/Server/templates/employeeActivation.mjml b/Server/templates/employeeActivation.mjml index 99d08d489..7fcaebfc2 100644 --- a/Server/templates/employeeActivation.mjml +++ b/Server/templates/employeeActivation.mjml @@ -16,10 +16,10 @@ -

Hello Alex!

+

Hello {{name}}!

One of the admins created an account for you on the BlueWave Uptime server.

You can go ahead and create your account using this link.

-

https://example.com

+

{{link}}

Thank you.

@@ -31,4 +31,4 @@
- + \ No newline at end of file diff --git a/Server/templates/noIncidentsThisWeek.mjml b/Server/templates/noIncidentsThisWeek.mjml index 0c2801e89..960a876fe 100644 --- a/Server/templates/noIncidentsThisWeek.mjml +++ b/Server/templates/noIncidentsThisWeek.mjml @@ -20,7 +20,7 @@ -

Hello Alex!

+

Hello {{name}}!

There were no incidents this week. Good job!

Current monitors:

Google: 100% availability

@@ -35,4 +35,4 @@
- + \ No newline at end of file diff --git a/Server/templates/passwordReset.mjml b/Server/templates/passwordReset.mjml index 7043401f3..de1e23138 100644 --- a/Server/templates/passwordReset.mjml +++ b/Server/templates/passwordReset.mjml @@ -1,51 +1,43 @@ - - - - - - - - - - - - - Message from BlueWave Uptime Service - - - - - - -

Hello Alex!

-

- You are receiving this email because a password reset request - has been made for gorkem.cetin@bluewavelabs.ca. Please use the - code below on the site to reset your password. -

-

- Verification Code: 4CCDFC45 -

-

If you didn't request this, please ignore this email.

+ + + + + + + + + + + + + Message from BlueWave Uptime Service + + + + + + +

Hello {{name}}!

+

+ You are receiving this email because a password reset request + has been made for gorkem.cetin@bluewavelabs.ca. Please use the + code below on the site to reset your password. +

+

+ Verification Code: {{verificationCode}} +

+

If you didn't request this, please ignore this email.

-

Thank you.

-
-
- - - -

This email was sent by BlueWave Uptime.

-
-
-
-
-
\ No newline at end of file +

Thank you.

+ + + + + +

This email was sent by BlueWave Uptime.

+
+
+ + + \ No newline at end of file diff --git a/Server/templates/serverIsDown.mjml b/Server/templates/serverIsDown.mjml index 95df602f5..3caa6549c 100644 --- a/Server/templates/serverIsDown.mjml +++ b/Server/templates/serverIsDown.mjml @@ -1,71 +1,57 @@ - - - - - - - - - - - - - Message from BlueWave Uptime Service - - - - - Google.com is down - - - - - - - -

Hello Alex!

-

- We detected an incident on one of your monitors. Your service is - currently down. We'll send a message to you once it is up again. -

-

- Monitor name: Google.com -

-

- URL: https://google.com -

-

- Problem: Connection timeout -

-

- Start date: Jun 8, 2024 8:15pm -

-
-
- - - - View incident details - - -

This email was sent by BlueWave Uptime.

-
-
-
-
-
\ No newline at end of file + + + + + + + + + + + + + Message from BlueWave Uptime Service + + + + + Google.com is down + + + + + + + +

Hello {{name}}!

+

+ We detected an incident on one of your monitors. Your service is + currently down. We'll send a message to you once it is up again. +

+

+ Monitor name: {{monitor}} +

+

+ URL: {{url}} +

+

+ Problem: {{problem}} +

+

+ Start date: {{startDate}} +

+
+
+ + + + View incident details + + +

This email was sent by BlueWave Uptime.

+
+
+
+
+ \ No newline at end of file diff --git a/Server/templates/serverIsUp.mjml b/Server/templates/serverIsUp.mjml index aa2caa5ba..9e73a8559 100644 --- a/Server/templates/serverIsUp.mjml +++ b/Server/templates/serverIsUp.mjml @@ -1,77 +1,63 @@ - - - - - - - - - - - - - Message from BlueWave Uptime Service - - - - - Google.com is up - - - - - - - -

Hello Alex!

-

- Your latest incident is resolved and your monitored service is - up again. -

-

- Monitor name: Google.com -

-

- URL: https://google.com -

-

- Problem: Connection timeout -

-

- Start date: Jun 8, 2024 8:15pm -

-

- Resolved date: Jun 8, 2024 8:15pm -

-

- Duration:3 minutes and 15 seconds -

-
-
- - - - View incident details - - -

This email was sent by BlueWave Uptime.

-
-
-
-
-
\ No newline at end of file + + + + + + + + + + + + + Message from BlueWave Uptime Service + + + + + {{monitor}} is up + + + + + + + +

Hello {{name}}!

+

+ Your latest incident is resolved and your monitored service is + up again. +

+

+ Monitor name: {{monitor}} +

+

+ URL: {{url}} +

+

+ Problem: {{problem}} +

+

+ Start date: {{startDate}} +

+

+ Resolved date: {{resolvedDate}} +

+

+ Duration:{{duration}} +

+
+
+ + + + View incident details + + +

This email was sent by BlueWave Uptime.

+
+
+
+
+ \ No newline at end of file diff --git a/Server/templates/welcomeEmail.mjml b/Server/templates/welcomeEmail.mjml index 62e5333d8..cb71bb34c 100644 --- a/Server/templates/welcomeEmail.mjml +++ b/Server/templates/welcomeEmail.mjml @@ -1,51 +1,43 @@ - - - - - - - - - - - - - Message from BlueWave Uptime Service - - - - - - -

Hello Alex!

-

- Thank you for trying out BlueWave Uptime! We developed it with - great care to meet our own needs, and we're excited to share it - with you. -

-

- BlueWave Uptime is an automated way of checking whether a - service such as a website or an application is available or not. -

-

We hope you find our service as valuable as we do.

-

Thank you.

-
-
- - - -

This email was sent by BlueWave Uptime.

-
-
-
-
-
\ No newline at end of file + + + + + + + + + + + + + Message from BlueWave Uptime Service + + + + + + +

Hello {{name}}!

+

+ Thank you for trying out BlueWave Uptime! We developed it with + great care to meet our own needs, and we're excited to share it + with you. +

+

+ BlueWave Uptime is an automated way of checking whether a + service such as a website or an application is available or not. +

+

We hope you find our service as valuable as we do.

+

Thank you.

+
+
+ + + +

This email was sent by BlueWave Uptime.

+
+
+
+
+ \ No newline at end of file From 50b5c0d9f5390529deb23fd2195bd72363bf5d6f Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 19 Jul 2024 11:18:23 -0700 Subject: [PATCH 13/14] Fix refactoring bug, shadowing variable --- Client/src/Pages/Auth/Register/Register.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Client/src/Pages/Auth/Register/Register.jsx b/Client/src/Pages/Auth/Register/Register.jsx index e029caacc..614c47c97 100644 --- a/Client/src/Pages/Auth/Register/Register.jsx +++ b/Client/src/Pages/Auth/Register/Register.jsx @@ -42,8 +42,8 @@ const Register = ({ isAdmin }) => { const handleSubmit = async (e) => { e.preventDefault(); - const form = { ...form, role: isAdmin ? "admin" : "user" }; - const { error } = credentials.validate(form, { + const registerForm = { ...form, role: isAdmin ? "admin" : "user" }; + const { error } = credentials.validate(registerForm, { abortEarly: false, context: { password: form.password }, }); @@ -62,8 +62,8 @@ const Register = ({ isAdmin }) => { : "Error validating data.", }); } else { - delete form.confirm; - const action = await dispatch(register(form)); + delete registerForm.confirm; + const action = await dispatch(register(registerForm)); if (action.payload.success) { const token = action.payload.data; localStorage.setItem("token", token); From d541dfb57beb89e007ad750947abe6616b5ee0c6 Mon Sep 17 00:00:00 2001 From: MuhammadKhalilzadeh Date: Fri, 19 Jul 2024 22:39:12 +0330 Subject: [PATCH 14/14] emailService.js created, env variables added --- Server/index.js | 87 ++--------------------- Server/package-lock.json | 9 +++ Server/package.json | 1 + Server/service/emailService.js | 125 +++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 81 deletions(-) create mode 100644 Server/service/emailService.js diff --git a/Server/index.js b/Server/index.js index cd25e8399..306776643 100644 --- a/Server/index.js +++ b/Server/index.js @@ -15,78 +15,7 @@ const JobQueue = require("./service/jobQueue"); const pageSpeedCheckRouter = require("./routes/pageSpeedCheckRoute"); const nodemailer = require("nodemailer"); -const fs = require("fs"); -const path = require("path"); -const { compile } = require("handlebars"); -const { mjml2html } = require("mjml"); - -// Fetching Templates - -// Welcome Email Template -const welcomeEmailTemplatePath = path.join( - __dirname, - "./templates/welcomeEmail.mjml" -); -const welcomeEmailTemplateContent = fs.readFileSync( - welcomeEmailTemplatePath, - "utf8" -); -const welcomeEmailTemplate = compile(welcomeEmailTemplateContent); - -// Employee Activation Email Template -const employeeActivationTemplatePath = path.join( - __dirname, - "./templates/employeeActivation.mjml" -); -const employeeActivationTemplateContent = fs.readFileSync( - employeeActivationTemplatePath, - "utf8" -); -const employeeActivation = compile(employeeActivationTemplateContent); - -// No Incident This Week Template -const noIncidentsThisWeekTemplatePath = path.join( - __dirname, - "./templates/noIncidentsThisWeek.mjml" -); -const noIncidentsThisWeekTemplateContent = fs.readFileSync( - noIncidentsThisWeekTemplatePath, - "utf8" -); -const noIncidentsThisWeek = compile(noIncidentsThisWeekTemplateContent); - -// Server is Down Template -const serverIsDownTemplatePath = path.join( - __dirname, - "./templates/serverIsDown.mjml" -); -const serverIsDownTemplateContent = fs.readFileSync( - serverIsDownTemplatePath, - "utf8" -); -const serverIsDown = compile(serverIsDownTemplateContent); - -// Server is Up Template -const serverIsUpTemplatePath = path.join( - __dirname, - "./templates/serverIsUp.mjml" -); -const serverIsUpTemplateContent = fs.readFileSync( - serverIsUpTemplatePath, - "utf8" -); -const serverIsUp = compile(serverIsUpTemplateContent); - -// Password Reset Template -const passwordResetTemplatePath = path.join( - __dirname, - "./templates/passwordReset.mjml" -); -const passwordResetTemplateContent = fs.readFileSync( - passwordResetTemplatePath, - "utf8" -); -const passwordReset = compile(passwordResetTemplateContent); +const emailService = require("./service/emailService"); // Need to wrap server setup in a function to handle async nature of JobQueue const startApp = async () => { @@ -163,11 +92,11 @@ const startApp = async () => { // Nodemailer code here const transporter = nodemailer.createTransport({ - host: "127.0.0.1", - port: 1025, + host: process.env.EMAIL_SERVICE_HOST, + port: process.env.EMAIL_SERVICE_PORT, auth: { - user: "project.1", - pass: "secret.1", + user: process.env.EMAIL_SERVICE_USERNAME, + pass: process.env.EMAIL_SERVICE_PASSWORD, }, }); @@ -176,16 +105,12 @@ const startApp = async () => { // Replacing varibales const context = { name: "Alex" }; - // The Template must be replaced according to the scenario and the response we need to give - const mjml = welcomeEmailTemplate(context); - const html = mjml2html(mjml); - // Define mail options const mailOptions = { from: "BlueWave Uptime ", // sender address to: "muhammadkhalilzadeh1998@gmailc.com", // list of receivers subject: "Testing template emails", // Subject line - html: html, // html body + html: emailService.sendWelcomeEmail(context), // html body }; // Send mail with defined transport object diff --git a/Server/package-lock.json b/Server/package-lock.json index 17f15fc81..31ac86ad5 100644 --- a/Server/package-lock.json +++ b/Server/package-lock.json @@ -24,6 +24,7 @@ "mjml": "^1.3.4", "mongoose": "^8.3.3", "multer": "1.4.5-lts.1", + "nodemailer": "^6.9.14", "ping": "0.4.4", "sharp": "0.33.4", "winston": "^3.13.0" @@ -3816,6 +3817,14 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, + "node_modules/nodemailer": { + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz", + "integrity": "sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nodemon": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", diff --git a/Server/package.json b/Server/package.json index 879aa80b5..bc3a4f299 100644 --- a/Server/package.json +++ b/Server/package.json @@ -26,6 +26,7 @@ "mjml": "^1.3.4", "mongoose": "^8.3.3", "multer": "1.4.5-lts.1", + "nodemailer": "^6.9.14", "ping": "0.4.4", "sharp": "0.33.4", "winston": "^3.13.0" diff --git a/Server/service/emailService.js b/Server/service/emailService.js new file mode 100644 index 000000000..235913b18 --- /dev/null +++ b/Server/service/emailService.js @@ -0,0 +1,125 @@ +const fs = require("fs"); +const path = require("path"); +const { compile } = require("handlebars"); +const { mjml2html } = require("mjml"); + +// Fetching Templates + +// Welcome Email Template +const welcomeEmailTemplatePath = path.join( + __dirname, + "../templates/welcomeEmail.mjml" +); +const welcomeEmailTemplateContent = fs.readFileSync( + welcomeEmailTemplatePath, + "utf8" +); +const welcomeEmailTemplate = compile(welcomeEmailTemplateContent); + +// Employee Activation Email Template +const employeeActivationTemplatePath = path.join( + __dirname, + "../templates/employeeActivation.mjml" +); +const employeeActivationTemplateContent = fs.readFileSync( + employeeActivationTemplatePath, + "utf8" +); +const employeeActivation = compile(employeeActivationTemplateContent); + +// No Incident This Week Template +const noIncidentsThisWeekTemplatePath = path.join( + __dirname, + "../templates/noIncidentsThisWeek.mjml" +); +const noIncidentsThisWeekTemplateContent = fs.readFileSync( + noIncidentsThisWeekTemplatePath, + "utf8" +); +const noIncidentsThisWeek = compile(noIncidentsThisWeekTemplateContent); + +// Server is Down Template +const serverIsDownTemplatePath = path.join( + __dirname, + "../templates/serverIsDown.mjml" +); +const serverIsDownTemplateContent = fs.readFileSync( + serverIsDownTemplatePath, + "utf8" +); +const serverIsDown = compile(serverIsDownTemplateContent); + +// Server is Up Template +const serverIsUpTemplatePath = path.join( + __dirname, + "../templates/serverIsUp.mjml" +); +const serverIsUpTemplateContent = fs.readFileSync( + serverIsUpTemplatePath, + "utf8" +); +const serverIsUp = compile(serverIsUpTemplateContent); + +// Password Reset Template +const passwordResetTemplatePath = path.join( + __dirname, + "../templates/passwordReset.mjml" +); +const passwordResetTemplateContent = fs.readFileSync( + passwordResetTemplatePath, + "utf8" +); +const passwordReset = compile(passwordResetTemplateContent); + +// *** Application specific functions *** + +function sendWelcomeEmail(context) { + const mjml = welcomeEmailTemplate(context); + const html = mjml2html(mjml); + + return html; +} + +function sendEmployeeActivationEmail(context) { + const mjml = employeeActivation(context); + const html = mjml2html(mjml); + + return html; +} + +function sendNoIncidentsThisWeekEmail(context) { + const mjml = noIncidentsThisWeek(context); + const html = mjml2html(mjml); + + return html; +} + +function sendServerIsDownEmail(context) { + const mjml = serverIsDown(context); + const html = mjml2html(mjml); + + return html; +} + +function sendServerIsUpEmail(context) { + const mjml = serverIsUp(context); + const html = mjml2html(mjml); + + return html; +} + +function sendPasswordResetEmail(context) { + const mjml = passwordReset(context); + const html = mjml2html(mjml); + + return html; +} + +module.exports = { + sendWelcomeEmail, + sendEmployeeActivationEmail, + sendNoIncidentsThisWeekEmail, + sendServerIsDownEmail, + sendServerIsUpEmail, + sendPasswordResetEmail, +};