diff options
| author | Jules Laplace <jules@okfoc.us> | 2014-06-09 16:14:49 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2014-06-09 16:14:49 -0400 |
| commit | 1165ef5440e643252635aeea73a14cba0bb2e461 (patch) | |
| tree | 6563f5314c774ee3ac9216e8375b38037b2eddcb /server | |
| parent | b1974b9c2fe6ee1f35b3e34895f134d906299cec (diff) | |
documentation system
Diffstat (limited to 'server')
| -rw-r--r-- | server/index.js | 13 | ||||
| -rw-r--r-- | server/lib/api.js | 54 | ||||
| -rw-r--r-- | server/lib/auth.js | 9 | ||||
| -rw-r--r-- | server/lib/middleware.js | 6 | ||||
| -rw-r--r-- | server/lib/schemas/Documentation.js | 33 | ||||
| -rw-r--r-- | server/lib/schemas/Project.js | 8 | ||||
| -rw-r--r-- | server/lib/schemas/User.js | 13 | ||||
| -rw-r--r-- | server/lib/util.js | 51 | ||||
| -rw-r--r-- | server/lib/views.js | 51 |
9 files changed, 208 insertions, 30 deletions
diff --git a/server/index.js b/server/index.js index a1efaf2..f418c42 100644 --- a/server/index.js +++ b/server/index.js @@ -63,6 +63,9 @@ app.all('*', middleware.ensureLocals); // Initialize views app.get('/', views.home); +app.get('/about', views.docs); +app.get('/about/:name/edit', views.docs); +app.get('/about/:name', views.docs); app.get('/login', views.modal); app.get('/signup', views.modal); app.post('/auth/signin', auth.loggedInLocal); @@ -74,10 +77,18 @@ app.get('/auth/facebook', auth.login('facebook')); app.get('/auth/facebook/callback', auth.loggedIn('facebook')); app.get('/profile', views.profile) app.get('/profile/edit', views.profile) + app.get('/api/profile', middleware.ensureAuthenticated, api.profile.show) app.put('/api/profile', middleware.ensureAuthenticated, api.profile.update) -app.get('/project/new', views.modal); +app.get('/project/new', middleware.ensureAuthenticated, views.modal); + +app.get('/staff', middleware.ensureAuthenticated, middleware.ensureIsStaff, views.staff.index); +app.get('/staff/bless', middleware.ensureAuthenticated, views.staff.bless); + +app.get('/api/docs', middleware.ensureAuthenticated, middleware.ensureIsStaff, api.docs.show) +app.post('/api/docs/new', middleware.ensureAuthenticated, middleware.ensureIsStaff, api.docs.create) +app.post('/api/docs/edit', middleware.ensureAuthenticated, middleware.ensureIsStaff, api.docs.update) app.get(/^\/([-_a-zA-Z0-9]+)\/?$/, views.profile) diff --git a/server/lib/api.js b/server/lib/api.js index cf2a911..9a8a1fc 100644 --- a/server/lib/api.js +++ b/server/lib/api.js @@ -8,8 +8,8 @@ var passport = require('passport'), util = require('./util'), upload = require('./upload'), config = require('../../config.json'), - User = require('./schemas/User'); - + User = require('./schemas/User'), + Documentation = require('./schemas/Documentation'); var api = { @@ -35,11 +35,10 @@ var api = { } delete data.old_password delete data.new_password - delete data.isAdmin + delete data.isStaff + data.updated_at = new Date () if (req.files.avatar) { - // handle the upload here - console.log("GOT SOME FILES") upload.put("avatars", req.files.avatar, { acceptable: function(){ console.log("acceptable") @@ -66,6 +65,51 @@ var api = { }) } } + }, + + + docs: { + show: function(req, res){ + Documentation.findOne({ name: req.query.name }, function(err, doc){ + if (doc) { + res.json(doc) + } + else { + var name = util.sanitize(req.query.name) + if (name == "new") { + name = "" + } + res.json({ name: name, isNew: true }) + } + }) + }, + + create: function(req, res){ + var data = util.cleanQuery(req.body) + data.name = data.new_name + delete data.new_name + new Documentation(data).save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + res.json(doc) + }) + }, + + update: function(req, res){ + var data = util.cleanQuery(req.body) + if (data.name == "new") { + return api.docs.create(req, res) + } + Documentation.findOne({ name: data.name }, function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + data.name = data.new_name + delete data.new_name + _.extend(doc, data) + doc.save(function(err, doc){ + if (err || ! doc) { return res.json({ error: err }) } + res.json(doc) + }) + }) + }, } } diff --git a/server/lib/auth.js b/server/lib/auth.js index 5a952f5..47c1c7c 100644 --- a/server/lib/auth.js +++ b/server/lib/auth.js @@ -98,7 +98,7 @@ var auth = { }, deserializeUser: function (id, done) { - User.findOne({ _id: id }, "_id displayName username photo", function (err, user) { + User.findOne({ _id: id }, "_id displayName username photo isStaff", function (err, user) { done(err, user); }); }, @@ -112,7 +112,7 @@ var auth = { shasum.update(password) password = shasum.digest('hex'); - User.findOne({ username: username }, function (err, user) { + User.findOne({ username: username }, "_id username", function (err, user) { if (user) { res.json({ error: { errors: { username: { message: "Username has been taken" } } } }) return @@ -121,7 +121,10 @@ var auth = { username: username, displayName: username, password: password, - email: email + email: email, + created_ip: util.ipToNum(req.connection.remoteAddress), + last_ip: util.ipToNum(req.connection.remoteAddress), + created_at: new Date () } new User(data).save(function(err, user){ if (err || ! data) { return res.json({ error: err }) } diff --git a/server/lib/middleware.js b/server/lib/middleware.js index fb19e68..dbe0b26 100644 --- a/server/lib/middleware.js +++ b/server/lib/middleware.js @@ -25,10 +25,10 @@ var middleware = { next(); }, - ensureIsAdmin: function (req, res, next) { + ensureIsStaff: function (req, res, next) { User.findOne({ _id: req.user._id }, function (err, user) { - if (! user.isAdmin) { - return res.redirect('http://' + config.host + '/' + req.user.username); + if (! user.isStaff) { + return res.redirect('http://' + config.host + '/'); } req.user = user next(); diff --git a/server/lib/schemas/Documentation.js b/server/lib/schemas/Documentation.js new file mode 100644 index 0000000..35cf34f --- /dev/null +++ b/server/lib/schemas/Documentation.js @@ -0,0 +1,33 @@ +/* jshint node: true */ + + +var mongoose = require('mongoose'), + _ = require('lodash'), + util = require('../util'); + +var DocumentationSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + unique: true, + validate: [function (val){ + val = util.slugify(val || this.displayName || "") + if (! val.length) return false + if (val == "new") return false + return true + },"{PATH} name is required"] + }, + displayName: { + type: String, + }, + body: { + type: String, + default: "" + }, + created_at: { type: Date }, + updated_at: { type: Date }, +}); + + +module.exports = exports = mongoose.model('documentation', DocumentationSchema); +exports.schema = DocumentationSchema; diff --git a/server/lib/schemas/Project.js b/server/lib/schemas/Project.js index a0382b3..5176e06 100644 --- a/server/lib/schemas/Project.js +++ b/server/lib/schemas/Project.js @@ -1,10 +1,9 @@ /* jshint node: true */ -var NONALPHANUMERICS_REGEX = new RegExp('[^-_a-zA-Z0-9]', 'g') - var mongoose = require('mongoose'), _ = require('lodash'), - config = require('../../../config.json'); + config = require('../../../config.json'), + util = require('../util'); var ProjectSchema = new mongoose.Schema({ name: { type: String, required: true }, @@ -12,7 +11,7 @@ var ProjectSchema = new mongoose.Schema({ type: String, required: true, validate: [function (val){ - val = (val || this.displayName || "").replace(/\s/g,"-").replace(NONALPHANUMERICS_REGEX, '-').replace(/-+/g,"-") + val = util.sanitize(val || this.displayName || "") if (! val.length) return false return true },"{PATH} name is required"] @@ -33,6 +32,5 @@ var ProjectSchema = new mongoose.Schema({ updated_at: { type: Date }, }); - module.exports = exports = mongoose.model('project', ProjectSchema); exports.schema = ProjectSchema; diff --git a/server/lib/schemas/User.js b/server/lib/schemas/User.js index 24b0adf..5a93df2 100644 --- a/server/lib/schemas/User.js +++ b/server/lib/schemas/User.js @@ -1,7 +1,5 @@ /* jshint node: true */ -var NONALPHANUMERICS_REGEX = new RegExp('[^-_a-zA-Z0-9]', 'g') - var mongoose = require('mongoose'), _ = require('lodash'), crypto = require('crypto'), @@ -16,7 +14,7 @@ var UserSchema = new mongoose.Schema({ type: String, required: true, validate: [function (val) { - val = val.replace(NONALPHANUMERICS_REGEX, "") + val = util.slugify(val) this.username = val.toLowerCase() switch (val) { case 'login': @@ -27,6 +25,7 @@ var UserSchema = new mongoose.Schema({ case 'about': case 'settings': case 'assets': + case 'staff': case 'admin': case 'terms': case 'api': @@ -39,7 +38,7 @@ var UserSchema = new mongoose.Schema({ return true }, "{PATH} is not an acceptable name"] }, - email: { type: String, efault: "" }, + email: { type: String, default: "" }, emailVerified: { type: Boolean, default: false, @@ -57,7 +56,11 @@ var UserSchema = new mongoose.Schema({ website: { type: String, default: "" }, twitterName: { type: String, default: "" }, facebookUrl: { type: String, default: "" }, - isAdmin: { type: Boolean, default: false } + isStaff: { type: Boolean, default: false }, + created_at: { type: Date }, + updated_at: { type: Date }, + created_ip: { type: Number }, + last_ip: { type: Number }, }); UserSchema.methods.validPassword = function (pw) { diff --git a/server/lib/util.js b/server/lib/util.js index 88d16cb..228563a 100644 --- a/server/lib/util.js +++ b/server/lib/util.js @@ -1,21 +1,56 @@ var _ = require('lodash'); +var whitespace = new RegExp('\s', 'g') var whitespaceHead = /^\s+/ var whitespaceTail = /\s+$/ +var nonAlphanumerics = new RegExp('[^-_a-zA-Z0-9]', 'g') +var consecutiveDashes = new RegExp("-+", 'g') +var entities = new RegExp("[<>&]", 'g') var util = {} -util.trim = function (s){ return s.replace(whitespaceHead,"").replace(whitespaceTail,"") } + +util.trim = function (s){ return (s || "").replace(whitespaceHead,"").replace(whitespaceTail,"") } + +util.slugify = function (s){ + return (s || "").replace(whitespace,"-").replace(nonAlphanumerics, '-').replace(consecutiveDashes,"-") +} + +util.sanitize = function (s){ + return (s || "").replace(entities, "") +} + +util.capitalize = function (s) { + return (s || "").split(" ").map(util.capitalizeWord).join(" "); +} + +util.capitalizeWord = function (s) { + return s.charAt(0).toUpperCase() + s.slice(1); +} + util.cleanQuery = function (query) { - var update = _.extend({}, query); - delete update._id; - delete update.created_at; - delete update.modified_at; - delete update.modified_by; - delete update.created_by; - return update; + var update = _.extend({}, query); + delete update._id; + delete update.created_at; + delete update.modified_at; + delete update.modified_by; + delete update.created_by; + return update; } +util.ip2num = function(dot) { + var d = dot.split('.'); + return ((((((+d[0])*256)+(+d[1]))*256)+(+d[2]))*256)+(+d[3]); +} + +util.num2ip = function(num) { + var d = num % 256; + for (var i = 3; i > 0; i--) { + num = Math.floor(num/256); + d = num % 256 + '.' + d; + } + return d; +} module.exports = util diff --git a/server/lib/views.js b/server/lib/views.js index 224dd3f..94774cb 100644 --- a/server/lib/views.js +++ b/server/lib/views.js @@ -2,9 +2,20 @@ var User = require('./schemas/User'), Project = require('./schemas/Project'), + Documentation = require('./schemas/Documentation'), config = require('../../config'), + marked = require('marked'), + util = require('./util'), _ = require('lodash'); +marked.setOptions({ + renderer: new marked.Renderer(), + gfm: true, + sanitize: true, + smartLists: true, + smartypants: true, +}); + var views = {} views.modal = function (req, res) { @@ -17,6 +28,34 @@ views.home = function (req, res) { }) } +views.docs = function (req, res){ + var name = req.params.name || "index" + + if (name === "new") { + res.render('docs', { + doc: { name: "new" }, + content: null, + isNew: true + }) + return + } + + Documentation.findOne({ name: name }, function(err, doc) { + if (err || ! doc) { + return res.render('docs', { + doc: { name: util.sanitize(name) }, + content: null, + isNew: true + }) + } + res.render('docs', { + doc: doc, + content: marked(doc.body), + isNew: false + }) + }) +} + views.profile = function (req, res) { var username = req.params[0] || req.user.username if (username) { @@ -43,4 +82,16 @@ views.profile = function (req, res) { } } +views.staff = { + index: function(req, res){ + res.render('staff') + }, + bless: function(req, res){ + req.user.isStaff = true + req.user.save(function(){ + res.redirect("/staff") + }) + }, +} + module.exports = views |
