Added email subjects, and favourites
This commit is contained in:
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
4
index.js
4
index.js
@@ -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
5
package-lock.json
generated
@@ -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",
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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...
|
||||||
@@ -14,6 +14,9 @@ let User = new Schema({
|
|||||||
},
|
},
|
||||||
permission: {
|
permission: {
|
||||||
type: Number
|
type: Number
|
||||||
|
},
|
||||||
|
favorites: {
|
||||||
|
type: Array
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
collection: 'users'
|
collection: 'users'
|
||||||
|
|||||||
107
user.route.js
107
user.route.js
@@ -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() {
|
||||||
|
|||||||
20
utils.js
20
utils.js
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user