Added session purge, email templates, email sending, and fixed user bugs

This commit is contained in:
Johnathon Slightham
2021-05-05 02:25:30 -04:00
parent c2ecd89ab0
commit 2ff2689e91
6 changed files with 188 additions and 20 deletions

16
config.js Normal file
View File

@@ -0,0 +1,16 @@
var config = {};
// Mailer settings
config.mail = {};
config.mail.host = "localhost";
config.mail.port = "465";
config.mail.secure = false;
config.mail.user = "username";
config.mail.pass = "pass";
config.mail.from = "<noreply@knologic.com>"
// Session purge settings
config.maxSessionLength = 30;
module.exports = config;

View File

@@ -1,21 +1,27 @@
require('log-timestamp');
const express = require('express');
const app = express();
const PORT = 4000;
const cors = require('cors');
var bodyParser = require('body-parser')
const mongoose = require('mongoose');
const utils = require ('./utils');
const CronJob = require('cron').CronJob;
const config = require('./DB.js');
const userRoutes = require('./user.route');
console.log("Starting Kno-Logic Backend Server");
// Handle MongoDB connection
mongoose.Promise = global.Promise;
mongoose.connect(config.DB, { useNewUrlParser: true, useUnifiedTopology: true }).then(
() => {
console.log('Connected to dabase');
utils.loadDefaultTemplates();
utils.purgeSessions();
},
err => {
console.log('Could not connect to database: ' + err);
console.log('Could not connect to database: ');
console.log(err);
}
);
@@ -30,3 +36,7 @@ app.use('/users', userRoutes);
app.listen(PORT, () => {
console.log('Express server running on port:', PORT);
});
// Cron jobs
var purge = new CronJob('*/5 * * * *', utils.purgeSessions);
purge.start();

39
package-lock.json generated
View File

@@ -461,6 +461,14 @@
"vary": "^1"
}
},
"cron": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/cron/-/cron-1.8.2.tgz",
"integrity": "sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==",
"requires": {
"moment-timezone": "^0.5.x"
}
},
"crypto-random-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
@@ -1008,6 +1016,19 @@
"package-json": "^6.3.0"
}
},
"log-prefix": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/log-prefix/-/log-prefix-0.1.1.tgz",
"integrity": "sha512-aP1Lst8OCdZKATqzXDN0JBissNVZuiKLyo6hOXDBxaQ1jHDsaxh2J1i5Pp0zMy6ayTKDWfUlLMXyLaQe1PJ48g=="
},
"log-timestamp": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/log-timestamp/-/log-timestamp-0.3.0.tgz",
"integrity": "sha512-luRz6soxijd1aJh0GkLXFjKABihxthvTfWTzu3XhCgg5EivG2bsTpSd63QFbUgS+/KmFtL+0RfSpeaD2QvOV8Q==",
"requires": {
"log-prefix": "0.1.1"
}
},
"lowercase-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
@@ -1118,6 +1139,19 @@
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"moment-timezone": {
"version": "0.5.33",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz",
"integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==",
"requires": {
"moment": ">= 2.9.0"
}
},
"mongodb": {
"version": "3.6.6",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.6.tgz",
@@ -1214,6 +1248,11 @@
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"nodemailer": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.0.tgz",
"integrity": "sha512-ikSMDU1nZqpo2WUPE0wTTw/NGGImTkwpJKDIFPZT+YvvR9Sj+ze5wzu95JHkBMglQLoG2ITxU21WukCC/XsFkg=="
},
"nodemon": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz",

View File

