merge master

This commit is contained in:
riley
2017-05-22 13:10:43 -06:00
105 changed files with 2436 additions and 435 deletions
-7
View File
@@ -4,8 +4,6 @@ const TagLinkSchema = require('./schema/tag_link');
const uuid = require('uuid');
const COMMENT_STATUS = require('./enum/comment_status');
const EDIT_WINDOW_MS = 30 * 1000; // 30 seconds
/**
* The Mongo schema for a Comment Status.
* @type {Schema}
@@ -97,12 +95,7 @@ CommentSchema.virtual('edited').get(function() {
return this.body_history.length > 1;
});
CommentSchema.virtual('editableUntil').get(function() {
return new Date(Number(this.created_at) + EDIT_WINDOW_MS);
});
// Comment model.
const Comment = mongoose.model('Comment', CommentSchema);
module.exports = Comment;
module.exports.EDIT_WINDOW_MS = EDIT_WINDOW_MS;
+2 -1
View File
@@ -1,4 +1,5 @@
module.exports = [
'ADMIN',
'MODERATOR'
'MODERATOR',
'STAFF'
];
+7
View File
@@ -86,6 +86,13 @@ const SettingSchema = new Schema({
default: ['localhost']
}
},
// Length of time (in milliseconds) after a comment is posted that it can still be edited by the author
editCommentWindowLength: {
type: Number,
min: [0, 'Edit Comment Window length must be greater than zero'],
default: 30 * 1000,
},
tags: [TagSchema]
}, {
timestamps: {
+14 -37
View File
@@ -3,6 +3,8 @@ const bcrypt = require('bcrypt');
const Schema = mongoose.Schema;
const uuid = require('uuid');
const TagLinkSchema = require('./schema/tag_link');
const intersection = require('lodash/intersection');
const can = require('../perms');
// USER_ROLES is the array of roles that is permissible as a user role.
const USER_ROLES = require('./enum/user_roles');
@@ -105,6 +107,14 @@ const UserSchema = new Schema({
default: false
},
// User's suspension details.
suspension: {
until: {
type: Date,
default: null,
},
},
// User's settings
settings: {
bio: {
@@ -154,14 +164,10 @@ UserSchema.index({
});
/**
* Returns true if the user has all the roles specified.
* returns true if a commenter is staff
*/
UserSchema.method('hasRoles', function(...roles) {
return roles.every((role) => {
// TODO: remove toUpperCase() once we've migrated usage.
return this.roles.indexOf(role.toUpperCase()) >= 0;
});
UserSchema.method('isStaff', function () {
return intersection(['ADMIN', 'MODERATOR', 'STAFF'], this.roles).length !== 0;
});
/**
@@ -183,41 +189,12 @@ UserSchema.method('verifyPassword', function(password) {
});
});
/**
* All the graph operations that are available for a user.
* @type {Array}
*/
const USER_GRAPH_OPERATIONS = [
'mutation:createComment',
'mutation:createAction',
'mutation:deleteAction',
'mutation:editName',
'mutation:setUserStatus',
'mutation:suspendUser',
'mutation:setCommentStatus',
'mutation:addTag',
'mutation:removeTag',
'mutation:editComment'
];
/**
* Can returns true if the user is allowed to perform a specific graph
* operation.
*/
UserSchema.method('can', function(...actions) {
if (actions.some((action) => USER_GRAPH_OPERATIONS.indexOf(action) === -1)) {
throw new Error(`invalid actions: ${actions}`);
}
if (this.status === 'BANNED') {
return false;
}
if (actions.some((action) => action === 'mutation:setUserStatus' || action === 'mutation:suspendUser' || action === 'mutation:setCommentStatus') && !this.hasRoles('ADMIN')) {
return false;
}
return true;
return can(this, ...actions);
});
// Create the User model.