From c234aa361685b54f8e095f7727d248b7b0027a4d Mon Sep 17 00:00:00 2001 From: newtbot Date: Sat, 27 Jan 2024 04:52:02 +0800 Subject: [PATCH] Add nodemailer configuration and console.log statement Update formAJAX function to log data from the server Add getUserByEmail and checkEmail functions Update profile.ejs to require login Update addSensorData function to emit new sensor data Update api.css with styling changes Update token route to generate and send token email Update authChecker middleware to allow user and token routes --- consumerWebsite/functions/nodeMail.js | 82 +++++++ consumerWebsite/functions/sensorData.js | 10 +- consumerWebsite/functions/user.js | 24 ++ consumerWebsite/middleware/authChecker.js | 16 +- consumerWebsite/modules/nodemailer.js | 1 + consumerWebsite/public/css/api.css | 22 +- consumerWebsite/public/js/app.js | 2 +- consumerWebsite/routes/auth.js | 54 +++-- consumerWebsite/routes/token.js | 28 ++- consumerWebsite/views/api.ejs | 156 ++++++------ consumerWebsite/views/contact.ejs | 14 +- consumerWebsite/views/index.ejs | 69 +++++- consumerWebsite/views/logintop.ejs | 25 +- consumerWebsite/views/profile.ejs | 6 +- example.html | 277 ++++++++++++++++++++++ 15 files changed, 638 insertions(+), 148 deletions(-) create mode 100644 consumerWebsite/functions/nodeMail.js create mode 100644 example.html diff --git a/consumerWebsite/functions/nodeMail.js b/consumerWebsite/functions/nodeMail.js new file mode 100644 index 0000000..f81a8c4 --- /dev/null +++ b/consumerWebsite/functions/nodeMail.js @@ -0,0 +1,82 @@ +const { transporter } = require("../modules/nodemailer"); +const path = require("path"); +require("dotenv").config({ path: path.resolve(__dirname, "../.env") }); + +/* +var message = { + from: "sender@server.com", + to: "receiver@sender.com", + subject: "Message title", + text: "Plaintext version of the message", + html: "

HTML version of the message

", +}; +//send mail with defined transport object +transporter.sendMail(data[, callback]) + +*/ + +async function sendContactEmail(email, name, message) { + console.log(email, name, message); + + try { + let contactMessage = await transporter.sendMail({ + to: process.env.euser, + subject: "Contact us Message", + html: ` +

Contact us Message

+

From: ${name}

+

User Email: ${email}

+

Message: ${message}

+

Thank you for contacting us. We will get back to you as soon as possible.

+

Regards,

+

EcoSaver Team

+

EcoSaver Website

+

Please do not reply to this email.

+ `, + }); + transporter.sendMail({ contactMessage }, function (error, info) { + if (error) { + console.log(error); + } else { + console.log("Email sent: " + info.response); + } + }); + } catch (error) { + console.error(error); + } +} + +async function sendTokenEmail(email, token) { + + try { + let tokenMessage = await transporter.sendMail({ + to: email, + from: process.env.euser, + subject: "API Token", + html: ` +

API Token

+

Token: ${token}

+

Please do not lose this token and do not share your token with anyone!

+

Thank you for using EcoSaver.

+

Regards,

+

EcoSaver Team

+

EcoSaver Website

+

Please do not reply to this email.

+ + `, + }); + transporter.sendMail({ tokenMessage }, function (error, info) { + if (error) { + console.log(error); + } else { + console.log("Email sent: " + info.response); + } + }); + } catch (error) { + console.error(error); + } +} + + + +module.exports = { sendContactEmail , sendTokenEmail }; diff --git a/consumerWebsite/functions/sensorData.js b/consumerWebsite/functions/sensorData.js index f59c28b..20a4176 100644 --- a/consumerWebsite/functions/sensorData.js +++ b/consumerWebsite/functions/sensorData.js @@ -18,7 +18,6 @@ async function getSensorData() { const sensorData = await sensorDataModel.findAll(); return sensorData; } -let dataArray = []; async function addSensorData(id_sensor, id_location, sensordata) { const sensorData = await sensorDataModel.create({ sensorid: id_sensor, @@ -26,11 +25,10 @@ async function addSensorData(id_sensor, id_location, sensordata) { measurement: sensordata.measurement, }); //console.log("sensorData", sensorData); - //console.log("sensorData", sensordata); - dataArray.push(sensordata); - console.log("dataArray", dataArray); + //console.log("sensorData", sensordata.measurement); + - io().emit('sensorData:new', dataArray) + io().emit('sensorData:new', sensordata) return sensorData; } @@ -68,7 +66,7 @@ async function getSensorDataById(id) { async function getLatestData() { const sensorData = await sensorDataModel.findAll({ - limit: 1, + limit: 6, order: [["createdAt", "DESC"]], }); return sensorData; diff --git a/consumerWebsite/functions/user.js b/consumerWebsite/functions/user.js index c94e183..d79d86d 100644 --- a/consumerWebsite/functions/user.js +++ b/consumerWebsite/functions/user.js @@ -20,6 +20,16 @@ async function getUserByID(userid) { return userRes; } +async function getUserByEmail(email) { + let userRes = await userModel.findOne({ + where: { + email: email, + }, + }); + if (!userRes) return false; + return userRes; +} + //api/v0/auth/register /* Registering new user 1) req.body is taken from html form or wtv @@ -131,9 +141,23 @@ async function updateProfile(user, body) { } } +async function checkEmail(email) { + let emailRes = await userModel.findOne({ + where: { + email: email, + }, + }); + if (!emailRes) return false; + return true; + +} + + module.exports = { getUserByID, + getUserByEmail, addUser, loginUser, updateProfile, + checkEmail }; \ No newline at end of file diff --git a/consumerWebsite/middleware/authChecker.js b/consumerWebsite/middleware/authChecker.js index cc9b3f9..300cf4d 100644 --- a/consumerWebsite/middleware/authChecker.js +++ b/consumerWebsite/middleware/authChecker.js @@ -19,12 +19,24 @@ async function auth(req, res, next) { const route = req.originalUrl.split("?")[0]; // Removing query parameters //if route is from user/ and permission is canRead allow it to do CRUD - if (route.includes("/user/") && token.permission === "canRead") { + if (route.includes("/user/") || route.includes("/token/") && token.permission === "canRead") { + console.log("user route"); return next(); } - if ((req.method === "GET" && token.permission === "canRead") || (["GET", "POST", "PUT", "DELETE"].includes(req.method) && token.permission === "canWrite")) { + if ((req.method === "GET" && token.permission === "canRead")){ + console.log("wtf you shldnt be here"); return next(); } + if (["GET", "POST", "PUT", "DELETE"].includes(req.method) && token.permission === "canWrite") { + console.log("wtf you shldnt be here"); + return next(); + } + /* + if ((req.method === "GET" && token.permission === "canRead") || + (["GET", "POST", "PUT", "DELETE"].includes(req.method) && token.permission === "canWrite")) { + return next(); + } + */ throw permissionError diff --git a/consumerWebsite/modules/nodemailer.js b/consumerWebsite/modules/nodemailer.js index 64e745f..a6d3cc2 100644 --- a/consumerWebsite/modules/nodemailer.js +++ b/consumerWebsite/modules/nodemailer.js @@ -2,6 +2,7 @@ const nodemailer = require("nodemailer"); const dotenv = require("dotenv"); const path = require('path') require('dotenv').config({ path: path.resolve(__dirname, '../.env') }) +//.env let transporter = nodemailer.createTransport({ service: 'gmail', diff --git a/consumerWebsite/public/css/api.css b/consumerWebsite/public/css/api.css index f5d527e..a13b630 100644 --- a/consumerWebsite/public/css/api.css +++ b/consumerWebsite/public/css/api.css @@ -528,22 +528,24 @@ body.one-content-column-version .content thead { .generate-key-button { - float: right; /* Align the button to the right */ - margin-right: 85%; - margin-top: -40px; /* Adjust the margin-top value based on your layout */ - /* Add any additional styling you want for the button */ -} - -#content-get-api .generate-key-button { + margin-top: -40px; + margin-left: 25px; background-color: #4caf50; /* Green background color */ - color: white; /* White text color */ + color: #ffffff; padding: 5px 11px; /* Padding for the button */ border: none; /* Remove button border */ border-radius: 5px; /* Add border-radius for rounded corners */ cursor: pointer; /* Add pointer cursor on hover */ font-size: 14px; /* Font size */ } +.api-form { + margin-top: 20px; + margin-left: 25px; +} -#content-get-api .generate-key-button:hover { +.generate-key-button:hover { background-color: #45a049; /* Darker green on hover */ -} \ No newline at end of file +} + + + diff --git a/consumerWebsite/public/js/app.js b/consumerWebsite/public/js/app.js index 0ffd8a2..90da0c3 100644 --- a/consumerWebsite/public/js/app.js +++ b/consumerWebsite/public/js/app.js @@ -285,7 +285,7 @@ function formAJAX(btn, del) { //console.log('Data being sent to', $form.attr('action'), formData) app.api[method]($form.attr("action"), formData, function (error, data) { - //console.log('Data back from the server', error, data) + console.log('Data back from the server', error, data) app.util.actionMessage(data.message, $form, error ? "danger" : "success"); //re-populate table if (!error) { $form.trigger("reset"); diff --git a/consumerWebsite/routes/auth.js b/consumerWebsite/routes/auth.js index dd16dc1..276a5a2 100644 --- a/consumerWebsite/routes/auth.js +++ b/consumerWebsite/routes/auth.js @@ -1,4 +1,5 @@ -const { addUser, loginUser } = require("../functions/user"); +const { addUser, loginUser, checkEmail } = require("../functions/user"); +const { sendContactEmail } = require("../functions/nodeMail"); const express = require("express"); const router = express.Router(); @@ -12,12 +13,11 @@ router.post("/register", async (req, res, next) => { error.message = "The user failed to be craated"; error.status = 400; return next(error); + } else { + return res.json({ + message: "User created successfully", + }); } - else{ - return res.json({ - message: "User created successfully", - }); - } } catch (error) { console.error(error); next(error); @@ -29,20 +29,18 @@ router.post("/login", async (req, res, next) => { try { let Res = await loginUser(req.body); if (Res == false) { - let error = new Error("User Login Failed"); + let error = new Error("User Login Failed"); error.status = 400; return next(error); + } else { + //pass res back to form to be set in local storage + return res.json({ + message: "User login successfully", + token: Res.token, + userid: Res.userid, + username: Res.username, + }); } - else{ - //pass res back to form to be set in local storage - return res.json({ - message: "User login successfully", - token: Res.token, - userid: Res.userid, - username: Res.username, - }); - - } } catch (error) { console.error(error); next(error); @@ -52,8 +50,26 @@ router.post("/login", async (req, res, next) => { //contact //auth/contact router.post("/contact", async (req, res, next) => { - + try { + //console.log(req.body); + let Res = await checkEmail(req.body.email); + if (!Res) { + let error = new Error("Email not found"); + error.status = 400; + return next(error); + } + else{ + //console.log(Res); + sendContactEmail(req.body.email, req.body.name, req.body.message); + return res.json({ + message: "Email sent successfully", + }); + + } + } catch (error) { + console.error(error); + next(error); + } }); module.exports = router; - diff --git a/consumerWebsite/routes/token.js b/consumerWebsite/routes/token.js index f6d4b46..18b8df0 100644 --- a/consumerWebsite/routes/token.js +++ b/consumerWebsite/routes/token.js @@ -1,4 +1,7 @@ const { addToken } = require("../functions/api"); +const { checkEmail , getUserByEmail } = require("../functions/user"); +const { sendTokenEmail } = require("../functions/nodeMail"); + const express = require("express"); @@ -15,8 +18,29 @@ const router = express.Router(); //'{"userid": "5", "permission": "canRead" ,}' router.post("/new", async (req, res, next) => { try { - const token = await addToken(req.body.userid, req.body.permission , "2204-01-24 07:34:36" ); - res.json({token: token}); + //console.log(req.body); + const Res = await checkEmail(req.body.email); + if (!Res) { + let error = new Error("Email not found"); + error.status = 400; + return next(error); + } + else + { + //console.log("email found"); + let userid = await getUserByEmail(req.body.email); + if (!userid) return false; + + const token = await addToken(userid.id, "canRead" , "2204-01-24 07:34:36" ); + if (!token) return false; + sendTokenEmail(req.body.email, token); + res.json({ + message: "Token generated successfully and sent to email", + }) + + } + //const token = await addToken(req.body.userid, "canRead" , "2204-01-24 07:34:36" ); + //res.json({token: token}); } catch (error) { console.error(error); next(error); diff --git a/consumerWebsite/views/api.ejs b/consumerWebsite/views/api.ejs index e3521e4..4e90eaf 100644 --- a/consumerWebsite/views/api.ejs +++ b/consumerWebsite/views/api.ejs @@ -6,6 +6,10 @@ !--> <%- include('top') %> + @@ -312,81 +316,6 @@ - -
-

Errors

-

- The Westeros API uses the following error codes: -

- - - - - - - - - - - - - - - - - - - - - - - - - -
Error CodeMeaning
X000 - Some parameters are missing. This error appears when you don't pass every mandatory - parameters. -
403 - Unknown or unvalid secret_key. This error appears if - you use an unknow API key or if your API key expired. -
500 - Unvalid secret_key No API key was supplied. Invalid - request. -
X003 - Unknown or unvalid user token. This error appears if - you use an unknow user token or if the user token expired. -
-
-
-
-

API Keys

- -

- You can generate API Keys here: -

- - - - - - - - - - - - - - - - - - - -
NamePublic KeyPrivate KeyKey TypeCreated
API KeyGR234-We34greR-234-fEGType2024-01-22
-
-

Get all sensor

@@ -483,7 +412,7 @@ Authorization JSON Your API key. - (Required) Example: curl https://api.teeseng.uk/api/v0/sensor/new + (Required) Example: curl https://api.teeseng.uk/api/v0/sensor/new -H "Authorization: {provide your API key here}" @@ -620,7 +549,8 @@ Description JSON Description of Sensor - (Optional) Description of Sensor Example: curl https://api.teeseng.uk/api/v0/sensor/update + (Optional) Description of Sensor Example: curl + https://api.teeseng.uk/api/v0/sensor/update -H "Authorization: provide your API key here" -d '{"description":"test"}' @@ -629,7 +559,8 @@ Location JSON Location of Sensor - (Optional) Location of Sensor Example: curl https://api.teeseng.uk/api/v0/sensor/update + (Optional) Location of Sensor Example: curl + https://api.teeseng.uk/api/v0/sensor/update -H "Authorization: provide your API key here" -d '{"location": "11"}' @@ -679,10 +610,77 @@ +

+

API Keys

+

+ You can generate API Keys here: +

+
+ + +
+ + +
+ +
+
+ +
+

Errors

+

+ The EcoSaver API uses the following error codes: +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Error CodeMeaning
X000 + Some parameters are missing. This error appears when you don't pass every + mandatory + parameters. +
403 + Unknown or unvalid secret_key. This error + appears if + you use an unknow API key or if your API key expired. +
500 + Unvalid secret_key No API key was supplied. + Invalid + request. +
X003 + Unknown or unvalid user token. This error + appears if + you use an unknow user token or if the user + token expired. +
+ - + + \ No newline at end of file diff --git a/consumerWebsite/views/contact.ejs b/consumerWebsite/views/contact.ejs index edc98f5..670c760 100644 --- a/consumerWebsite/views/contact.ejs +++ b/consumerWebsite/views/contact.ejs @@ -42,7 +42,8 @@

E: - leongdingxuan@gmail.com + ecosaverx@gmail.com +

@@ -55,17 +56,18 @@

+

Send us a Message

-
- + +
- +
- +
@@ -75,6 +77,8 @@
+
+
diff --git a/consumerWebsite/views/index.ejs b/consumerWebsite/views/index.ejs index c2e533a..c4419a3 100644 --- a/consumerWebsite/views/index.ejs +++ b/consumerWebsite/views/index.ejs @@ -1,18 +1,59 @@ <%- include('top') %> - @@ -69,7 +110,8 @@

Air Quality Index

-

{{ measurement.psi }} PSI

+

Average: {{average.psi}} PSI

+

Latest: {{latest.psi}} PSI