diff --git a/README.md b/README.md index 20941c87..f8671efe 100644 --- a/README.md +++ b/README.md @@ -385,6 +385,12 @@ Configuration options reference If the endpoint doesn't provide the email address for the user, allow empty emails to authenticate anyway. Note that GitHub authentication usually requires this to be `true` (unless all wiki users have public email addresses on their GitHub accounts). +#### authorization.moderatorsFile (string: "") + + Absolute path for your moderators YAML file. If used, this file must contain a list of `usernames` and `emails` for users who have write access to the wiki. A user who has a match in either the `usernames` or `emails` list will have right access. + + If this field is left blank, all logged in users will have write access to the wiki. + #### pages.index (string: "Home") Defines the page name for the index of the wiki diff --git a/lib/app.js b/lib/app.js index c6f5a65b..806c8a6b 100644 --- a/lib/app.js +++ b/lib/app.js @@ -175,7 +175,23 @@ module.exports.initialize = function (config) { } } - app.all('/pages/*', requireAuthentication) + function requireModerator (req, res, next) { + requireAuthentication(req, res, function(){ + if (!res.locals.user.moderator) { + res.locals.title = '403 - Permission denied' + res.statusCode = 403 + res.render('403.pug') + } else { + next() + } + }) + } + + if (app.locals.config.get('authorization').moderators) { + app.all('/pages/*', requireModerator) + } else { + app.all('/pages/*', requireAuthentication) + } if (!app.locals.config.get('authorization').anonRead) { app.all('/wiki', requireAuthentication) diff --git a/lib/config.js b/lib/config.js index 545bf8cc..899bf707 100644 --- a/lib/config.js +++ b/lib/config.js @@ -36,6 +36,11 @@ module.exports = (function () { } } + // Load moderators from moderatorsFile + if (config.authorization.moderatorsFile){ + config.authorization.moderators = yaml.load(fs.readFileSync(config.authorization.moderatorsFile).toString()) + } + return true }, @@ -121,7 +126,8 @@ module.exports = (function () { anonRead: true, validMatches: '.+', // Breaking changes in Jingo 1.5 (when this parameter has been added): the default for new servers is to NOT allow empty emails to validate - emptyEmailMatches: false + emptyEmailMatches: false, + moderatorsFile: '' }, // Defaults for the pages key are compatible with Jingo < 1 (which means diff --git a/routes/auth.js b/routes/auth.js index c21ada08..205272bd 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -184,6 +184,19 @@ passport.deserializeUser(function (user, done) { user.email = 'jingouser' } + // Check moderator status + user.moderator = false + var moderators = app.locals.config.get('authorization').moderators + if (moderators){ + if (moderators.usernames.indexOf(user.displayName) > -1 || + moderators.emails.indexOf(user.email) > -1){ + user.moderator = true + } + } else { + // If no moderators file supplied everyone is a 'moderator' + user.moderator = true + } + user.asGitAuthor = user.displayName + ' <' + user.email + '>' done(undefined, user) }) diff --git a/views/403.pug b/views/403.pug new file mode 100644 index 00000000..03d19b7e --- /dev/null +++ b/views/403.pug @@ -0,0 +1,7 @@ +extends layout + +block content + #content + .jumbotron + h2 #{title} + p You do not have permission to perform this action