refactored the entire privileges stack. .editable() is now deprecated, use

.privileges instead. Privileges now are inherited, so querying a topic's
privileges will automatically query it's parent category's privileges as
well, etc.
v1.18.x
Julian Lam 12 years ago
parent 3e8d664e71
commit e62fcc5831

@ -164,6 +164,10 @@ footer.footer {
margin-bottom: 10px; margin-bottom: 10px;
padding-bottom: 10px; padding-bottom: 10px;
&.deleted {
-moz-opacity: 0.30;
opacity: 0.30;
}
} }
&:last-child li { &:last-child li {

@ -10,7 +10,7 @@
<div class="span9"> <div class="span9">
<ul id="topics-container"> <ul id="topics-container">
<!-- BEGIN topics --> <!-- BEGIN topics -->
<a href="../../topic/{topics.slug}"><li> <a href="../../topic/{topics.slug}"><li class="{topics.deleted-class}">
<div class="row-fluid"> <div class="row-fluid">
<div class="span1 thread-rating hidden-phone hidden-tablet"> <div class="span1 thread-rating hidden-phone hidden-tablet">
<span> <span>

@ -1,7 +1,8 @@
var RDB = require('./redis.js'), var RDB = require('./redis.js'),
posts = require('./posts.js'), posts = require('./posts.js'),
utils = require('./utils.js'), utils = require('./utils.js'),
user = require('./user.js'); user = require('./user.js'),
async = require('async');
(function(Categories) { (function(Categories) {
@ -27,6 +28,30 @@ var RDB = require('./redis.js'),
}); });
}; };
Categories.privileges = function(cid, uid, callback) {
async.parallel([
// function(next) {
// user.getUserField(uid, 'reputation', function(reputation) {
// next(null, reputation >= config.privilege_thresholds.manage_category);
// });
// },
function(next) {
user.isModerator(uid, cid, function(isMod) {
next(null, isMod);
});
}, function(next) {
user.isAdministrator(uid, function(isAdmin) {
next(null, isAdmin);
});
}
], function(err, results) {
callback({
editable: results.indexOf(true) !== -1 ? true : false,
view_deleted: results.indexOf(true) !== -1 ? true : false
});
});
}
Categories.edit = function(data, callback) { Categories.edit = function(data, callback) {
// just a reminder to self that name + slugs are stored into topics data as well. // just a reminder to self that name + slugs are stored into topics data as well.
}; };

