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"}`. 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
Configuration for the application is done in the [`config.js`](https://github.com/jslightham/kno-logic-api/blob/main/config.js) file. 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); res.json(c);
}) })
.catch((e) => { .catch((e) => {
console.log(e); console.error(e);
res.status(500).send("Error creating category"); res.status(500).send("Error creating category");
}); });
} else { } else {
@@ -46,7 +46,7 @@ categoryRoutes.route('/create').post((req, res) => {
categoryRoutes.route('/all').get((req, res) => { categoryRoutes.route('/all').get((req, res) => {
Category.find({}, (err, cArr) => { Category.find({}, (err, cArr) => {
if (err) { if (err) {
console.log(err); console.error(err);
res.status(500).send("Error getting categories"); res.status(500).send("Error getting categories");
return; return;
} }
@@ -62,7 +62,7 @@ categoryRoutes.route('/all').get((req, res) => {
categoryRoutes.route('/posts').get((req, res) => { categoryRoutes.route('/posts').get((req, res) => {
Post.find({}, (err, postArr) => { Post.find({}, (err, postArr) => {
if (err) { if (err) {
console.log(err); console.error(err);
res.status(500).send("Error getting posts"); res.status(500).send("Error getting posts");
return; return;
} }

View File

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

View File

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

5
package-lock.json generated
View File

@@ -622,6 +622,11 @@
"vary": "~1.1.2" "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": { "fill-range": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",

View File

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

View File

@@ -1,3 +1,4 @@
Kno-Logic Password Reset
Hello %name%, Hello %name%,
Someone has requested a password reset for the account connected to your email. 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%, 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: { permission: {
type: Number type: Number
},
favorites: {
type: Array
} }
}, { }, {
collection: 'users' collection: 'users'

View File

@@ -8,6 +8,7 @@ const sessionLength = 25;
let Session = require('./session.model'); let Session = require('./session.model');
let User = require('./user.model'); let User = require('./user.model');
let Post = require('./post.model');
/* /*
POST - /user/create POST - /user/create
@@ -26,19 +27,16 @@ userRoutes.route('/create').post((req, res) => {
res.status(401).send("Empty fields"); res.status(401).send("Empty fields");
return; return;
} }
console.log(req.body);
let u = new User(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) => { bcrypt.hash(u.password, saltRounds, (err, hash) => {
if (err) { if (err) {
console.log(err); console.error(err);
res.status(500).send("Error creating user");; res.status(500).send("Error creating user");;
} else { } else {
console.log(hash);
u.password = hash; u.password = hash;
User.find({ email: u.email }, (err, arr) => { User.find({ email: u.email }, (err, arr) => {
if (err) { if (err) {
console.log(err); console.error(err);
res.status(500).send("Error creating user"); res.status(500).send("Error creating user");
} }
// Account already exists // Account already exists
@@ -67,7 +65,6 @@ userRoutes.route('/create').post((req, res) => {
401 - Incorrect 401 - Incorrect
*/ */
userRoutes.route('/login').post((req, res) => { userRoutes.route('/login').post((req, res) => {
console.log(req.body);
if (!req.body) { if (!req.body) {
res.status(401).send("Missing body"); res.status(401).send("Missing body");
return; return;
@@ -80,7 +77,7 @@ userRoutes.route('/login').post((req, res) => {
} }
User.findOne({ email: req.body.email }, (err, u) => { User.findOne({ email: req.body.email }, (err, u) => {
if (err) { if (err) {
console.log(err); console.error(err);
res.status(500).send("Error logging in user"); res.status(500).send("Error logging in user");
return; return;
} }
@@ -92,7 +89,7 @@ userRoutes.route('/login').post((req, res) => {
bcrypt.compare(req.body.password, u.password, (err, result) => { bcrypt.compare(req.body.password, u.password, (err, result) => {
if (err) { if (err) {
console.log(err); console.error(err);
res.status(500).send("Error logging in user"); res.status(500).send("Error logging in user");
return; return;
} }
@@ -127,7 +124,7 @@ userRoutes.route('/login').post((req, res) => {
userRoutes.route('/logout').post((req, res) => { userRoutes.route('/logout').post((req, res) => {
Session.findOne({ sessionId: req.body.sessionId }, (err, sess) => { Session.findOne({ sessionId: req.body.sessionId }, (err, sess) => {
if (err) { if (err) {
console.log(err); console.error(err);
res.status(500).send("Error logging out"); res.status(500).send("Error logging out");
return; return;
} }
@@ -141,7 +138,8 @@ userRoutes.route('/logout').post((req, res) => {
.then(() => { .then(() => {
res.status(201).send("Success deleting session"); res.status(201).send("Success deleting session");
}) })
.catch(() => { .catch((e) => {
console.error(e);
res.status(500).send("Error logging out"); res.status(500).send("Error logging out");
}); });
@@ -150,6 +148,95 @@ userRoutes.route('/logout').post((req, res) => {
// TODO: Add forgotten password route // 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; module.exports = userRoutes;
function generateSession() { function generateSession() {

View File

@@ -43,8 +43,8 @@ const loadDefaultTemplates = () => {
} else { } else {
let newMsg = Message(); let newMsg = Message();
newMsg.name = name; newMsg.name = name;
newMsg.subject = "Email From Kno-Logic" //TODO: Should load these from config.js newMsg.subject = data.substring(0, data.indexOf("\n"));
newMsg.body = data; newMsg.body = data.substring(data.indexOf("\n") + 1);
newMsg.save() newMsg.save()
.then(() => { .then(() => {
console.log("Loaded " + name + " message"); console.log("Loaded " + name + " message");
@@ -74,15 +74,17 @@ const sendMail = async (user, message, replacements) => {
pass: config.mail.pass, 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++) { for (let i = 0; i < replacements.length; i++) {
msgBody = msgBody.replace(replacements[i].from, replacements[i].to); msgBody = msgBody.replace(replacements[i].from, replacements[i].to);
} }
console.log(message);
try { try {
await transporter.sendMail({ transporter.sendMail({
from: config.mail.from, from: config.mail.from,
to: user.email, to: user.email,
subject: message.subject, subject: message.subject,
@@ -93,6 +95,7 @@ const sendMail = async (user, message, replacements) => {
console.log("Error sending mail: ") console.log("Error sending mail: ")
console.error(error); console.error(error);
} }
})
} }
@@ -130,9 +133,18 @@ function dateToEpoch(d) {
} }
} }
// 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.purgeSessions = purgeSessions;
module.exports.loadDefaultTemplates = loadDefaultTemplates; module.exports.loadDefaultTemplates = loadDefaultTemplates;
module.exports.sendMail = sendMail; module.exports.sendMail = sendMail;
module.exports.checkSession = checkSession; module.exports.checkSession = checkSession;
module.exports.isAdmin = isAdmin; module.exports.isAdmin = isAdmin;
module.exports.dateToEpoch = dateToEpoch; module.exports.dateToEpoch = dateToEpoch;
module.exports.removeValue = removeValue;