@@ -20,8 +20,11 @@
"bcrypt": "^5.0.1",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"cron": "^1.8.2",
"express": "^4.17.1",
"mongoose": "^5.12.7"
"log-timestamp": "^0.3.0",
"mongoose": "^5.12.7",
"nodemailer": "^6.6.0"
},
"devDependencies": {
"nodemon": "^2.0.7"

View File

@@ -16,6 +16,16 @@ let User = require('./user.model');
409 - Account already exists
*/
userRoutes.route('/create').post((req, res) => {
if (!req.body) {
res.status(401).send("Missing body");
return;
} else if (!req.body.email || !req.body.password || !req.body.name) {
res.status(401).send("Missing body");
return;
} else if (req.body.email == "" || req.body.password == "" || req.body.name == "") {
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
@@ -56,22 +66,32 @@ userRoutes.route('/create').post((req, res) => {
401 - Incorrect
*/
userRoutes.route('/login').post((req, res) => {
if (!req.body) {
res.status(401).send("Missing body");
return;
} else if (!req.body.email || !req.body.password) {
res.status(401).send("Missing body");
return;
} else if (req.body.email == "" || req.body.password == "") {
res.status(401).send("Empty fields");
return;
}
User.findOne({ email: req.body.email }, (err, u) => {
if (err) {
console.log(err);
res.status(500);
res.status(500).send("Error logging in user");
return;
}
if (!u) {
res.status(401);
res.status(401).send("No user exists with that email");
return;
}
bcrypt.compare(req.body.password, u.password, (err, result) => {
if (err) {
console.log(err);
res.status(500);
res.status(500).send("Error logging in user");
return;
}
@@ -83,13 +103,13 @@ userRoutes.route('/login').post((req, res) => {
s.save()
.then(() => {
res.json(u);
res.json(s);
})
.catch(() => {
res.status(500);
res.status(500).send("Error logging in user");
});
} else {
res.status(401);
res.status(401).send("Incorrect password");
}
});
@@ -103,15 +123,15 @@ userRoutes.route('/login').post((req, res) => {
400 - No session exists
*/
userRoutes.route('/logout').post((req, res) => {
Session.findOne({ userId: req.body._id }, (err, sess) => {
Session.findOne({sessionId: req.body.sessionId}, (err, sess) => {
if (err) {
console.log(err);
res.status(500);
res.status(500).send("Error logging out");
return;
}
if (!sess) {
res.status(400);
res.status(400).send("No session found");
return;
}
@@ -120,7 +140,7 @@ userRoutes.route('/logout').post((req, res) => {
res.status(201).send("Success deleting session");
})
.catch(() => {
res.status(500);
res.status(500).send("Error logging out");
});
});

View File

@@ -1,19 +1,99 @@
const fs = require('fs');
const nodemailer = require("nodemailer");
var config = require('./config');
let User = require('./user.model');
let Session = require('./session.model');
let Message = require('./message.model');
var maxSessionLength = config.maxSessionLength;
// purgeSessions() purge sessions that have existed for longer than maxSessionLength
const purgeSessions = () => {
// TODO: Write a function to purge all old session IDs automatically, use cron to schedule
console.log("Purging old sessions...");
Session.find({}, (err, arr) => {
for (let i = 0; i < arr.length; i++) {
let timeDifference = new Date().getTime() - arr[i].date;
let dayDifference = timeDifference / (1000 * 3600 * 24);
if (dayDifference > maxSessionLength) {
arr[i].delete().catch(e => {
console.log(e);
});
}
}
});
}
// loadDefaultTemplates() load the default email templates into the database
// if no template exists for that name
const loadDefaultTemplates = () => {
// TODO: Write a function that loads default mailing templates into the database
console.log("Loading default email templates...")
fs.readdir('./templates', (err, files) => {
files.forEach(file => {
fs.readFile('./templates/' + file, 'utf8', function (err, data) {
if (err) {
console.log(err);
}
let name = file.substring(0, file.indexOf('.'));
Message.findOne({ name: name }, (err, msg) => {
if (err) {
console.log(err);
return;
}
if (msg) {
} else {
let newMsg = Message();
newMsg.name = name;
newMsg.subject = "Email From Kno-Logic" //TODO: Should load these from config.js
newMsg.body = data;
newMsg.save()
.then(() => {
console.log("Loaded " + name + " message");
})
.catch(() => {
console.log("Error loading messages from file.");
});
}
});
});
});
});
}
const sendMail = (user, message) => {
// TODO: Write a function that can take in a message and a user and send the email using nodemailer
}
// sendMail(user, message, replacements) send an email with message to the user, making
// replacements in the message
// replacements is an array of data {from, to}
const sendMail = async (user, message, replacements) => {
console.log("Sending mail...");
let transporter = nodemailer.createTransport({
host: config.mail.host,
port: config.mail.port,
secure: config.mail.secure,
auth: {
user: config.mail.user,
pass: config.mail.pass,
},
});
let msgBody = message.body;
for (let i = 0; i < replacements.length; i++) {
msgBody = msgBody.replace(replacements[i].from, replacements[i].to);
}
try {
await transporter.sendMail({
from: config.mail.from,
to: user.email,
subject: message.subject,
text: msgBody,
});
} catch (error) {
console.log("Error sending mail: ")
console.error(error);
}
}
module.exports.purgeSessions = purgeSessions;
module.exports.loadDefaultTemplates = loadDefaultTemplates;