@ -13,34 +13,28 @@ marked.setOptions({
(function(Posts) { (function(Posts) {
Posts.get = function(callback, tid, current_user, start, end) { Posts.get = function(callback, tid, current_user, start, end) {
if (start == null) start = 0; if (start == null) start = 0;
if (end == null) end = -1;//start + 10; if (end == null) end = -1;//start + 10;
var post_data, user_data, thread_data, vote_data, viewer_data; var post_data, user_data, thread_data, vote_data, privileges;
getTopicPosts(); getTopicPosts();
getViewerData(); getPrivileges();
//compile thread after all data is asynchronously called //compile thread after all data is asynchronously called
function generateThread() { function generateThread() {
if (!post_data || !user_data || !thread_data || !vote_data || !viewer_data) return; if (!post_data || !user_data || !thread_data || !vote_data || !privileges) return;
var posts = [], var posts = [],
main_posts = [], main_posts = [];
manage_content = (
viewer_data.reputation >= config.privilege_thresholds.manage_content ||
viewer_data.isModerator ||
viewer_data.isAdministrator
);
for (var i=0, ii= post_data.pid.length; i<ii; i++) { for (var i=0, ii= post_data.pid.length; i<ii; i++) {
var uid = post_data.uid[i], var uid = post_data.uid[i],
pid = post_data.pid[i]; pid = post_data.pid[i];
if (post_data.deleted[i] === null || (post_data.deleted[i] === '1' && manage_content) || current_user === uid) { if (post_data.deleted[i] === null || (post_data.deleted[i] === '1' && privileges.view_deleted) || current_user === uid) {
var post_obj = { var post_obj = {
'pid' : pid, 'pid' : pid,
'uid' : uid, 'uid' : uid,
@ -53,7 +47,7 @@ marked.setOptions({
'gravatar' : user_data[uid].picture || 'http://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e', 'gravatar' : user_data[uid].picture || 'http://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e',
'signature' : user_data[uid].signature, 'signature' : user_data[uid].signature,
'fav_star_class' : vote_data[pid] ? 'icon-star' : 'icon-star-empty', 'fav_star_class' : vote_data[pid] ? 'icon-star' : 'icon-star-empty',
'display_moderator_tools': (uid == current_user || manage_content || viewer_data.isModerator) ? 'show' : 'none', 'display_moderator_tools': (uid == current_user || privileges.editable) ? 'show' : 'none',
'edited-class': post_data.editor[i] !== null ? '' : 'none', 'edited-class': post_data.editor[i] !== null ? '' : 'none',
'editor': post_data.editor[i] !== null ? user_data[post_data.editor[i]].username : '', 'editor': post_data.editor[i] !== null ? user_data[post_data.editor[i]].username : '',
'relativeEditTime': post_data.editTime !== null ? utils.relativeTime(post_data.editTime[i]) : '', 'relativeEditTime': post_data.editTime !== null ? utils.relativeTime(post_data.editTime[i]) : '',
@ -73,7 +67,7 @@ marked.setOptions({
'deleted': parseInt(thread_data.deleted) || 0, 'deleted': parseInt(thread_data.deleted) || 0,
'pinned': parseInt(thread_data.pinned) || 0, 'pinned': parseInt(thread_data.pinned) || 0,
'topic_id': tid, 'topic_id': tid,
'expose_tools': manage_content ? 1 : 0, 'expose_tools': privileges.editable ? 1 : 0,
'posts': posts, 'posts': posts,
'main_posts': main_posts 'main_posts': main_posts
}); });
@ -159,40 +153,23 @@ marked.setOptions({
}); });
} }
function getViewerData() { function getPrivileges() {
async.parallel([ topics.privileges(tid, current_user, function(user_privs) {
function(callback) { privileges = user_privs;
user.getUserField(current_user, 'reputation', function(reputation){
viewer_data = viewer_data || {};
viewer_data.reputation = reputation;
callback(null);
});
},
function(callback) {
RDB.get('tid:' + tid + ':cid', function(err, cid) {
user.isModerator(current_user, cid, function(isMod) {
viewer_data = viewer_data || {};
viewer_data.isModerator = isMod;
callback(null);
});
})
},
function(callback) {
user.isAdministrator(current_user, function(isAdmin) {
viewer_data = viewer_data || {};
viewer_data.isAdministrator = isAdmin;
callback(null);
});
}
], function(err) {
generateThread(); generateThread();
}); });
} }
} }
Posts.editable = function(uid, pid, callback) { Posts.privileges = function(pid, uid, callback) {
async.parallel([ async.parallel([
function(next) {
Posts.get_tid_by_pid(pid, function(tid) {
topics.privileges(tid, uid, function(privileges) {
next(null, privileges);
});
});
},
function(next) { function(next) {
RDB.get('pid:' + pid + ':uid', function(err, author) { RDB.get('pid:' + pid + ':uid', function(err, author) {
if (author && parseInt(author) > 0) next(null, author === uid); if (author && parseInt(author) > 0) next(null, author === uid);
@ -202,23 +179,12 @@ marked.setOptions({
user.getUserField(uid, 'reputation', function(reputation) { user.getUserField(uid, 'reputation', function(reputation) {
next(null, reputation >= config.privilege_thresholds.manage_content); next(null, reputation >= config.privilege_thresholds.manage_content);
}); });
},
function(next) {
Posts.get_tid_by_pid(pid, function(tid) {
RDB.get('tid:' + tid + ':cid', function(err, cid) {
user.isModerator(uid, cid, function(isMod) {
next(null, isMod);
});
});
});
}, function(next) {
user.isAdministrator(uid, function(isAdmin) {
next(null, isAdmin);
});
} }
], function(err, results) { ], function(err, results) {
// If any return true, allow the edit callback({
if (results.indexOf(true) !== -1) callback(true); editable: results[0].editable || (results.slice(1).indexOf(true) !== -1 ? true : false),
view_deleted: results[0].view_deleted || (results.slice(1).indexOf(true) !== -1 ? true : false)
});
}); });
} }
@ -462,8 +428,8 @@ marked.setOptions({
}); });
}; };
Posts.editable(uid, pid, function(editable) { Posts.privileges(pid, uid, function(privileges) {
if (editable) success(); if (privileges.editable) success();
}); });
} }
@ -476,8 +442,8 @@ marked.setOptions({
}); });
}; };
Posts.editable(uid, pid, function(editable) { Posts.privileges(pid, uid, function(privileges) {
if (editable) success(); if (privileges.editable) success();
}); });
} }
@ -490,8 +456,8 @@ marked.setOptions({
}); });
}; };
Posts.editable(uid, pid, function(editable) { Posts.privileges(pid, uid, function(privileges) {
if (editable) success(); if (privileges.editable) success();
}); });
} }
}(exports)); }(exports));

