category whitelist for replying to posts, lots of refactoring, too

v1.18.x
Julian Lam 11 years ago
parent 182659d0e1
commit 5ee5c8179a

@ -171,28 +171,6 @@ var RDB = require('./redis.js'),
});
};
Categories.privileges = function(cid, uid, callback) {
function isModerator(next) {
user.isModerator(uid, cid, function(isMod) {
next(null, isMod);
});
}
function isAdministrator(next) {
user.isAdministrator(uid, function(isAdmin) {
next(null, isAdmin);
});
}
async.parallel([isModerator, isAdministrator], function(err, results) {
callback({
editable: results.indexOf(true) !== -1 ? true : false,
view_deleted: results.indexOf(true) !== -1 ? true : false
});
});
};
Categories.isTopicsRead = function(cid, uid, callback) {
RDB.zrange('categories:' + cid + ':tid', 0, -1, function(err, tids) {

@ -0,0 +1,32 @@
var Groups = require('./groups'),
User = require('./user'),
async = require('async'),
CategoryTools = {};
CategoryTools.privileges = function(cid, uid, callback) {
async.parallel({
"+r": function(next) {
Groups.isMemberByGroupName(uid, 'cid:' + cid + ':privileges:+r', next);
},
"+w": function(next) {
Groups.isMemberByGroupName(uid, 'cid:' + cid + ':privileges:+w', next);
},
moderator: function(next) {
User.isModerator(uid, cid, next);
},
admin: function(next) {
User.isAdministrator(uid, next);
}
}, function(err, privileges) {
callback(err, !privileges ? null : {
read: privileges['+r'] || privileges.moderator || privileges.admin,
write: privileges['+w'] || privileges.moderator || privileges.admin,
editable: privileges.moderator || privileges.admin,
view_deleted: privileges.moderator || privileges.admin
});
});
};
module.exports = CategoryTools;

@ -108,8 +108,6 @@
};
Feed.updateRecent = function(callback) {
console.log('entered');
if (process.env.NODE_ENV === 'development') winston.info('[rss] Updating Recent Posts RSS feed');
topics.getLatestTopics(0, 0, 19, undefined, function (err, recentData) {
var feed = new rss({
title: 'Recently Active Topics',

@ -36,9 +36,7 @@ var RDB = require('./redis'),
function getThreadPrivileges(next) {
posts.getPostField(pid, 'tid', function(err, tid) {
threadTools.privileges(tid, uid, function(privileges) {
next(null, privileges);
});
threadTools.privileges(tid, uid, next);
});
}

@ -1,19 +1,20 @@
var RDB = require('./redis.js'),
utils = require('./../public/src/utils.js'),
user = require('./user.js'),
topics = require('./topics.js'),
categories = require('./categories.js'),
favourites = require('./favourites.js'),
threadTools = require('./threadTools.js'),
var RDB = require('./redis'),
utils = require('./../public/src/utils'),
user = require('./user'),
topics = require('./topics'),
categories = require('./categories'),
favourites = require('./favourites'),
threadTools = require('./threadTools'),
postTools = require('./postTools'),
categories = require('./categories'),
feed = require('./feed.js'),
async = require('async'),
feed = require('./feed'),
plugins = require('./plugins'),
meta = require('./meta'),
async = require('async'),
reds = require('reds'),
postSearch = reds.createSearch('nodebbpostsearch'),
nconf = require('nconf'),
meta = require('./meta.js'),
validator = require('validator'),
winston = require('winston');
@ -125,13 +126,15 @@ var RDB = require('./redis.js'),
};
Posts.reply = function(tid, uid, content, callback) {
threadTools.privileges(tid, uid, function(err, privileges) {
if (content) {
content = content.trim();
}
if (!content || content.length < meta.config.minimumPostLength) {
callback(new Error('content-too-short'), null);
return;
return callback(new Error('content-too-short'));
} else if (!privileges.write) {
return callback(new Error('no-privileges'));
}
Posts.create(uid, tid, content, function(err, postData) {
@ -181,6 +184,7 @@ var RDB = require('./redis.js'),
callback(null, postData);
});
});
});
}
Posts.getPostsByTid = function(tid, start, end, callback) {

@ -130,7 +130,7 @@ var user = require('./../user.js'),
var uid = (req.user) ? req.user.uid : 0;
// Category Whitelisting (support for "-r" to come later)
var whitelistReadKey = 'cid:' + req.params.id + ':permissions:+r',
var whitelistReadKey = 'cid:' + req.params.id + ':privileges:+r',
success = function() {
categories.getCategoryById(req.params.id, uid, function (err, data) {
if (!err && data && data.disabled === "0")

@ -55,15 +55,6 @@ var DebugRoute = function(app) {
});
});
app.get('/prune', function(req, res) {
var Notifications = require('../notifications');
Notifications.prune(new Date(), function() {
console.log('done');
});
res.send();
});
app.get('/uuidtest', function(req, res) {
var Utils = require('../../public/src/utils.js');

@ -1,16 +1,18 @@
var RDB = require('./redis.js'),
topics = require('./topics.js'),
categories = require('./categories.js'),
user = require('./user.js'),
var RDB = require('./redis'),
topics = require('./topics'),
categories = require('./categories'),
CategoryTools = require('./categoryTools'),
user = require('./user'),
async = require('async'),
notifications = require('./notifications.js'),
notifications = require('./notifications'),
posts = require('./posts'),
meta = require('./meta'),
websockets = require('./websockets');
reds = require('reds'),
topicSearch = reds.createSearch('nodebbtopicsearch'),
winston = require('winston'),
meta = require('./meta'),
nconf = require('nconf'),
websockets = require('./websockets');
(function(ThreadTools) {
@ -22,28 +24,24 @@ var RDB = require('./redis.js'),
}
ThreadTools.privileges = function(tid, uid, callback) {
//todo: break early if one condition is true
function getCategoryPrivileges(next) {
async.parallel({
categoryPrivs: function(next) {
topics.getTopicField(tid, 'cid', function(err, cid) {
categories.privileges(cid, uid, function(privileges) {
next(null, privileges);
});
CategoryTools.privileges(cid, uid, next);
});
}
function hasEnoughRep(next) {
},
hasEnoughRep: function(next) {
user.getUserField(uid, 'reputation', function(err, reputation) {
if (err) return next(null, false);
next(null, parseInt(reputation, 10) >= parseInt(meta.config['privileges:manage_topic'], 10));
});
}
async.parallel([getCategoryPrivileges, hasEnoughRep], function(err, results) {
callback({
editable: results[0].editable || results[1],
view_deleted: results[0].view_deleted || results[1]
}, function(err, results) {
callback(err, !results ? undefined : {
read: results.categoryPrivs.read,
write: results.categoryPrivs.write,
editable: results.categoryPrivs.editable || results.hasEnoughRep,
view_deleted: results.categoryPrivs.view_deleted || results.hasEnoughRep
});
});
}

@ -2,16 +2,17 @@ var RDB = require('./redis'),
posts = require('./posts'),
utils = require('./../public/src/utils'),
user = require('./user'),
Groups = require('./groups')
categories = require('./categories'),
CategoryTools = require('./categoryTools'),
posts = require('./posts'),
threadTools = require('./threadTools'),
postTools = require('./postTools'),
notifications = require('./notifications'),
async = require('async'),
feed = require('./feed'),
favourites = require('./favourites'),
meta = require('./meta'),
async = require('async'),
reds = require('reds'),
topicSearch = reds.createSearch('nodebbtopicsearch'),
nconf = require('nconf'),
@ -20,6 +21,8 @@ var RDB = require('./redis'),
(function(Topics) {
Topics.post = function(uid, title, content, category_id, callback) {
CategoryTools.privileges(category_id, uid, function(err, privileges) {
if (privileges.write) {
if (!category_id)
throw new Error('Attempted to post without a category_id');
@ -113,6 +116,10 @@ var RDB = require('./redis'),
});
});
});
} else {
callback(new Error('no-privileges'));
}
});
};
Topics.getTopicData = function(tid, callback) {
@ -403,7 +410,7 @@ var RDB = require('./redis'),
// temporary. I don't think this call should belong here
function getPrivileges(next) {
categories.privileges(category_id, current_user, function(user_privs) {
CategoryTools.privileges(category_id, current_user, function(user_privs) {
next(null, user_privs);
});
}
@ -486,27 +493,25 @@ var RDB = require('./redis'),
function getTopicData(next) {
Topics.getTopicData(tid, next);
}
};
function getTopicPosts(next) {
Topics.getTopicPosts(tid, start, end, current_user, function(topicPosts, privileges) {
Topics.getTopicPosts(tid, start, end, current_user, function(topicPosts) {
next(null, topicPosts);
});
}
};
function getPrivileges(next) {
threadTools.privileges(tid, current_user, function(privData) {
next(null, privData);
});
}
threadTools.privileges(tid, current_user, next);
};
function getCategoryData(next) {
Topics.getCategoryData(tid, next);
}
};
async.parallel([getTopicData, getTopicPosts, getPrivileges, getCategoryData], function(err, results) {
if (err) {
console.log(err.message);
winston.error('[Topics.getTopicWithPosts] Could not retrieve topic data: ', err.message);
callback(err, null);
return;
}

@ -723,14 +723,14 @@ var bcrypt = require('bcrypt'),
User.isModerator = function(uid, cid, callback) {
RDB.sismember('cid:' + cid + ':moderators', uid, function(err, exists) {
RDB.handle(err);
callback( !! exists);
callback(err, !! exists);
});
};
User.isAdministrator = function(uid, callback) {
Groups.getGidFromName('Administrators', function(err, gid) {
Groups.isMember(uid, gid, function(err, isAdmin) {
callback( !! isAdmin);
callback(err, !! isAdmin);
});
});
};

@ -364,6 +364,13 @@ module.exports.init = function(io) {
posts.emitContentTooShortAlert(socket);
} else if (err.message === 'too-many-posts') {
posts.emitTooManyPostsAlert(socket);
} else if (err.message === 'no-privileges') {
socket.emit('event:alert', {
title: 'Unable to post',
message: 'You do not have posting privileges in this category.',
type: 'danger',
timeout: 7500
});
} else {
socket.emit('event:alert', {
title: 'Error',
@ -423,7 +430,6 @@ module.exports.init = function(io) {
posts.reply(data.topic_id, uid, data.content, function(err, postData) {
if(err) {
if (err.message === 'content-too-short') {
posts.emitContentTooShortAlert(socket);
} else if (err.message === 'too-many-posts') {
@ -435,6 +441,13 @@ module.exports.init = function(io) {
type: 'warning',
timeout: 2000
});
} else if (err.message === 'no-privileges') {
socket.emit('event:alert', {
title: 'Unable to post',
message: 'You do not have posting privileges in this category.',
type: 'danger',
timeout: 7500
});
}
return;
}
@ -495,8 +508,8 @@ module.exports.init = function(io) {
});
socket.on('api:topic.delete', function(data) {
threadTools.privileges(data.tid, uid, function(privileges) {
if (privileges.editable) {
threadTools.privileges(data.tid, uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.delete(data.tid, function(err) {
if (!err) {
emitTopicPostStats();
@ -511,8 +524,8 @@ module.exports.init = function(io) {
});
socket.on('api:topic.restore', function(data) {
threadTools.privileges(data.tid, uid, function(privileges) {
if (privileges.editable) {
threadTools.privileges(data.tid, uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.restore(data.tid, socket, function(err) {
emitTopicPostStats();
@ -526,32 +539,32 @@ module.exports.init = function(io) {
});
socket.on('api:topic.lock', function(data) {
threadTools.privileges(data.tid, uid, function(privileges) {
if (privileges.editable) {
threadTools.privileges(data.tid, uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.lock(data.tid, socket);
}
});
});
socket.on('api:topic.unlock', function(data) {
threadTools.privileges(data.tid, uid, function(privileges) {
if (privileges.editable) {
threadTools.privileges(data.tid, uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.unlock(data.tid, socket);
}
});
});
socket.on('api:topic.pin', function(data) {
threadTools.privileges(data.tid, uid, function(privileges) {
if (privileges.editable) {
threadTools.privileges(data.tid, uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.pin(data.tid, socket);
}
});
});
socket.on('api:topic.unpin', function(data) {
threadTools.privileges(data.tid, uid, function(privileges) {
if (privileges.editable) {
threadTools.privileges(data.tid, uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.unpin(data.tid, socket);
}
});

Loading…
Cancel
Save