446 lines
15 KiB
JavaScript
446 lines
15 KiB
JavaScript
var ejs = require('ejs');
|
|
var fs = require('fs');
|
|
var path = require('path');
|
|
var adminPath;
|
|
|
|
var PRODUCT_LIST_PATH = "VAP_Availability_List_Nov2016.pdf";
|
|
|
|
//Notes:
|
|
//Use res.send or res.sendFile for static resources (like images or html)
|
|
//Use res.send(ejs.render(htmlStr, viewArgs)) to manually render EJS files
|
|
//Use res.render("my.ejs", {root: adminPath}) to render EJS files (if you have setup the ejs renderer
|
|
|
|
module.exports = function(app, rootPath, passport, smtpTransport, sequelize) {
|
|
adminPath = path.join(rootPath, 'admin');
|
|
|
|
// =====================================
|
|
// HOME PAGE (with login links)
|
|
// =====================================
|
|
//app.get('/', isLoggedIn, function(req, res) {
|
|
// res.render('index.ejs'); // load the index.ejs file
|
|
//});
|
|
//Handle the root being requested, and the search engine requesting a static page with content.
|
|
app.get('/', function(req, res) {
|
|
try {
|
|
//Note: This is for search engines.
|
|
if(typeof(req.query._escaped_fragment_) !== "undefined") {
|
|
console.log("Search Engine Detected");
|
|
var viewArgs = {}; //What args to use for a search engine?
|
|
|
|
//The DIY method which is somewhat brittle since it relies on <!--CONTENT--> existing in the index file, and it replaces that with the contents of the passed parameter (what is after the #!) for the content html which is inserted into the index file in place of <!--CONTENT-->.
|
|
fs.readFile(rootPath + '/index.html', {encoding: "UTF8"}, function(err, indexContent) {
|
|
if(!err) {
|
|
var file = rootPath + '/' + req.query._escaped_fragment_ + '.html';
|
|
|
|
fs.readFile(file, {encoding: "UTF8"}, function(err, content) {
|
|
if(!err) {
|
|
//Non-regex method.//
|
|
if(content.indexOf("<runonce>") != -1 && content.indexOf("</runonce>") != -1) {
|
|
content = content.substr(0, content.indexOf("<runonce>")) + content.substr(content.indexOf("</runonce>") + 10, -1);
|
|
}
|
|
//Doesn't work? Not sure why. Works in the regex test tools.//
|
|
//content = content.replace(/<runonce>(.|\n)*?<\x2frunonce>/, " ");
|
|
|
|
//Doesn't work? Based on the regex failure above, I think that replace is failing.//
|
|
var html = indexContent.replace(/<!--CONTENT-->/g, content);
|
|
|
|
//console.log(html);
|
|
//res.send(ejs.render(html, viewArgs));
|
|
res.send(html);
|
|
}
|
|
else console.log("Error reading the content file '" + file + "'. " + err);
|
|
});
|
|
}
|
|
else console.log("Error reading the index.html file. " + err);
|
|
});
|
|
}
|
|
else {
|
|
//res.render("index.html", {root: rootPath});
|
|
res.sendFile("index.html", {root: rootPath});
|
|
}
|
|
} catch(e) {
|
|
console.log(e);
|
|
}
|
|
});
|
|
|
|
app.get('/admin', isLoggedIn, function(req, res) {
|
|
try {
|
|
//Note: This is for search engines.
|
|
if(typeof(req.query._escaped_fragment_) !== "undefined") {
|
|
var viewArgs = {}; //What args to use for a search engine?
|
|
|
|
//The DIY method which is somewhat brittle since it relies on <!--CONTENT--> existing in the index file, and it replaces that with the contents of the passed parameter (what is after the #!) for the content html which is inserted into the index file in place of <!--CONTENT-->.
|
|
fs.readFile(adminPath + '/index.ejs', {encoding: "UTF8"}, function(err, indexContent) {
|
|
if(!err) {
|
|
var file = adminPath + '/' + req.query._escaped_fragment_ + '.ejs';
|
|
|
|
fs.readFile(file, {encoding: "UTF8"}, function(err, content) {
|
|
if(!err) {
|
|
//Non-regex method.//
|
|
if(content.indexOf("<runonce>") != -1 && content.indexOf("</runonce>") != -1) {
|
|
content = content.substr(0, content.indexOf("<runonce>")) + content.substr(content.indexOf("</runonce>") + 10, -1);
|
|
}
|
|
//Doesn't work? Not sure why. Works in the regex test tools.//
|
|
//content = content.replace(/<runonce>(.|\n)*?<\x2frunonce>/, " ");
|
|
|
|
//Doesn't work? Based on the regex failure above, I think that replace is failing.//
|
|
var html = indexContent.replace(/<!--CONTENT-->/g, content);
|
|
|
|
//console.log(html);
|
|
res.send(ejs.render(html, viewArgs));
|
|
}
|
|
else console.log("Error reading the content file '" + file + "'. " + err);
|
|
});
|
|
}
|
|
else console.log("Error reading the index.ejs file. " + err);
|
|
});
|
|
}
|
|
else {
|
|
//console.log("Looking for index.ejs in " + adminPath);
|
|
//res.render("index.ejs", {root: adminPath});
|
|
res.render(path.join(adminPath, req.baseUrl, "index"));
|
|
}
|
|
} catch(e) {console.log(e);}
|
|
});
|
|
|
|
app.use('/ContactUs', function(req, res) {
|
|
try {
|
|
var firstName = req.body.FirstName;
|
|
var lastName = req.body.LastName;
|
|
var email = req.body.Email;
|
|
var message = req.body.Text;
|
|
var params = {from: config.fromAddress, to: config.contactUsRecipient, subject: "Contact Us", text: "A user has commented via the Petit Teton website.\n\nFirst Name: " + firstName + "\nLast Name: " + lastName + "\nEmail: " + email + "\n" + message};
|
|
|
|
smtpTransport.sendMail(params, function(error, response) {
|
|
if(error) {
|
|
try {
|
|
console.log("Received an error while sending the contact us email to the admin. " + error);
|
|
fs.appendFile(rootPath + '/emailFailures.txt', JSON.stringify(params) + '\n', function(err) {if(err) {console.log("Failed to write email data to file! (contact us)");}});
|
|
} catch(e) {console.log(e);}
|
|
}
|
|
});
|
|
|
|
res.status(200).send('success');
|
|
} catch(e) {console.log(e);}
|
|
});
|
|
|
|
// =====================================
|
|
// LOGIN
|
|
// =====================================
|
|
// show the login form
|
|
app.get('/admin/login', function(req, res) {
|
|
// render the page and pass in any flash data if it exists
|
|
res.render(path.join(adminPath, req.baseUrl, 'login.ejs'), { message: req.flash('loginMessage') });
|
|
});
|
|
|
|
// process the login form
|
|
app.post('/admin/login', passport.authenticate('local-login', {successRedirect: '/admin', failureRedirect: '/admin/login', failureFlash: true}));
|
|
|
|
// =====================================
|
|
// SIGNUP
|
|
// =====================================
|
|
// show the signup form
|
|
/* Turned off since only admin users can add admin users.
|
|
app.get('/admin/signup', function(req, res) {
|
|
|
|
// render the page and pass in any flash data if it exists
|
|
res.render(path.join(adminPath, req.baseUrl, 'signup.ejs'), { message: req.flash('signupMessage') });
|
|
});
|
|
|
|
app.post('/admin/signup', passport.authenticate('local-signup', {successRedirect: '/admin', failureRedirect: '/admin/signup', failureFlash: true}));
|
|
*/
|
|
// =====================================
|
|
// PROFILE SECTION
|
|
// =====================================
|
|
// we will want this protected so you have to be logged in to visit
|
|
// we will use route middleware to verify this (the isLoggedIn function)
|
|
app.get('/admin/profile', isLoggedIn, function(req, res) {
|
|
res.render(path.join(adminPath, req.baseUrl, 'profile.ejs'), {
|
|
user : req.user // get the user out of session and pass to template
|
|
});
|
|
});
|
|
|
|
// =====================================
|
|
// LOGOUT
|
|
// =====================================
|
|
app.get('/admin/logout', function(req, res) {
|
|
req.logout();
|
|
res.redirect('/');
|
|
});
|
|
|
|
// Check for an ejs first even if an html is requested.
|
|
app.get('/admin/*.html', isLoggedIn, function(req, res) {
|
|
var ejs = req.path.substring(0, req.path.length - 4) + "ejs";
|
|
|
|
//console.log("Checking for an ejs: " + ejs);
|
|
|
|
fs.stat(path.join(rootPath, ejs), function(err, stats) {
|
|
if(!err) {
|
|
res.render(path.join(rootPath, ejs));
|
|
}
|
|
else {
|
|
res.sendFile(path.join(rootPath, req.path));
|
|
//res.sendFile(req.path);
|
|
}
|
|
});
|
|
});
|
|
|
|
/* Test code to find all Categories and Subcategories.
|
|
sequelize.models.Category.findAll({
|
|
include:
|
|
[
|
|
{model: sequelize.models.Subcategory, paranoid: true, as: 'subcategories'}
|
|
],
|
|
order: ['name', ['name']]
|
|
}).then(function(values) {
|
|
console.log(values);
|
|
}).catch(function(err) {
|
|
console.log(err);
|
|
});
|
|
*/
|
|
|
|
app.use('/ProductList', function(req, res) {
|
|
try {
|
|
res.sendFile(path.join(rootPath, PRODUCT_LIST_PATH));
|
|
}
|
|
catch(e) {
|
|
console.log(e);
|
|
}
|
|
});
|
|
|
|
//Allows the client to query using the models defined by the application. Returns status codes or the results of the queries.
|
|
app.use('/admin/data/:cls/:query', isLoggedIn, function(req, res) {
|
|
try {
|
|
if(req.user.admin) {
|
|
//var params = Object.keys(req.body).length == 0 ? req.query : req.body; //Use the Request.query if Request.body is empty.
|
|
var params = req.query;
|
|
var cls = req.params.cls;
|
|
var query = req.params.query;
|
|
var model = sequelize.models[cls];
|
|
|
|
//Merge the Request.body parameters into the params object.
|
|
//TODO: Can we just use extend?
|
|
Object.keys(req.body).forEach(function(key) {params[key] = req.body[key]});
|
|
|
|
//The client must wrapper any JSON it wants to send into another JSON object whose sole attribute is 'request' and whose value is the actual parameter JSON stringified.
|
|
//This is because for some unknown reason, jquery.ajax (or derivative methods) does not stringify the JSON correctly (converts bool, int, etc, into strings), and the server cannot convert the strings back into native types.
|
|
params = params.request ? JSON.parse(params.request) : params;
|
|
|
|
if(!model) {
|
|
res.status(400).end();
|
|
}
|
|
else {
|
|
res.header("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
res.header("Pragma", "no-cache");
|
|
res.header("Expires", 0);
|
|
|
|
switch(query) {
|
|
case 'readAll':
|
|
case 'findAll':
|
|
case 'getAll': {
|
|
//Check the params for model references that need to be linked to the correct class. Example:
|
|
//{include: [{model: 'Subcategory', paranoid: true, as: 'subcategories'}], order: ['name', ['name']]}
|
|
if(params.include) {
|
|
var include = params.include;
|
|
|
|
for(var includeIndex = 0; includeIndex < include.length; includeIndex++) {
|
|
var nextInclude = include[includeIndex];
|
|
|
|
if(nextInclude.model) {
|
|
nextInclude.model = sequelize.models[nextInclude.model];
|
|
}
|
|
}
|
|
}
|
|
|
|
model.findAll(params).then(function(values) {
|
|
res.json(values);
|
|
}).catch(function(err) {
|
|
console.log(err);
|
|
res.status(400).end();
|
|
});
|
|
break;
|
|
}
|
|
case 'read':
|
|
case 'readOne':
|
|
case 'readFirst':
|
|
case 'find':
|
|
case 'findOne':
|
|
case 'findFirst':
|
|
case 'get':
|
|
case 'getFirst':
|
|
case 'getOne': {
|
|
//Check the params for model references that need to be linked to the correct class. Example:
|
|
//{include: [{model: 'Subcategory', paranoid: true, as: 'subcategories'}], order: ['name', ['name']]}
|
|
if(params.include) {
|
|
var include = params.include;
|
|
|
|
for(var includeIndex = 0; includeIndex < include.length; includeIndex++) {
|
|
var nextInclude = include[includeIndex];
|
|
|
|
if(nextInclude.model) {
|
|
nextInclude.model = sequelize.models[nextInclude.model];
|
|
}
|
|
}
|
|
}
|
|
|
|
model.find(params).then(function(value) {
|
|
res.json(value);
|
|
}).catch(function(err) {
|
|
console.log(err);
|
|
res.status(400).end();
|
|
});
|
|
break;
|
|
}
|
|
case 'create':
|
|
case 'insert':
|
|
case 'new': {
|
|
model.create(params).then(function(user) {
|
|
//res.json({result: 'success'});
|
|
res.status(200).end();
|
|
}).catch(function(err) {
|
|
console.log(err);
|
|
//res.json({result: 'duplicate'});
|
|
res.status(400).end();
|
|
});
|
|
break;
|
|
}
|
|
case 'delete':
|
|
case 'remove':
|
|
case 'destroy': {
|
|
//params: {where: {id: myId}}
|
|
model.destroy(params).then(function(count) {
|
|
if(count == 1) {
|
|
//res.json({result: 'success'});
|
|
res.status(200).end();
|
|
}
|
|
else {
|
|
//res.json({result: 'failure'});
|
|
res.status(400).end();
|
|
}
|
|
}).catch(function(err) {
|
|
console.log(err);
|
|
//res.json({result: 'failure'});
|
|
res.status(400).end();
|
|
});
|
|
break;
|
|
}
|
|
case 'restore': {
|
|
params.paranoid = false;
|
|
model.find(params).then(function(value) {
|
|
if(value) {
|
|
value.setDataValue('deletedAt', null);
|
|
value.save({paranoid: false}).then(function() {
|
|
res.status(200).end();
|
|
}).catch(function(err) {
|
|
console.log(err);
|
|
res.status(400).end();
|
|
});
|
|
}
|
|
else {
|
|
res.status(400).end();
|
|
}
|
|
}).catch(function(err) {
|
|
console.log(err);
|
|
res.status(400).end();
|
|
});
|
|
break;
|
|
}
|
|
case 'update':
|
|
case 'change':
|
|
case 'edit':
|
|
case 'modify': {
|
|
model.findById(params.id, {}).then(function(myModel) {
|
|
for(var key in params) {
|
|
if(key != 'id') {
|
|
myModel[key] = params[key];
|
|
}
|
|
}
|
|
|
|
return myModel.save();
|
|
}).then(function() {
|
|
//res.json({result: 'success'});
|
|
res.status(200).end();
|
|
}).catch(function(err) {
|
|
console.log(err);
|
|
//res.json({result: 'failure'});
|
|
res.status(400).end();
|
|
});
|
|
break;
|
|
}
|
|
default: {
|
|
res.status(400).end();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
//TODO: Return some kind of error.
|
|
res.status(400).end();
|
|
}
|
|
}
|
|
catch(e) {
|
|
console.log(e);
|
|
res.status(400).end();
|
|
}
|
|
});
|
|
|
|
/*
|
|
app.get('/admin/getCategories', isLoggedIn, function(req, res) {
|
|
sequelize.models.Category.findAll({attributes: ['id', 'name', 'visible'], order: [['name', 'DESC'], ['visible', 'DESC']]}).then(function(values) {
|
|
res.json(values);
|
|
});
|
|
});
|
|
|
|
app.get('/admin/getSubcategories', isLoggedIn, function(req, res) {
|
|
sequelize.models.Subcategory.findAll({where: {categoryId: req.query.id}, attributes: ['id', 'name', 'visible'], order: [['name', 'DESC'], ['visible', 'DESC']]}).then(function(values) {
|
|
res.json(values);
|
|
}).catch(function(error) {
|
|
console.log(error);
|
|
res.json("[]");
|
|
});
|
|
});
|
|
|
|
app.get('/admin/getItems', isLoggedIn, function(req, res) {
|
|
sequelize.models.Item.findAll({where: {subcategoryId: req.query.id}, attributes: ['id', 'name', 'counts', 'visible', 'subcategoryId'], order: [['name', 'DESC'], ['visible', 'DESC']]}).then(function(values) {
|
|
res.json(values);
|
|
});
|
|
});
|
|
|
|
app.get('/admin/getMeasures', isLoggedIn, function(req, res) {
|
|
sequelize.models.Measure.findAll({attributes: ['id', 'name', "image", 'postfix', 'visible'], order: [['name', 'DESC'], ['visible', 'DESC']]}).then(function(values) {
|
|
res.json(values);
|
|
});
|
|
});
|
|
|
|
app.get('/admin/getVenues', isLoggedIn, function(req, res) {
|
|
sequelize.models.Venue.findAll({attributes: ['id', 'name', 'visible'], order: [['name', 'DESC'], ['visible', 'DESC']]}).then(function(values) {
|
|
res.json(values);
|
|
});
|
|
});
|
|
|
|
app.get('/admin/toggleVenueVisibility', isLoggedIn, function(req, res) {
|
|
sequelize.models.Venue.find({where: {id: req.query.id}, attributes: ['id', 'name', 'visible']}).then(function(venue) {
|
|
if(venue) {
|
|
venue.visible = venue.visible ? false : true;
|
|
venue.save().then(function() {
|
|
res.json({visible: venue.visible});
|
|
}).catch(function(error) {
|
|
res.json({error: error});
|
|
});
|
|
}
|
|
else {
|
|
res.json({error: "Can't find the venue!"});
|
|
}
|
|
});
|
|
});
|
|
*/
|
|
};
|
|
|
|
// route middleware to make sure a user is logged in
|
|
function isLoggedIn(req, res, next) {
|
|
if(req.isAuthenticated()) return next();
|
|
|
|
//Redirect if the user isn't logged in.
|
|
res.redirect('/admin/login');
|
|
} |