@ -87,13 +87,15 @@ marked.setOptions({
var usernames, var usernames,
has_read, has_read,
moderators, moderators,
teaser_info; teaser_info,
privileges;
function generate_topic() { function generate_topic() {
if (!usernames || !has_read || !moderators || !teaser_info) return; if (!usernames || !has_read || !moderators || !teaser_info || !privileges) return;
if (tids.length > 0) { if (tids.length > 0) {
for (var i=0, ii=title.length; i<ii; i++) { for (var i=0, ii=title.length; i<ii; i++) {
if (!deleted[i] || (deleted[i] && privileges.view_deleted) || uid[i] === current_user) {
topics.push({ topics.push({
'title' : title[i], 'title' : title[i],
'uid' : uid[i], 'uid' : uid[i],
@ -104,6 +106,7 @@ marked.setOptions({
'post_count' : postcount[i], 'post_count' : postcount[i],
'lock-icon': locked[i] === '1' ? 'icon-lock' : 'none', 'lock-icon': locked[i] === '1' ? 'icon-lock' : 'none',
'deleted': deleted[i], 'deleted': deleted[i],
'deleted-class': deleted[i] ? 'deleted' : '',
'pinned': parseInt(pinned[i] || 0), // For sorting purposes 'pinned': parseInt(pinned[i] || 0), // For sorting purposes
'pin-icon': pinned[i] === '1' ? 'icon-pushpin' : 'none', 'pin-icon': pinned[i] === '1' ? 'icon-pushpin' : 'none',
'badgeclass' : (has_read[i] && current_user !=0) ? '' : 'badge-important', 'badgeclass' : (has_read[i] && current_user !=0) ? '' : 'badge-important',
@ -112,6 +115,7 @@ marked.setOptions({
}); });
} }
} }
}
// Float pinned topics to the top // Float pinned topics to the top
topics = topics.sort(function(a, b) { topics = topics.sort(function(a, b) {
@ -157,39 +161,33 @@ marked.setOptions({
teaser_info = teasers; teaser_info = teasers;
generate_topic(); generate_topic();
}); });
// else {
// callback({ categories.privileges(category_id, current_user, function(user_privs) {
// 'category_name' : category_id ? category_name : 'Recent', privileges = user_privs;
// 'show_topic_button' : category_id ? 'show' : 'hidden', });
// 'category_id': category_id || 0,
// 'topics': []
// });
// }
}); });
}); });
} }
Topics.editable = function(tid, uid, callback) { Topics.privileges = function(tid, uid, callback) {
async.parallel([ async.parallel([
function(next) {
user.getUserField(uid, 'reputation', function(reputation) {
next(null, reputation >= config.privilege_thresholds.manage_thread);
});
},
function(next) { function(next) {
Topics.get_cid_by_tid(tid, function(cid) { Topics.get_cid_by_tid(tid, function(cid) {
user.isModerator(uid, cid, function(isMod) { categories.privileges(cid, uid, function(privileges) {
next(null, isMod); next(null, privileges);
}); });
}); });
}, function(next) { },
user.isAdministrator(uid, function(isAdmin) { function(next) {
next(null, isAdmin); user.getUserField(uid, 'reputation', function(reputation) {
next(null, reputation >= config.privilege_thresholds.manage_thread);
}); });
} }
], function(err, results) { ], function(err, results) {
// If any return true, allow the edit callback({
if (results.indexOf(true) !== -1) callback(true); editable: results[0].editable || (results.slice(1).indexOf(true) !== -1 ? true : false),
view_deleted: results[0].view_deleted || (results.slice(1).indexOf(true) !== -1 ? true : false)
});
}); });
} }
@ -383,8 +381,8 @@ marked.setOptions({
}; };
Topics.lock = function(tid, uid, socket) { Topics.lock = function(tid, uid, socket) {
Topics.editable(tid, uid, function(editable) { Topics.privileges(tid, uid, function(privileges) {
if (editable) { if (privileges.editable) {
// Mark thread as locked // Mark thread as locked
RDB.set('tid:' + tid + ':locked', 1); RDB.set('tid:' + tid + ':locked', 1);
@ -399,8 +397,8 @@ marked.setOptions({
} }
Topics.unlock = function(tid, uid, socket) { Topics.unlock = function(tid, uid, socket) {
Topics.editable(tid, uid, function(editable) { Topics.privileges(tid, uid, function(privileges) {
if (editable) { if (privileges.editable) {
// Mark thread as unlocked // Mark thread as unlocked
RDB.del('tid:' + tid + ':locked'); RDB.del('tid:' + tid + ':locked');
@ -415,8 +413,8 @@ marked.setOptions({
} }
Topics.delete = function(tid, uid, socket) { Topics.delete = function(tid, uid, socket) {
Topics.editable(tid, uid, function(editable) { Topics.privileges(tid, uid, function(privileges) {
if (editable) { if (privileges.editable) {
// Mark thread as deleted // Mark thread as deleted
RDB.set('tid:' + tid + ':deleted', 1); RDB.set('tid:' + tid + ':deleted', 1);
Topics.lock(tid, uid); Topics.lock(tid, uid);
@ -432,8 +430,8 @@ marked.setOptions({
} }
Topics.restore = function(tid, uid, socket) { Topics.restore = function(tid, uid, socket) {
Topics.editable(tid, uid, function(editable) { Topics.privileges(tid, uid, function(privileges) {
if (editable) { if (privileges.editable) {
// Mark thread as restored // Mark thread as restored
RDB.del('tid:' + tid + ':deleted'); RDB.del('tid:' + tid + ':deleted');
Topics.unlock(tid, uid); Topics.unlock(tid, uid);
@ -449,8 +447,8 @@ marked.setOptions({
} }
Topics.pin = function(tid, uid, socket) { Topics.pin = function(tid, uid, socket) {
Topics.editable(tid, uid, function(editable) { Topics.privileges(tid, uid, function(privileges) {
if (editable) { if (privileges.editable) {
// Mark thread as pinned // Mark thread as pinned
RDB.set('tid:' + tid + ':pinned', 1); RDB.set('tid:' + tid + ':pinned', 1);
@ -465,8 +463,8 @@ marked.setOptions({
} }
Topics.unpin = function(tid, uid, socket) { Topics.unpin = function(tid, uid, socket) {
Topics.editable(tid, uid, function(editable) { Topics.privileges(tid, uid, function(privileges) {
if (editable) { if (privileges.editable) {
// Mark thread as unpinned // Mark thread as unpinned
RDB.del('tid:' + tid + ':pinned'); RDB.del('tid:' + tid + ':pinned');

Loading…
Cancel
Save