716 lines
19 KiB
JavaScript
716 lines
19 KiB
JavaScript
// Imports libraries
|
|
const express = require('express');
|
|
const router = express.Router();
|
|
const bcrypt = require('bcryptjs');
|
|
const passport = require('passport');
|
|
const MongoClient = require('mongodb').MongoClient;
|
|
const ObjectId = require('mongodb').ObjectId;
|
|
const Quest = require('../models/Quest');
|
|
const Course = require('../models/Course');
|
|
const socket = require('socket.io');
|
|
const server = require('../app.js').server;
|
|
const io = socket(server);
|
|
|
|
// Load Profanity filter
|
|
const Filter = require('bad-words');
|
|
const filter = new Filter();
|
|
|
|
// Load User model
|
|
const User = require('../models/User');
|
|
const { forwardAuthenticated } = require('../config/auth');
|
|
|
|
// DB Config
|
|
const url = require('../config/keys').mongoURI;
|
|
|
|
// Loads libraries for uploading img functions
|
|
let fs = require('fs');
|
|
let path = require('path');
|
|
let multer = require('multer');
|
|
|
|
let storage = multer.diskStorage({
|
|
destination: (req, file, cb) => {
|
|
cb(null, 'routes/uploads')
|
|
},
|
|
filename: (req, file, cb) => {
|
|
cb(null, file.fieldname + '-' + Date.now())
|
|
}
|
|
});
|
|
|
|
let upload = multer({ storage: storage });
|
|
|
|
let questsList;
|
|
// Collects Quest Data
|
|
Quest.find({}, function(err, quests) {
|
|
questsList = quests;
|
|
});
|
|
|
|
// Show Quest page
|
|
router.get('/quests', (req, res) => res.render('quests', { quests: questsList }));
|
|
|
|
// Login Page
|
|
router.get('/login', forwardAuthenticated, (req, res) => res.render('login'));
|
|
|
|
// Register Page
|
|
router.get('/register', forwardAuthenticated, (req, res) => res.render('register'));
|
|
|
|
// Edit page
|
|
router.get('/edit', (req, res) => res.render('edit'));
|
|
|
|
// Create Course / Class
|
|
router.post('/createClass', (req, res, next) => {
|
|
const { name, description, grade } = req.body;
|
|
|
|
let errors = [];
|
|
|
|
//Checks if Class Already Exists
|
|
Course.findOne({ name: name }).then(course => {
|
|
if (course) {
|
|
errors.push({ msg: 'Course Name Already Exists' })
|
|
// Redirect to dashboard page with errors
|
|
res.render('dashboard', {
|
|
errors,
|
|
name,
|
|
description,
|
|
grade
|
|
});
|
|
} else {
|
|
try {
|
|
// Creates new Course Object
|
|
const newCourse = new Course({
|
|
name: name,
|
|
description: description,
|
|
grade: grade
|
|
});
|
|
newCourse
|
|
.save()
|
|
.then(course => {
|
|
req.flash(
|
|
'success_msg'
|
|
);
|
|
// Takes to Dashboard on success
|
|
let value = encodeURIComponent('createdClass')
|
|
res.redirect('/dashboard?successRate=' + value);
|
|
})
|
|
.catch(err => console.log(err));
|
|
} catch (err) {
|
|
if (err) throw err;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// Delete User
|
|
router.post('/deleteUser', (req, res, next) => {
|
|
const id = req.body.delete_id;
|
|
|
|
// Deletes User
|
|
MongoClient.connect(url, {
|
|
useUnifiedTopology: true,
|
|
useNewUrlParser: true}, function(err, db) {
|
|
if (err) throw err;
|
|
let dbo = db.db("XPmockDB");
|
|
dbo.collection("students").deleteOne({ _id: ObjectId(id) }, function(err, obj) {
|
|
if (err) throw err;
|
|
db.close();
|
|
});
|
|
// Takes to Dahsboard on success
|
|
let value = encodeURIComponent('deletedUser');
|
|
res.redirect('/dashboard?successRate=' + value);
|
|
}
|
|
);
|
|
});
|
|
|
|
// Create Quest
|
|
router.post('/createQuest', (req, res, next) => {
|
|
const { title, amount, expiry, instructions, campaign} = req.body;
|
|
|
|
let errors = [];
|
|
|
|
// Checks if Quest with title exists
|
|
Quest.findOne({ title: title }).then(quest => {
|
|
if (quest) {
|
|
errors.push({ msg: 'Quest Already Exists' });
|
|
// Redirect to dashboard page with errors
|
|
res.render('dashboard', {
|
|
errors,
|
|
name,
|
|
email,
|
|
password,
|
|
password2
|
|
});
|
|
} else {
|
|
|
|
try {
|
|
// Creates new User Object
|
|
const newQuest = new Quest({
|
|
title: title,
|
|
campaign: campaign,
|
|
expiry: expiry,
|
|
xp: amount,
|
|
instruction: instructions
|
|
});
|
|
newQuest
|
|
.save()
|
|
.then(quest => {
|
|
req.flash(
|
|
'success_msg'
|
|
);
|
|
// Takes to Dashboard on success
|
|
let value = encodeURIComponent('createdQuest')
|
|
res.redirect('/dashboard?successRate=' + value);
|
|
})
|
|
.catch(err => console.log(err));
|
|
} catch (err) {
|
|
if (err) throw err;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// Add XP
|
|
router.post('/addXP', (req, res, next) => {
|
|
const { _id_add, current_xp, amount } = req.body;
|
|
|
|
if(amount > 50) {
|
|
// Takes to Dahsboard on success
|
|
let value = encodeURIComponent('addXP > 50')
|
|
res.redirect('/dashboard?successRate=' + value);
|
|
}
|
|
|
|
if(amount < 0 || amount == 0) {
|
|
// Takes to Dahsboard on success
|
|
let value = encodeURIComponent('addXP <= 0')
|
|
res.redirect('/dashboard?successRate=' + value);
|
|
}
|
|
|
|
if (amount < 50 && amount > 0 && current_xp < 800) {
|
|
let newXP = parseInt(current_xp) + parseInt(amount);
|
|
if (newXP > 800) {
|
|
newXP = 800;
|
|
}
|
|
|
|
try {
|
|
// Creates updated object
|
|
let updated = {
|
|
xp: newXP
|
|
}
|
|
|
|
// Updates user xp
|
|
MongoClient.connect(url, {
|
|
useUnifiedTopology: true,
|
|
useNewUrlParser: true}, function(err, db) {
|
|
if (err) throw err;
|
|
let dbo = db.db("XPmockDB");
|
|
dbo.collection('users').updateOne({ _id: ObjectId(_id_add) }, { $set: updated }, { upsert: true }, function(err, res) {
|
|
if (err) throw err;
|
|
db.close()
|
|
});
|
|
// Takes to Dahsboard on success
|
|
let value1 = encodeURIComponent(amount.toString())
|
|
let value2 = encodeURIComponent(_id_add);
|
|
res.redirect('/dashboard?successRate='+value1+'&id='+value2);
|
|
}
|
|
);
|
|
}
|
|
catch(err) {
|
|
console.log(err);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Edit
|
|
router.post('/edit', upload.single('image'), (req, res, next) => {
|
|
// Passes image path to defaultImage Model
|
|
imagePath = __dirname + '/uploads/default-image';
|
|
module.exports = {
|
|
defaultPath: imagePath
|
|
}
|
|
|
|
// Gets inputs
|
|
let { _id, name, newPassword, newPassword2 } = req.body;
|
|
let errors = [];
|
|
let useName = true;
|
|
let useNewPassword = true;
|
|
|
|
if (!name) {
|
|
useName = false;
|
|
}
|
|
|
|
if (filter.isProfane(name)) {
|
|
errors.push({ msg: "Name contains profanity" });
|
|
name = filter.clean(name);
|
|
}
|
|
|
|
if (!newPassword) {
|
|
if (newPassword2.length > 0) {
|
|
errors.push({ msg: 'You need to enter your new password' })
|
|
}
|
|
|
|
if (!newPassword2) {
|
|
useNewPassword = false;
|
|
}
|
|
}
|
|
|
|
if (newPassword.length > 0) {
|
|
if (!newPassword2) {
|
|
errors.push({ msg: 'Confirm new Password' })
|
|
}
|
|
|
|
// Checks if new password & new password confirm match
|
|
if (newPassword != newPassword2) {
|
|
errors.push({ msg: 'New Passwords do not match' });
|
|
}
|
|
|
|
// Validates new password is required lenght
|
|
if (newPassword.length < 6) {
|
|
errors.push({ msg: 'Password must be at least 6 characters' });
|
|
}
|
|
}
|
|
|
|
if (filter.isProfane(newPassword)) {
|
|
errors.push({ msg: "Password contains profanity" });
|
|
newPassword = filter.clean(newPassword);
|
|
}
|
|
|
|
if (filter.isProfane(newPassword2)) {
|
|
errors.push({ msg: "Password contains profanity" });
|
|
newPassword2 = filter.clean(newPassword2);
|
|
}
|
|
|
|
// Error Handling
|
|
if (errors.length > 0) {
|
|
// Redirects to edit page with errors
|
|
res.render('edit', {
|
|
errors,
|
|
name,
|
|
newPassword,
|
|
newPassword2
|
|
});
|
|
} else {
|
|
let hashPass;
|
|
let updated;
|
|
let defaultImage = require('../models/defaultImage').defaultImage;
|
|
|
|
try {
|
|
if (useName && useNewPassword) {
|
|
// Encrypts password
|
|
bcrypt.genSalt(10, (err, salt) => {
|
|
bcrypt.hash(newPassword, salt, (err, hash) => {
|
|
if (err) throw err;
|
|
hashPass = hash;
|
|
});
|
|
});
|
|
|
|
//creates updated image object
|
|
updated = {
|
|
name: name,
|
|
image: {
|
|
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
|
contentType: 'image/png'
|
|
},
|
|
password: hashPass
|
|
}
|
|
}
|
|
|
|
if (useName) {
|
|
//creates updated image object
|
|
updated = {
|
|
name: name,
|
|
image: {
|
|
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
|
contentType: 'image/png'
|
|
}
|
|
}
|
|
}
|
|
|
|
if (useNewPassword) {
|
|
//creates updated image object
|
|
updated = {
|
|
image: {
|
|
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
|
contentType: 'image/png'
|
|
},
|
|
password: hashPass
|
|
}
|
|
}
|
|
|
|
if (!useName && !useNewPassword) {
|
|
//creates updated image object
|
|
updated = {
|
|
image: {
|
|
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
|
contentType: 'image/png'
|
|
}
|
|
}
|
|
}
|
|
|
|
// Deletes File for its not needed
|
|
fs.unlink(path.join(__dirname + '/uploads/' + req.file.filename), function (err) {
|
|
if (err) throw err;
|
|
});
|
|
|
|
//Updates user and redirects to dashboard
|
|
MongoClient.connect(url, {
|
|
useUnifiedTopology: true,
|
|
useNewUrlParser: true}, function(err, db) {
|
|
if (err) throw err;
|
|
let dbo = db.db("XPmockDB");
|
|
dbo.collection('users').updateOne({ _id: ObjectId(_id) }, { $set: updated }, { upsert: true }, function(err, res) {
|
|
if (err) throw err;
|
|
db.close()
|
|
});
|
|
res.redirect('/users/login');
|
|
}
|
|
);
|
|
}
|
|
catch(err) {
|
|
if (useName && useNewPassword) {
|
|
// Encrypts password
|
|
bcrypt.genSalt(10, (err, salt) => {
|
|
bcrypt.hash(newPassword, salt, (err, hash) => {
|
|
if (err) throw err;
|
|
hashPass = hash;
|
|
});
|
|
});
|
|
|
|
//creates updated image object
|
|
updated = {
|
|
name: name,
|
|
image: defaultImage,
|
|
password: hashPass
|
|
}
|
|
}
|
|
|
|
if (useName) {
|
|
//creates updated image object
|
|
updated = {
|
|
name: name,
|
|
image: defaultImage
|
|
}
|
|
}
|
|
|
|
if (useNewPassword) {
|
|
//creates updated image object
|
|
updated = {
|
|
image: defaultImage,
|
|
password: hashPass
|
|
}
|
|
}
|
|
|
|
if (!useName && !useNewPassword) {
|
|
//creates updated image object
|
|
updated = {
|
|
image: defaultImage
|
|
}
|
|
}
|
|
//Updates user and redirects to dashboard
|
|
MongoClient.connect(url, {
|
|
useUnifiedTopology: true,
|
|
useNewUrlParser: true}, function(err, db) {
|
|
if (err) throw err;
|
|
let dbo = db.db("XPmockDB");
|
|
dbo.collection('users').updateOne({ _id: ObjectId(_id) }, { $set: updated }, { upsert: true }, function(err, res) {
|
|
if (err) throw err;
|
|
db.close()
|
|
});
|
|
res.redirect('/users/login');
|
|
}
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Register Teacher
|
|
router.post('/registerTeacher', upload.single('image'), (req, res, next) => {
|
|
// Passes image path to defaultImage Model
|
|
imagePath = __dirname + '/uploads/default-image';
|
|
module.exports = {
|
|
defaultPath: imagePath
|
|
}
|
|
|
|
// Collects input
|
|
let { name, email, password, password2 } = req.body;
|
|
let errors = [];
|
|
|
|
// Check for blanks
|
|
if (!name || !email || !password || !password2) {
|
|
errors.push({ msg: 'Please enter all fields' });
|
|
}
|
|
|
|
if (filter.isProfane(name)) {
|
|
errors.push({ msg: 'Name contains profanity' });
|
|
name = filter.clean(name);
|
|
}
|
|
|
|
if (filter.isProfane(password)) {
|
|
errors.push({ msg: "Password contains profanity" })
|
|
password = filter.clean(password);
|
|
}
|
|
|
|
if(filter.isProfane(password2)) {
|
|
errors.push({ msg: "Password contains profanity" })
|
|
password2 = filter.clean(password2);
|
|
}
|
|
|
|
// Check if password is confirmed
|
|
if (password != password2) {
|
|
errors.push({ msg: 'Passwords do not match' });
|
|
}
|
|
|
|
// Validates password is to required length
|
|
if (password.length < 6) {
|
|
errors.push({ msg: 'Password must be at least 6 characters' });
|
|
}
|
|
|
|
// Error handling
|
|
if (errors.length > 0) {
|
|
// Redirects to register page with errors
|
|
res.render('register', {
|
|
errors,
|
|
name,
|
|
email,
|
|
password,
|
|
password2
|
|
});
|
|
} else {
|
|
// Verifies Email isnt taken
|
|
User.findOne({ email: email }).then(user => {
|
|
if (user) {
|
|
errors.push({ msg: 'Email already exists' });
|
|
// Redirect to dashboard page with errors
|
|
res.render('dashboard', {
|
|
errors,
|
|
name,
|
|
email,
|
|
password,
|
|
password2
|
|
});
|
|
} else {
|
|
|
|
try {
|
|
// Creates new User Object
|
|
const newUser = new User({
|
|
name,
|
|
email,
|
|
password,
|
|
image: {
|
|
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
|
contentType: 'image/png'
|
|
}
|
|
});
|
|
|
|
// Deletes File for its not needed
|
|
fs.unlink(path.join(__dirname + '/uploads/' + req.file.filename), function (err) {
|
|
if (err) throw err;
|
|
});
|
|
|
|
// Encrypts password
|
|
bcrypt.genSalt(10, (err, salt) => {
|
|
bcrypt.hash(newUser.password, salt, (err, hash) => {
|
|
if (err) throw err;
|
|
newUser.password = hash;
|
|
newUser.role = "Teacher";
|
|
newUser
|
|
.save()
|
|
.then(user => {
|
|
req.flash(
|
|
'success_msg'
|
|
);
|
|
// Takes to Dashboard on success
|
|
let value = encodeURIComponent('createdTeacher')
|
|
res.redirect('/dashboard?successRate=' + value);
|
|
})
|
|
.catch(err => console.log(err));
|
|
});
|
|
});
|
|
}
|
|
catch(err) {
|
|
const defaultImage = require('../models/defaultImage').defaultImage;
|
|
// Creates new User Object
|
|
const newUser = new User({
|
|
name,
|
|
email,
|
|
password,
|
|
image: defaultImage
|
|
});
|
|
|
|
// Encrypts password
|
|
bcrypt.genSalt(10, (err, salt) => {
|
|
bcrypt.hash(newUser.password, salt, (err, hash) => {
|
|
if (err) throw err;
|
|
newUser.password = hash;
|
|
newUser.role = "Teacher";
|
|
newUser
|
|
.save()
|
|
.then(user => {
|
|
req.flash(
|
|
'success_msg'
|
|
);
|
|
// Takes to Dashboard on success
|
|
let value = encodeURIComponent('success')
|
|
res.redirect('/dashboard?createTeacher=' + value);
|
|
})
|
|
.catch(err => console.log(err));
|
|
});
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Register
|
|
router.post('/register', upload.single('image'), (req, res, next) => {
|
|
// Passes image path to defaultImage Model
|
|
imagePath = __dirname + '/uploads/default-image';
|
|
module.exports = {
|
|
defaultPath: imagePath
|
|
}
|
|
|
|
// Collects input
|
|
let { name, email, password, password2 } = req.body;
|
|
let errors = [];
|
|
|
|
// Check for blanks
|
|
if (!name || !email || !password || !password2) {
|
|
errors.push({ msg: 'Please enter all fields' });
|
|
}
|
|
|
|
if(filter.isProfane(name)) {
|
|
errors.push({ msg: "Name contains profanity" });
|
|
name = filter.clean(name);
|
|
}
|
|
|
|
if(filter.isProfane(password)) {
|
|
errors.push({ msg: "Password contains profanity" });
|
|
password = filter.clean(password);
|
|
}
|
|
|
|
if(filter.isProfane(password2)) {
|
|
errors.push({ msg: "Password contains profanity" });
|
|
password2 = filter.clean(password2);
|
|
}
|
|
|
|
// Check if password is confirmed
|
|
if (password != password2) {
|
|
errors.push({ msg: 'Passwords do not match' });
|
|
}
|
|
|
|
// Validates password is to required length
|
|
if (password.length < 6) {
|
|
errors.push({ msg: 'Password must be at least 6 characters' });
|
|
}
|
|
|
|
// Error handling
|
|
if (errors.length > 0) {
|
|
// Redirects to register page with errors
|
|
res.render('register', {
|
|
errors,
|
|
name,
|
|
email,
|
|
password,
|
|
password2
|
|
});
|
|
} else {
|
|
// Verifies Email isnt taken
|
|
User.findOne({ email: email }).then(user => {
|
|
if (user) {
|
|
errors.push({ msg: 'Email already exists' });
|
|
// Redirect to register page with errors
|
|
res.render('register', {
|
|
errors,
|
|
name,
|
|
email,
|
|
password,
|
|
password2
|
|
});
|
|
} else {
|
|
|
|
try {
|
|
// Creates new User Object
|
|
const newUser = new User({
|
|
name,
|
|
email,
|
|
password,
|
|
image: {
|
|
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
|
|
contentType: 'image/png'
|
|
}
|
|
});
|
|
|
|
// Deletes File for its not needed
|
|
fs.unlink(path.join(__dirname + '/uploads/' + req.file.filename), function (err) {
|
|
if (err) throw err;
|
|
});
|
|
|
|
// Encrypts password
|
|
bcrypt.genSalt(10, (err, salt) => {
|
|
bcrypt.hash(newUser.password, salt, (err, hash) => {
|
|
if (err) throw err;
|
|
newUser.password = hash;
|
|
newUser
|
|
.save()
|
|
.then(user => {
|
|
req.flash(
|
|
'success_msg',
|
|
'You are now registered and can log in'
|
|
);
|
|
// Takes to login page on success
|
|
res.redirect('/users/login');
|
|
})
|
|
.catch(err => console.log(err));
|
|
});
|
|
});
|
|
}
|
|
catch(err) {
|
|
const defaultImage = require('../models/defaultImage').defaultImage;
|
|
// Creates new User Object
|
|
const newUser = new User({
|
|
name,
|
|
email,
|
|
password,
|
|
image: defaultImage
|
|
});
|
|
|
|
// Encrypts password
|
|
bcrypt.genSalt(10, (err, salt) => {
|
|
bcrypt.hash(newUser.password, salt, (err, hash) => {
|
|
if (err) throw err;
|
|
newUser.password = hash;
|
|
newUser
|
|
.save()
|
|
.then(user => {
|
|
req.flash(
|
|
'success_msg',
|
|
'You are now registered and can log in'
|
|
);
|
|
// Takes to login page on success
|
|
res.redirect('/users/login');
|
|
})
|
|
.catch(err => console.log(err));
|
|
});
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Login
|
|
router.post('/login', (req, res, next) => {
|
|
passport.authenticate('local', {
|
|
successRedirect: '/dashboard',
|
|
failureRedirect: '/users/login',
|
|
failureFlash: true
|
|
})(req, res, next);
|
|
});
|
|
|
|
// Logout
|
|
router.get('/logout', (req, res) => {
|
|
req.logout();
|
|
req.flash('success_msg', 'You are logged out');
|
|
res.redirect('/users/login');
|
|
});
|
|
|
|
module.exports = router;
|