652 lines
22 KiB
JavaScript
652 lines
22 KiB
JavaScript
var express = require('express');
|
|
var flash = require('express-flash');
|
|
var path = require('path');
|
|
var passport = require('passport');
|
|
var Strategy = require('passport-local').Strategy;
|
|
var async = require('async');
|
|
var multer = require('multer');
|
|
var fs = require('fs');
|
|
var markdown = require( "markdown" ).markdown;
|
|
|
|
// Get connected to our database
|
|
var MongoClient = require('mongodb').MongoClient
|
|
|
|
Post = require('./post.js');
|
|
User = require('./user.js');
|
|
Category = require('./category.js');
|
|
var database = require('./db.js');
|
|
var genStatic = require('./genStatic.js');
|
|
var genPhotos = require('./genPhotos.js');
|
|
|
|
var app = express();
|
|
|
|
// Get config variables
|
|
var config = require('./config.js').config;
|
|
|
|
// view engine setup
|
|
app.set('views', path.join(__dirname, 'views'));
|
|
app.set('view engine', 'jade');
|
|
|
|
// Make HTML pretty while we're setting up our jade templates
|
|
// but it doesn't need to be pretty in production.
|
|
|
|
// uncomment after placing your favicon in /public
|
|
//app.use(require('serve-favicon')(path.join(__dirname, 'public',
|
|
// 'favicon.ico')));
|
|
app.use(flash());
|
|
app.use(require('morgan')('dev'));
|
|
app.use(require('cookie-parser')());
|
|
app.use(require('body-parser').urlencoded({ extended: true }));
|
|
app.use(require('express-session')({
|
|
secret: 'amdasdfasdfamd',
|
|
resave: true,
|
|
saveUninitialized: true })
|
|
);
|
|
app.use(express.static(path.join(__dirname, 'public')));
|
|
|
|
var upload = multer({ dest: config.uploadDir });
|
|
|
|
// Setup authentication via twitter.
|
|
passport.use(new Strategy(
|
|
function(username, password, done) {
|
|
User.verify(username, password, function(err, user) {
|
|
console.log("Verifying user: " + username);
|
|
if (!user) { return done(null, false); }
|
|
return done(null, user);
|
|
});
|
|
}
|
|
));
|
|
|
|
passport.serializeUser(function(user, done) {
|
|
console.log("Serializing user: "+user.username);
|
|
done(null, user.username);
|
|
});
|
|
|
|
passport.deserializeUser(function(username, done) {
|
|
console.log("Deserializing user: "+username);
|
|
User.getByUsername(username, function (err, user) {
|
|
if (!user) { return done(false); }
|
|
done(null, user);
|
|
});
|
|
});
|
|
|
|
app.use(passport.initialize());
|
|
app.use(passport.session());
|
|
|
|
// Require logins for all admin pages other pages have to be handled separately.
|
|
app.all('/admin*', require('connect-ensure-login').ensureLoggedIn());
|
|
|
|
// User management routing
|
|
app.get('/login', function(req, res) {
|
|
res.render('admin-login', {user: req.user});
|
|
});
|
|
|
|
app.post('/login',
|
|
passport.authenticate('local', { successReturnToOrRedirect: '/admin', failureRedirect: '/login' })
|
|
);
|
|
|
|
app.get('/logout', function(req, res) {
|
|
req.logout();
|
|
res.redirect('/');
|
|
}
|
|
);
|
|
|
|
// Post management routing
|
|
app.get('/admin/post/list/:start?',
|
|
function(req, res, next) {
|
|
var count = 25;
|
|
if (req.params.start) {
|
|
var start = req.params.start;
|
|
} else {
|
|
var start = 0;
|
|
}
|
|
Post.getPosts(count, start, function(err, posts){
|
|
res.render('admin-post-list', {posts, user: req.user});
|
|
});
|
|
}
|
|
);
|
|
|
|
app.get('/admin/post/view/:uuid?',
|
|
function (req, res, next) {
|
|
if (req.params.uuid) {
|
|
Post.getByUUID(req.params.uuid, function(err, post) {
|
|
res.render('admin-post-view', {
|
|
successNotice: req.flash('successNotice'),
|
|
failureNotice: req.flash('failureNotice'),
|
|
post: post,
|
|
content: markdown.toHTML(post.get("markdown")),
|
|
user: req.user
|
|
})
|
|
})
|
|
}
|
|
else {
|
|
res.redirect('/admin/post/list');
|
|
}
|
|
}
|
|
);
|
|
|
|
app.get('/admin/post/new',
|
|
function(req, res, next) {
|
|
Category.getCategories(null, null, function (err, categories) {
|
|
res.render('admin-post-new', { categories: categories, user: req.user });
|
|
});
|
|
}
|
|
);
|
|
|
|
app.post('/admin/post/new',
|
|
function(req, res, next) {
|
|
var post = new Post();
|
|
post.set("title", req.body.title);
|
|
if (req.body.slug != "") {
|
|
post.set("slug", req.body.slug);
|
|
} else {
|
|
post.set("slug", post.makeSlug());
|
|
}
|
|
if (req.body.postDate != "") {
|
|
post.set("postDate", new Date(req.body.postDate));
|
|
post.set("updatedDate", new Date(req.body.postDate));
|
|
}
|
|
post.tagPost(req.body.tags);
|
|
post.set("markdown", req.body.markdown);
|
|
|
|
Category.getByName(req.body.category, function (err, category) {
|
|
post.set("category", category.get("uuid"));
|
|
console.log(post);
|
|
post.save(function (err) {
|
|
if (!err) {
|
|
req.flash('successNotice', 'Post created.');
|
|
res.redirect('/admin/post/edit/'+post.get("uuid"));
|
|
}
|
|
else {
|
|
req.flash('failureNotice', 'Post creation failed');
|
|
res.redirect('/admin/post/new/');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
);
|
|
|
|
app.get('/admin/post/edit/:uuid',
|
|
function(req, res, next) {
|
|
Post.getByUUID(req.params.uuid, function(err, post) {
|
|
Category.getByUUID(post.get("category"), function(err, category) {
|
|
Category.getCategories(null, null, function(err, categories) {
|
|
var tags = ""
|
|
for (i=0; i<post.get("tags").length; i++) {
|
|
tags += post.get("tags")[i].name + " ";
|
|
}
|
|
res.render('admin-post-edit', {
|
|
successNotice: req.flash('successNotice'),
|
|
failureNotice: req.flash('failureNotice'),
|
|
categories: categories,
|
|
category: category,
|
|
post: post,
|
|
postTags: tags,
|
|
user: req.user
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
);
|
|
|
|
app.post('/admin/post/edit/:uuid',
|
|
function(req, res, next) {
|
|
Post.getByUUID(req.params.uuid, function(err, post) {
|
|
post.set("title", req.body.title);
|
|
post.set("slug", req.body.slug);
|
|
post.set("markdown", req.body.markdown);
|
|
post.set("postDate", new Date(req.body.postDate));
|
|
post.tagPost(req.body.tags);
|
|
Category.getByName(req.body.category, function(err, category) {
|
|
post.set("category", category.get("uuid"));
|
|
post.save(function(err) {
|
|
if (!err) {
|
|
req.flash("successNotice", "Post updated.");
|
|
res.redirect("/admin/post/edit/"+post.get("uuid"));
|
|
}
|
|
else {
|
|
req.flash("failureNotice", "Post failed to update.");
|
|
res.redirect("/admin/post/edit/"+post.get("uuid"));
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
);
|
|
|
|
app.get('/admin/post/regenerate/:id?',
|
|
function(req, res, next) {
|
|
if (req.params.id) {
|
|
genStatic.generateStatic(function(err){ if (err) console.log(err) });
|
|
genPosts.generatePost(req.params.id, function(err) {
|
|
if (!err) {
|
|
req.flash('successNotice', 'Post regenerated successfully.');
|
|
res.redirect('/admin/post/view/'+req.params.id);
|
|
}
|
|
else {
|
|
req.flash('failureNotice', 'Post regeneration failed, check logs.');
|
|
res.redirect('/admin/post/view/'+req.params.id);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
res.redirect('/admin/post/list');
|
|
}
|
|
|
|
}
|
|
);
|
|
|
|
// Photo management Routing
|
|
app.get('/admin/photo/list/:start?',
|
|
function(req, res, next) {
|
|
var count = 25;
|
|
if (req.params.start) {
|
|
var start = req.params.start;
|
|
} else {
|
|
var start = 0;
|
|
}
|
|
database.listPhotos(count, start, function(photos){
|
|
for (photo in photos) {
|
|
var date = new Date(photos[photo].photoDate);
|
|
photos[photo].dateString = date.getFullYear() + '-' +
|
|
("0" + (date.getMonth()+1)).slice(-2) + '-' +
|
|
("0" + date.getDate()).slice(-2);
|
|
}
|
|
res.render('admin-photo-list', {photos, user: req.user});
|
|
});
|
|
}
|
|
);
|
|
|
|
app.get('/admin/photo/view/:id?',
|
|
function (req, res, next) {
|
|
if (req.params.id) {
|
|
database.getPhotoById(req.params.id, function(row) {
|
|
res.render('admin-photo-view', {
|
|
successNotice: req.flash('successNotice'),
|
|
failureNotice: req.flash('failureNotice'),
|
|
photo: row,
|
|
srcPath: '/'+row.path,
|
|
user: req.user
|
|
})
|
|
})
|
|
}
|
|
else {
|
|
res.redirect('/admin/photo/list');
|
|
}
|
|
}
|
|
);
|
|
|
|
app.get('/admin/photo/new',
|
|
function(req, res, next) {
|
|
res.render('admin-photo-new', { user: req.user });
|
|
}
|
|
);
|
|
|
|
app.post('/admin/photo/new',
|
|
upload.single('photo'),
|
|
function(req, res, next) {
|
|
console.log(req.file);
|
|
if ( req.body.title != "") {
|
|
var title = req.body.title;
|
|
}
|
|
else {
|
|
var title = req.file.originalname.split('.').slice(0,-1).join(' ');
|
|
}
|
|
var extension = req.file.originalname.split('.').slice(-1);
|
|
if (req.body.photoDate != "") {
|
|
var photoDate = helper.dateToEpoch(new Date(req.body.photoDate));
|
|
}
|
|
else {
|
|
var photoDate = helper.dateToEpoch(new Date());
|
|
}
|
|
if (req.body.slug != "") {
|
|
var slug = req.body.slug;
|
|
}
|
|
else if ( req.body.title != "" ){
|
|
var slug = helper.makeSlug(title+'-'+photoDate);
|
|
}
|
|
else {
|
|
var cleanFileName = req.file.originalname.split('.').slice(0,-1).join('-');
|
|
var slug = helper.makeSlug(cleanFileName+'-'+photoDate);
|
|
}
|
|
var mimetype = req.file.mimetype;
|
|
var tags = helper.parseTags(req.body.tags);
|
|
var markdown = req.body.markdown;
|
|
var updatedDate = photoDate;
|
|
var createDate = helper.dateToEpoch(new Date());
|
|
var categoryName = req.body.category;
|
|
var path = req.file.path;
|
|
|
|
database.createPhoto(title, slug, markdown, extension, mimetype, photoDate, updatedDate, createDate, path, function(err, row) {
|
|
if (err) console.log(err);
|
|
console.log(row);
|
|
database.tagPhoto(row.id, tags);
|
|
req.flash('successNotice', 'Photo created.');
|
|
res.redirect('/admin/photo/view/'+row.id);
|
|
});
|
|
}
|
|
);
|
|
|
|
app.get('/admin/photo/edit/:id',
|
|
function(req, res, next) {
|
|
var id = req.params.id;
|
|
async.parallel({
|
|
photoTags: function(callback) {
|
|
database.getPhotoTagsAsString(id, function(tagString) {
|
|
callback(null, tagString);
|
|
})
|
|
},
|
|
photo: function(callback) {
|
|
database.getPhotoById(id, function(photo) {
|
|
callback(null, photo);
|
|
})
|
|
}
|
|
},
|
|
function(err, results) {
|
|
res.render('admin-photo-edit', {
|
|
successNotice: req.flash('successNotice'),
|
|
failureNotice: req.flash('failureNotice'),
|
|
photo: results.photo,
|
|
srcPath: '/'+results.photo.path,
|
|
photoTags: results.photoTags,
|
|
formattedDate: helper.epochToDateString(results.photo.photoDate),
|
|
user: req.user
|
|
});
|
|
});
|
|
}
|
|
);
|
|
|
|
app.post('/admin/photo/edit/:id',
|
|
function(req, res, next) {
|
|
var id = req.params.id;
|
|
var title = req.body.title;
|
|
var slug = req.body.slug;
|
|
var markdown = req.body.markdown;
|
|
var photoDate = helper.dateToEpoch(new Date(req.body.photoDate));
|
|
var tags = helper.parseTags(req.body.tags);
|
|
console.log('Post '+id+' update request received');
|
|
database.tagPhoto(id, tags);
|
|
database.updatePhoto(id, title, slug, markdown, photoDate, function(err, row) {
|
|
req.flash('successNotice', 'Photo updated.');
|
|
res.redirect('/admin/photo/view/'+id);
|
|
});
|
|
}
|
|
);
|
|
|
|
app.get('/admin/photo/regenerate/:id',
|
|
function(req, res, next) {
|
|
console.log('Generating resized images for: '+req.params.id);
|
|
genStatic.generateStatic(function(err){ if (err) console.log(err) });
|
|
genPhotos.generatePhotoSizesById(req.params.id, function(err) {
|
|
if (!err) {
|
|
genPhotos.generatePhotoPage(req.params.id, function(err) {
|
|
if (!err) {
|
|
req.flash("successNotice", "Photo regenerated");
|
|
res.redirect('/admin/photo/view/'+req.params.id);
|
|
}
|
|
else {
|
|
req.flash('failureNotice', 'Photo was unable to be resized.');
|
|
res.redirect('/admin/photo/view/'+req.params.id);
|
|
}
|
|
})
|
|
}
|
|
else {
|
|
req.flash('failureNotice', 'Photo was unable to be resized.');
|
|
res.redirect('/admin/photo/view/'+req.params.id);
|
|
}
|
|
});
|
|
}
|
|
);
|
|
|
|
// Admin dashboard page.
|
|
app.get('/admin',
|
|
function(req, res, next) {
|
|
async.parallel({
|
|
categories: function(callback) {
|
|
database.countCategories(function(count) {
|
|
callback(null, count);
|
|
});
|
|
},
|
|
posts: function(callback) {
|
|
Post.countPosts(function(err, count) {
|
|
callback(null, count);
|
|
});
|
|
},
|
|
galleries: function(callback) {
|
|
database.countGalleries(function(count) {
|
|
callback(null, count);
|
|
});
|
|
},
|
|
photos: function(callback) {
|
|
database.countPhotos(function(count) {
|
|
callback(null, count);
|
|
});
|
|
},
|
|
tags: function(callback) {
|
|
database.countTags(function(count) {
|
|
callback(null, count);
|
|
});
|
|
},
|
|
regenerateDate: function(callback) {
|
|
database.getLastRegenerateDate(function(date) {
|
|
var dateString = helper.epochToDateString(date.date).slice(0,-12);
|
|
callback(null, dateString);
|
|
});
|
|
},
|
|
uploadDate: function(callback) {
|
|
database.getLastUploadDate(function(date) {
|
|
var dateString = helper.epochToDateString(date.date).slice(0,-12);
|
|
callback(null, dateString);
|
|
});
|
|
}
|
|
},
|
|
function(err, results) {
|
|
res.render('admin-dashboard', {
|
|
successNotice: req.flash('successNotice'),
|
|
failureNotice: req.flash('failureNotice'),
|
|
categories: results.categories,
|
|
posts: results.posts,
|
|
galleries: results.galleries,
|
|
photos: results.photos,
|
|
tags: results.tags,
|
|
regenerateDate: results.regenerateDate,
|
|
uploadDate: results.uploadDate,
|
|
user: req.user});
|
|
}
|
|
);
|
|
}
|
|
);
|
|
|
|
// Routes for previewing sent versions of the built items.
|
|
app.get('/blog/*',
|
|
require('connect-ensure-login').ensureLoggedIn(),
|
|
function(req, res, next) {
|
|
if (req.params[0] != '') {
|
|
var path = __dirname + '/' + config.genDir + '/blog/' + req.params[0];
|
|
console.log('Trying to serve: ' + path);
|
|
fs.exists(path, function(exists) {
|
|
if (exists) {
|
|
console.log(path + ' exists serving...');
|
|
res.sendFile(path);
|
|
}
|
|
else {
|
|
console.log(path + ' does not exist...');
|
|
if (path.slice(-1) != '/') path += '/';
|
|
path += 'index.html'
|
|
console.log('Trying to serve: ' + path);
|
|
fs.exists(path, function(exists) {
|
|
if (exists) {
|
|
console.log(path + ' exists serving...');
|
|
res.sendFile(path);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
);
|
|
|
|
app.get('/photos/*',
|
|
require('connect-ensure-login').ensureLoggedIn(),
|
|
function(req, res, next) {
|
|
if (req.params[0] != '') {
|
|
var path = __dirname + '/' + config.genDir + '/photos/' + req.params[0];
|
|
console.log('Trying to serve: ' + path);
|
|
fs.exists(path, function(exists) {
|
|
if (exists) {
|
|
console.log(path + ' exists serving...');
|
|
res.sendFile(path);
|
|
}
|
|
else {
|
|
console.log(path + ' does not exist...');
|
|
if (path.slice(-1) != '/') path += '/';
|
|
path += 'index.html'
|
|
console.log('Trying to serve: ' + path);
|
|
fs.exists(path, function(exists) {
|
|
if (exists) {
|
|
console.log(path + ' exists serving...');
|
|
res.sendFile(path);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
);
|
|
|
|
app.get('/galleries/*',
|
|
require('connect-ensure-login').ensureLoggedIn(),
|
|
function(req, res, next) {
|
|
if (req.params[0] != '') {
|
|
var path = __dirname + '/' + config.genDir + '/galleries/' + req.params[0];
|
|
console.log('Trying to serve: ' + path);
|
|
fs.exists(path, function(exists) {
|
|
if (exists) {
|
|
console.log(path + ' exists serving...');
|
|
res.sendFile(path);
|
|
}
|
|
else {
|
|
console.log(path + ' does not exist...');
|
|
if (path.slice(-1) != '/') path += '/';
|
|
path += 'index.html'
|
|
console.log('Trying to serve: ' + path);
|
|
fs.exists(path, function(exists) {
|
|
if (exists) {
|
|
console.log(path + ' exists serving...');
|
|
res.sendFile(path);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
);
|
|
|
|
app.get('/static/*',
|
|
require('connect-ensure-login').ensureLoggedIn(),
|
|
function(req, res, next) {
|
|
if (req.params[0] != '') {
|
|
var path = __dirname + '/' + config.genDir + '/static/' + req.params[0];
|
|
console.log('Trying to serve: ' + path);
|
|
fs.exists(path, function(exists) {
|
|
if (exists) {
|
|
console.log(path + ' exists serving...');
|
|
res.sendFile(path);
|
|
}
|
|
else {
|
|
console.log(path + ' does not exist...');
|
|
if (path.slice(-1) != '/') path += '/';
|
|
path += 'index.html'
|
|
console.log('Trying to serve: ' + path);
|
|
fs.exists(path, function(exists) {
|
|
if (exists) {
|
|
console.log(path + ' exists serving...');
|
|
res.sendFile(path);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
);
|
|
|
|
app.get('/'+config.uploadDir+'/*',
|
|
require('connect-ensure-login').ensureLoggedIn(),
|
|
function(req, res, next) {
|
|
if (req.params[0] != '') {
|
|
var path = __dirname + '/'+ config.uploadDir + '/'+ req.params[0];
|
|
console.log('Trying to serve: ' + path);
|
|
fs.exists(path, function(exists) {
|
|
if (exists) {
|
|
console.log(path + ' exists serving...');
|
|
res.sendFile(path);
|
|
}
|
|
else {
|
|
console.log(path + ' does not exist...');
|
|
if (path.slice(-1) != '/') path += '/';
|
|
path += 'index.html'
|
|
console.log('Trying to serve: ' + path);
|
|
fs.exists(path, function(exists) {
|
|
if (exists) {
|
|
console.log(path + ' exists serving...');
|
|
res.sendFile(path);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
);
|
|
|
|
// Have to have some sort of home page.
|
|
app.get('/', function(req, res, next) {
|
|
res.render('admin-index', { title: 'AMDavidson.com', user: req.user });
|
|
}
|
|
);
|
|
|
|
// catch 404 and forward to error handler
|
|
app.use(function(req, res, next) {
|
|
var err = new Error('Not Found');
|
|
err.status = 404;
|
|
next(err);
|
|
});
|
|
|
|
// error handlers
|
|
|
|
// development error handler
|
|
// will print stacktrace
|
|
if (app.get('env') === 'development') {
|
|
app.use(function(err, req, res, next) {
|
|
res.status(err.status || 500);
|
|
res.render('admin-error', {
|
|
message: err.message,
|
|
error: err,
|
|
user: req.user
|
|
});
|
|
});
|
|
}
|
|
|
|
// production error handler
|
|
// no stacktraces leaked to user
|
|
app.use(function(err, req, res, next) {
|
|
res.status(err.status || 500);
|
|
res.render('error', {
|
|
message: err.message,
|
|
user: req.user,
|
|
error: {}
|
|
});
|
|
});
|
|
|
|
|
|
app.set('port', process.env.PORT || 3000)
|
|
var server = require('http').createServer(app)
|
|
|
|
MongoClient.connect('mongodb://localhost/crunch', function(err, database) {
|
|
if (!err) {
|
|
global.db = database;
|
|
server.listen(app.get('port'), function() {
|
|
console.log("Server listening on port " + app.get('port'));
|
|
});
|
|
}
|
|
});
|