Added email subjects, and favourites

This commit is contained in:
Johnathon Slightham
2021-05-19 15:53:22 -04:00
parent fb799fa001
commit ac404a0ac5
11 changed files with 161 additions and 45 deletions

View File

@@ -34,6 +34,8 @@ Emails are stored in the [`templates`](https://github.com/jslightham/kno-logic-a
Any portion of the message can be replaced when sending the email. The convention used in all default email templates is `%replace_string%`. The replace string does not matter since when calling the sendMail function, replacements is an array of data with the form `{from: "%replace_string%", to: "Username"}`.
Email subjects are the first line of the file, which are removed from the email body.
## Configuration
Configuration for the application is done in the [`config.js`](https://github.com/jslightham/kno-logic-api/blob/main/config.js) file.

View File

@@ -27,7 +27,7 @@ categoryRoutes.route('/create').post((req, res) => {
res.json(c);
})
.catch((e) => {
console.log(e);
console.error(e);
res.status(500).send("Error creating category");
});
} else {
@@ -46,7 +46,7 @@ categoryRoutes.route('/create').post((req, res) => {
categoryRoutes.route('/all').get((req, res) => {
Category.find({}, (err, cArr) => {
if (err) {
console.log(err);
console.error(err);
res.status(500).send("Error getting categories");
return;
}
@@ -62,7 +62,7 @@ categoryRoutes.route('/all').get((req, res) => {
categoryRoutes.route('/posts').get((req, res) => {
Post.find({}, (err, postArr) => {
if (err) {
console.log(err);
console.error(err);
res.status(500).send("Error getting posts");
return;
}

View File

@@ -3,11 +3,11 @@ var config = {};
// Mailer settings
config.mail = {};
config.mail.host = "localhost";
config.mail.port = "465";
config.mail.port = "587";
config.mail.secure = false;
config.mail.user = "username";
config.mail.pass = "pass";
config.mail.from = "<noreply@knologic.com>"
config.mail.user = "email";
config.mail.pass = "password";
config.mail.from = "name"
// Session purge settings
config.maxSessionLength = 30;

View File

@@ -10,6 +10,7 @@ const config = require('./DB.js');
const userRoutes = require('./user.route');
const postRoutes = require('./post.route');
const categoryRoutes = require('./category.route');
const mongoSanitize = require('express-mongo-sanitize');
console.log("Starting Kno-Logic Backend Server");
@@ -32,6 +33,9 @@ app.use(cors());
app.use(express.urlencoded({ extended: true }))
app.use(express.json());
// Sanitize data to prevent NoSQL injections
app.use(mongoSanitize());
// Express routes
app.use('/user', userRoutes);
app.use('/post', postRoutes);

5
package-lock.json generated
View File

@@ -622,6 +622,11 @@
"vary": "~1.1.2"
}
},
"express-mongo-sanitize": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/express-mongo-sanitize/-/express-mongo-sanitize-2.1.0.tgz",
"integrity": "sha512-ELGeH/Tx+kJGn3klCzSmOewfN1ezJQrkqzq83dl/K3xhd5PUbvLtiD5CiuYRmQfoZPL4rUEVjANf/YjE2BpTWQ=="
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",

View File

@@ -22,6 +22,7 @@
"cors": "^2.8.5",
"cron": "^1.8.2",
"express": "^4.17.1",
"express-mongo-sanitize": "^2.1.0",
"log-timestamp": "^0.3.0",
"mongoose": "^5.12.7",
"nodemailer": "^6.6.0"

View File

@@ -1,3 +1,4 @@
Kno-Logic Password Reset
Hello %name%,
Someone has requested a password reset for the account connected to your email.

View File

@@ -1,3 +1,4 @@
Welcome to Kno-Logic!
Hello %name%,
Welcome to kno-logic!
Welcome to the kno-logic app. Thank you for...

View File

@@ -14,6 +14,9 @@ let User = new Schema({
},
permission: {
type: Number
},
favorites: {
type: Array
}
}, {
collection: 'users'

View File

@@ -1,4 +1,4 @@
const utils = require ('./utils');
const utils = require('./utils');
const express = require('express');
const bcrypt = require('bcrypt');
const userRoutes = express.Router();
@@ -8,6 +8,7 @@ const sessionLength = 25;
let Session = require('./session.model');
let User = require('./user.model');
let Post = require('./post.model');
/*
POST - /user/create
@@ -26,19 +27,16 @@ userRoutes.route('/create').post((req, res) => {
res.status(401).send("Empty fields");
return;
}
console.log(req.body);
let u = new User(req.body);
// TODO: Look for a different encryption method that can scale more easily
bcrypt.hash(u.password, saltRounds, (err, hash) => {
if (err) {
console.log(err);
console.error(err);
res.status(500).send("Error creating user");;
} else {
console.log(hash);
u.password = hash;
User.find({ email: u.email }, (err, arr) => {
if (err) {
console.log(err);
console.error(err);
res.status(500).send("Error creating user");
}
// Account already exists
@@ -67,7 +65,6 @@ userRoutes.route('/create').post((req, res) => {
401 - Incorrect
*/
userRoutes.route('/login').post((req, res) => {
console.log(req.body);
if (!req.body) {
res.status(401).send("Missing body");
return;
@@ -80,7 +77,7 @@ userRoutes.route('/login').post((req, res) => {
}
User.findOne({ email: req.body.email }, (err, u) => {
if (err) {
console.log(err);
console.error(err);
res.status(500).send("Error logging in user");
return;
}
@@ -92,7 +89,7 @@ userRoutes.route('/login').post((req, res) => {
bcrypt.compare(req.body.password, u.password, (err, result) => {
if (err) {
console.log(err);
console.error(err);
res.status(500).send("Error logging in user");
return;
}
@@ -125,9 +122,9 @@ userRoutes.route('/login').post((req, res) => {
400 - No session exists
*/
userRoutes.route('/logout').post((req, res) => {
Session.findOne({sessionId: req.body.sessionId}, (err, sess) => {
Session.findOne({ sessionId: req.body.sessionId }, (err, sess) => {
if (err) {
console.log(err);
console.error(err);
res.status(500).send("Error logging out");
return;
}
@@ -141,7 +138,8 @@ userRoutes.route('/logout').post((req, res) => {
.then(() => {
res.status(201).send("Success deleting session");
})
.catch(() => {
.catch((e) => {
console.error(e);
res.status(500).send("Error logging out");
});
@@ -150,6 +148,95 @@ userRoutes.route('/logout').post((req, res) => {
// TODO: Add forgotten password route
/*
POST - /user/favorite/add
Add a favorite article
Response: 200 - OK
401 - Unauthorized
*/
userRoutes.route('/favorite/add').post((req, res) => {
utils.checkSession(req.body.userId, req.body.sessionId, valid => {
if (valid) {
User.findById(req.body.userId, (err, user) => {
if (err) {
console.error(err);
res.status(500).send("Error adding article");
return;
}
user.favorites.push(req.body.postId);
user.save()
.then(() => {
res.status(201).send("Success saving article");
})
.catch((e) => {
console.error(e);
res.status(500).send("Error saving article");
});
})
} else {
res.status(401).send("Unauthorized");
}
})
})
/*
POST - /user/favorite/remove
Remove a favorite article
Response: 200 - OK
401 - Unauthorized
*/
userRoutes.route('/favorite/remove').post((req, res) => {
utils.checkSession(req.body.userId, req.body.sessionId, valid => {
if (valid) {
User.findById(req.body.userId, (err, user) => {
if (err) {
console.error(err);
res.status(500).send("Error removing article");
return;
}
user.favorites = utils.removeValue(user.favorites, req.body.articleId);
user.save()
.then(() => {
res.status(201).send("Success removing article");
})
.catch((e) => {
console.error(e);
res.status(500).send("Error removing article");
});
})
} else {
res.status(401).send("Unauthorized");
}
})
})
/*
POST - /user/favorite/get
Get all favorite articles
Response: 200 - OK
401 - Unauthorized
*/
userRoutes.route('/favorite/get').post((req, res) => {
utils.checkSession(req.body.userId, req.body.sessionId, valid => {
if (valid) {
User.findById(req.body.userId, (err, user) => {
if (err) {
console.error(err);
res.status(500).send("Error removing article");
return;
}
console.log(user.favorites);
Post.find({ '_id': { $in: user.favorites } }, (err, postArray) => {
res.json(postArray);
})
})
} else {
res.status(401).send("Unauthorized");
}
})
})
module.exports = userRoutes;
function generateSession() {

View File

@@ -43,8 +43,8 @@ const loadDefaultTemplates = () => {
} else {
let newMsg = Message();
newMsg.name = name;
newMsg.subject = "Email From Kno-Logic" //TODO: Should load these from config.js
newMsg.body = data;
newMsg.subject = data.substring(0, data.indexOf("\n"));
newMsg.body = data.substring(data.indexOf("\n") + 1);
newMsg.save()
.then(() => {
console.log("Loaded " + name + " message");
@@ -70,35 +70,38 @@ const sendMail = async (user, message, replacements) => {
port: config.mail.port,
secure: config.mail.secure,
auth: {
user: config.mail.user,
pass: config.mail.pass,
user: config.mail.user,
pass: config.mail.pass,
},
});
Message.findOne({ name: message }, (err, message) => {
let msgBody = message.body;
let msgBody = message.body;
for (let i = 0; i < replacements.length; i++) {
msgBody = msgBody.replace(replacements[i].from, replacements[i].to);
}
for (let i = 0; i < replacements.length; i++) {
msgBody = msgBody.replace(replacements[i].from, replacements[i].to);
}
console.log(message);
try {
await transporter.sendMail({
from: config.mail.from,
to: user.email,
subject: message.subject,
text: msgBody,
});
try {
transporter.sendMail({
from: config.mail.from,
to: user.email,
subject: message.subject,
text: msgBody,
});
} catch (error) {
console.log("Error sending mail: ")
console.error(error);
}
} catch (error) {
console.log("Error sending mail: ")
console.error(error);
}
})
}
// checkSession(userId, sessionId) checks if the sessionId is valid for the user
const checkSession = (userId, sessionId, f) => {
Session.find({userId: userId, sessionId: sessionId }, (err, res) => {
Session.find({ userId: userId, sessionId: sessionId }, (err, res) => {
if (res) {
f(true);
return;
@@ -110,7 +113,7 @@ const checkSession = (userId, sessionId, f) => {
// isAdmin(userId) checks if the user with userId is an administrator
const isAdmin = (userId, f) => {
User.findById(userId, (err, res) => {
if(res.permission == 1) {
if (res.permission == 1) {
f(true);
return;
}
@@ -124,11 +127,19 @@ function dateToEpoch(d) {
if (d) {
// When comparing js dates, the timezone does not matter
// ex. May 17 EDT == May 17 GMT, May 17 EDT != May 18 GMT
return d.setHours(0,0,0,0);
return d.setHours(0, 0, 0, 0);
} else {
return null;
}
}
}
// removeValue(array, item) remove item from the array
function removeValue(array, item) {
var index = array.indexOf(item);
if (index !== -1) {
array.splice(index, 1);
}
}
module.exports.purgeSessions = purgeSessions;
module.exports.loadDefaultTemplates = loadDefaultTemplates;
@@ -136,3 +147,4 @@ module.exports.sendMail = sendMail;
module.exports.checkSession = checkSession;
module.exports.isAdmin = isAdmin;
module.exports.dateToEpoch = dateToEpoch;
module.exports.removeValue = removeValue;