mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 02:55:58 +01:00 
			
		
		
		
	first pass for #1518
this only handles postTools privileges, topic and category will follow
This commit is contained in:
		| @@ -9,6 +9,7 @@ var winston = require('winston'), | |||||||
| 	posts = require('./posts'), | 	posts = require('./posts'), | ||||||
| 	topics = require('./topics'), | 	topics = require('./topics'), | ||||||
| 	threadTools = require('./threadTools'), | 	threadTools = require('./threadTools'), | ||||||
|  | 	privileges = require('./privileges'), | ||||||
| 	user = require('./user'), | 	user = require('./user'), | ||||||
| 	utils = require('../public/src/utils'), | 	utils = require('../public/src/utils'), | ||||||
| 	plugins = require('./plugins'), | 	plugins = require('./plugins'), | ||||||
| @@ -31,47 +32,6 @@ var winston = require('winston'), | |||||||
| 		}); | 		}); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	PostTools.privileges = function(pid, uid, callback) { |  | ||||||
| 		async.parallel({ |  | ||||||
| 			topicPrivs: function(next) { |  | ||||||
| 				posts.getPostField(pid, 'tid', function(err, tid) { |  | ||||||
| 					threadTools.privileges(tid, uid, next); |  | ||||||
| 				}); |  | ||||||
| 			}, |  | ||||||
| 			isOwner: function(next) { |  | ||||||
| 				posts.getPostField(pid, 'uid', function(err, author) { |  | ||||||
| 					next(null, parseInt(author, 10) === parseInt(uid, 10)); |  | ||||||
| 				}); |  | ||||||
| 			}, |  | ||||||
| 			hasEnoughRep: function(next) { |  | ||||||
| 				if (parseInt(meta.config['privileges:disabled'], 10)) { |  | ||||||
| 					return next(null, false); |  | ||||||
| 				} else { |  | ||||||
| 					user.getUserField(uid, 'reputation', function(err, reputation) { |  | ||||||
| 						if (err) { |  | ||||||
| 							return next(null, false); |  | ||||||
| 						} |  | ||||||
| 						next(null, parseInt(reputation, 10) >= parseInt(meta.config['privileges:manage_content'], 10)); |  | ||||||
| 					}); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		}, function(err, results) { |  | ||||||
| 			if(err) { |  | ||||||
| 				return callback(err); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			callback(null, { |  | ||||||
| 				meta: { |  | ||||||
| 					read: results.topicPrivs.meta.read, |  | ||||||
| 					editable: results.topicPrivs.meta.editable || results.isOwner || results.hasEnoughRep, |  | ||||||
| 					view_deleted: results.topicPrivs.meta.view_deleted || results.isOwner || results.hasEnoughRep, |  | ||||||
| 					move: results.topicPrivs.admin || results.topicPrivs.mods |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	PostTools.edit = function(uid, pid, title, content, options, callback) { | 	PostTools.edit = function(uid, pid, title, content, options, callback) { | ||||||
| 		options = options || {}; | 		options = options || {}; | ||||||
|  |  | ||||||
| @@ -120,8 +80,8 @@ var winston = require('winston'), | |||||||
| 			}, callback); | 			}, callback); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		PostTools.privileges(pid, uid, function(err, privileges) { | 		privileges.posts.canEdit(pid, uid, function(err, canEdit) { | ||||||
| 			if (err || !privileges.meta.editable) { | 			if (err || !canEdit) { | ||||||
| 				return callback(err || new Error('[[error:no-privileges]]')); | 				return callback(err || new Error('[[error:no-privileges]]')); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| @@ -161,10 +121,11 @@ var winston = require('winston'), | |||||||
| 				} else if(parseInt(deleted, 10) !== 1 && !isDelete) { | 				} else if(parseInt(deleted, 10) !== 1 && !isDelete) { | ||||||
| 					return next(new Error('[[error:post-already-restored]]')); | 					return next(new Error('[[error:post-already-restored]]')); | ||||||
| 				} | 				} | ||||||
| 				PostTools.privileges(pid, uid, next); |  | ||||||
|  | 				privileges.posts.canEdit(pid, uid, next); | ||||||
| 			}, | 			}, | ||||||
| 			function(privileges, next) { | 			function(canEdit, next) { | ||||||
| 				if (!privileges || !privileges.meta.editable) { | 				if (!canEdit) { | ||||||
| 					return next(new Error('[[error:no-privileges]]')); | 					return next(new Error('[[error:no-privileges]]')); | ||||||
| 				} | 				} | ||||||
| 				next(); | 				next(); | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								src/posts.js
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/posts.js
									
									
									
									
									
								
							| @@ -6,6 +6,7 @@ var db = require('./database'), | |||||||
| 	topics = require('./topics'), | 	topics = require('./topics'), | ||||||
| 	favourites = require('./favourites'), | 	favourites = require('./favourites'), | ||||||
| 	postTools = require('./postTools'), | 	postTools = require('./postTools'), | ||||||
|  | 	privileges = require('./privileges'), | ||||||
| 	categories = require('./categories'), | 	categories = require('./categories'), | ||||||
| 	plugins = require('./plugins'), | 	plugins = require('./plugins'), | ||||||
| 	meta = require('./meta'), | 	meta = require('./meta'), | ||||||
| @@ -163,8 +164,8 @@ var db = require('./database'), | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			async.filter(pids, function(pid, next) { | 			async.filter(pids, function(pid, next) { | ||||||
| 				postTools.privileges(pid, callerUid, function(err, privileges) { | 				privileges.posts.canRead(pid, callerUid, function(err, canRead) { | ||||||
| 					next(!err && privileges.meta.read); | 					next(!err && canRead); | ||||||
| 				}); | 				}); | ||||||
| 			}, function(pids) { | 			}, function(pids) { | ||||||
| 				if (!(pids && pids.length)) { | 				if (!(pids && pids.length)) { | ||||||
| @@ -215,8 +216,8 @@ var db = require('./database'), | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			async.filter(pids, function(pid, next) { | 			async.filter(pids, function(pid, next) { | ||||||
| 				postTools.privileges(pid, uid, function(err, privileges) { | 				privileges.posts.canRead(pid, uid, function(err, canRead) { | ||||||
| 					next(!err && privileges.meta.read); | 					next(!err && canRead); | ||||||
| 				}); | 				}); | ||||||
| 			}, function(pids) { | 			}, function(pids) { | ||||||
| 				Posts.getPostSummaryByPids(pids, true, callback); | 				Posts.getPostSummaryByPids(pids, true, callback); | ||||||
| @@ -481,4 +482,14 @@ var db = require('./database'), | |||||||
| 		}); | 		}); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  | 	Posts.isOwner = function(pid, uid, callback) { | ||||||
|  | 		Posts.getPostField(pid, 'uid', function(err, author) { | ||||||
|  | 			if (err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  | 			callback(null, parseInt(author, 10) === parseInt(uid, 10)); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  |  | ||||||
| }(exports)); | }(exports)); | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								src/privileges.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/privileges.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  | var privileges = {}; | ||||||
|  |  | ||||||
|  | require('./privileges/posts')(privileges); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | module.exports = privileges; | ||||||
							
								
								
									
										66
									
								
								src/privileges/helpers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/privileges/helpers.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  |  | ||||||
|  | 'use strict'; | ||||||
|  |  | ||||||
|  | var async = require('async'), | ||||||
|  |  | ||||||
|  | 	meta = require('../meta'), | ||||||
|  | 	user = require('../user'), | ||||||
|  | 	groups = require('../groups'), | ||||||
|  | 	categories = require('../categories'); | ||||||
|  |  | ||||||
|  | var helpers = {}; | ||||||
|  |  | ||||||
|  | helpers.allowedTo = function(privilege, uid, cid, callback) { | ||||||
|  | 	categories.getCategoryField(cid, 'disabled', function(err, disabled) { | ||||||
|  | 		if (err) { | ||||||
|  | 			return callback(err); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (parseInt(disabled, 10) === 1) { | ||||||
|  | 			return callback(null, false); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		async.parallel({ | ||||||
|  | 			hasUserPrivilege: function(next) { | ||||||
|  | 				hasPrivilege(groups.isMember, 'cid:' + cid + ':privileges:' + privilege, uid, next); | ||||||
|  | 			}, | ||||||
|  | 			hasGroupPrivilege: function(next) { | ||||||
|  | 				hasPrivilege(groups.isMemberOfGroupList, 'cid:' + cid + ':privileges:groups:' + privilege, uid, next); | ||||||
|  | 			}, | ||||||
|  | 		}, function(err, results) { | ||||||
|  | 			if (err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  | 			callback(null,  results.hasUserPrivilege && results.hasGroupPrivilege); | ||||||
|  | 		}); | ||||||
|  | 	}); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | function hasPrivilege(method, group, uid, callback) { | ||||||
|  | 	groups.exists(group, function(err, exists) { | ||||||
|  | 		if (err) { | ||||||
|  | 			return callback(err); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (!exists) { | ||||||
|  | 			return callback(null, true); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		method(group, uid, callback); | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | helpers.hasEnoughReputationFor = function(privilege, uid, callback) { | ||||||
|  | 	if (parseInt(meta.config['privileges:disabled'], 10)) { | ||||||
|  | 		return callback(null, false); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	user.getUserField(uid, 'reputation', function(err, reputation) { | ||||||
|  | 		if (err) { | ||||||
|  | 			return callback(null, false); | ||||||
|  | 		} | ||||||
|  | 		callback(null, parseInt(reputation, 10) >= parseInt(meta.config[privilege], 10)); | ||||||
|  | 	}); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | module.exports = helpers; | ||||||
							
								
								
									
										112
									
								
								src/privileges/posts.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/privileges/posts.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | |||||||
|  |  | ||||||
|  | 'use strict'; | ||||||
|  |  | ||||||
|  | var async = require('async'), | ||||||
|  |  | ||||||
|  | 	posts = require('../posts'), | ||||||
|  | 	user = require('../user'), | ||||||
|  | 	helpers = require('./helpers'), | ||||||
|  | 	groups = require('../groups'), | ||||||
|  | 	categories = require('../categories'); | ||||||
|  |  | ||||||
|  | module.exports = function(privileges) { | ||||||
|  |  | ||||||
|  | 	privileges.posts = {}; | ||||||
|  |  | ||||||
|  | 	privileges.posts.get = function(pid, uid, callback) { | ||||||
|  |  | ||||||
|  | 		async.parallel({ | ||||||
|  | 			isOwner: function(next) { | ||||||
|  | 				posts.isOwner(pid, uid, next); | ||||||
|  | 			}, | ||||||
|  | 			manage_content: function(next) { | ||||||
|  | 				helpers.hasEnoughReputationFor('privileges:manage_content', uid, next); | ||||||
|  | 			}, | ||||||
|  | 			manage_topic: function(next) { | ||||||
|  | 				helpers.hasEnoughReputationFor('privileges:manage_topic', uid, next); | ||||||
|  | 			}, | ||||||
|  | 			isAdministrator: function(next) { | ||||||
|  | 				user.isAdministrator(uid, next); | ||||||
|  | 			}, | ||||||
|  | 			isModerator: function(next) { | ||||||
|  | 				posts.getCidByPid(pid, function(err, cid) { | ||||||
|  | 					if (err) { | ||||||
|  | 						return next(err); | ||||||
|  | 					} | ||||||
|  | 					user.isModerator(uid, cid, next); | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 		}, function(err, results) { | ||||||
|  | 			if(err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var editable = results.isAdministrator || results.isModerator || results.manage_content || results.manage_topic || results.isOwner; | ||||||
|  |  | ||||||
|  | 			callback(null, { | ||||||
|  | 				meta: { | ||||||
|  | 					editable: editable, | ||||||
|  | 					view_deleted: editable, | ||||||
|  | 					move: results.isAdministrator || results.isModerator | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	privileges.posts.canRead = function(pid, uid, callback) { | ||||||
|  | 		posts.getCidByPid(pid, function(err, cid) { | ||||||
|  | 			if (err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			async.some([ | ||||||
|  | 				function(next) { | ||||||
|  | 					helpers.allowedTo('read', uid, cid, next); | ||||||
|  | 				}, | ||||||
|  | 				function(next) { | ||||||
|  | 					user.isModerator(uid, cid, next); | ||||||
|  | 				}, | ||||||
|  | 				function(next) { | ||||||
|  | 					user.isAdministrator(uid, next); | ||||||
|  | 				} | ||||||
|  | 			], function(task, next) { | ||||||
|  | 				task(function(err, result) { | ||||||
|  | 					next(!err && result); | ||||||
|  | 				}); | ||||||
|  | 			}, function(result) { | ||||||
|  | 				callback(null, result); | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	privileges.posts.canEdit = function(pid, uid, callback) { | ||||||
|  | 		async.some([ | ||||||
|  | 			function(next) { | ||||||
|  | 				posts.isOwner(pid, uid, next); | ||||||
|  | 			}, | ||||||
|  | 			function(next) { | ||||||
|  | 				helpers.hasEnoughReputationFor('privileges:manage_content', uid, next); | ||||||
|  | 			}, | ||||||
|  | 			function(next) { | ||||||
|  | 				helpers.hasEnoughReputationFor('privileges:manage_topic', uid, next); | ||||||
|  | 			}, | ||||||
|  | 			function(next) { | ||||||
|  | 				posts.getCidByPid(pid, function(err, cid) { | ||||||
|  | 					if (err) { | ||||||
|  | 						return next(err); | ||||||
|  | 					} | ||||||
|  | 					user.isModerator(uid, cid, next); | ||||||
|  | 				}); | ||||||
|  | 			}, | ||||||
|  | 			function(next) { | ||||||
|  | 				user.isAdministrator(uid, next); | ||||||
|  | 			} | ||||||
|  | 		], function(task, next) { | ||||||
|  | 			task(function(err, result) { | ||||||
|  | 				next(!err && result); | ||||||
|  | 			}); | ||||||
|  | 		}, function(result) { | ||||||
|  | 			callback(null, result); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
| @@ -5,6 +5,7 @@ var	async = require('async'), | |||||||
|  |  | ||||||
| 	db = require('../database'), | 	db = require('../database'), | ||||||
| 	posts = require('../posts'), | 	posts = require('../posts'), | ||||||
|  | 	privileges = require('../privileges'), | ||||||
| 	meta = require('../meta'), | 	meta = require('../meta'), | ||||||
| 	topics = require('../topics'), | 	topics = require('../topics'), | ||||||
| 	favourites = require('../favourites'), | 	favourites = require('../favourites'), | ||||||
| @@ -17,7 +18,6 @@ var	async = require('async'), | |||||||
| 	SocketPosts = {}; | 	SocketPosts = {}; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| SocketPosts.reply = function(socket, data, callback) { | SocketPosts.reply = function(socket, data, callback) { | ||||||
|  |  | ||||||
| 	if (!socket.uid && !parseInt(meta.config.allowGuestPosting, 10)) { | 	if (!socket.uid && !parseInt(meta.config.allowGuestPosting, 10)) { | ||||||
| @@ -127,10 +127,10 @@ function sendNotificationToPostOwner(data, uid, notification) { | |||||||
| SocketPosts.getRawPost = function(socket, pid, callback) { | SocketPosts.getRawPost = function(socket, pid, callback) { | ||||||
| 	async.waterfall([ | 	async.waterfall([ | ||||||
| 		function(next) { | 		function(next) { | ||||||
| 			postTools.privileges(pid, socket.uid, next); | 			privileges.posts.canRead(pid, socket.uid, next); | ||||||
| 		}, | 		}, | ||||||
| 		function(privileges, next) { | 		function(canRead, next) { | ||||||
| 			if (!privileges || !privileges.meta.read) { | 			if (!canRead) { | ||||||
| 				return next(new Error('[[error:no-privileges]]')); | 				return next(new Error('[[error:no-privileges]]')); | ||||||
| 			} | 			} | ||||||
| 			posts.getPostFields(pid, ['content', 'deleted'], next); | 			posts.getPostFields(pid, ['content', 'deleted'], next); | ||||||
| @@ -205,7 +205,7 @@ function deleteOrRestore(command, socket, data, callback) { | |||||||
| } | } | ||||||
|  |  | ||||||
| SocketPosts.getPrivileges = function(socket, pid, callback) { | SocketPosts.getPrivileges = function(socket, pid, callback) { | ||||||
| 	postTools.privileges(pid, socket.uid, function(err, privileges) { | 	privileges.posts.get(pid, socket.uid, function(err, privileges) { | ||||||
| 		if(err) { | 		if(err) { | ||||||
| 			return callback(err); | 			return callback(err); | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ var async = require('async'), | |||||||
| 	db = require('./../database'), | 	db = require('./../database'), | ||||||
|  |  | ||||||
| 	posts = require('./../posts'), | 	posts = require('./../posts'), | ||||||
|  | 	privileges = require('../privileges'), | ||||||
| 	postTools = require('./../postTools'), | 	postTools = require('./../postTools'), | ||||||
| 	threadTools = require('./../threadTools'); | 	threadTools = require('./../threadTools'); | ||||||
|  |  | ||||||
| @@ -52,16 +53,12 @@ module.exports = function(Topics) { | |||||||
| 				}); | 				}); | ||||||
|  |  | ||||||
| 				function move(pid, next) { | 				function move(pid, next) { | ||||||
| 					postTools.privileges(pid, uid, function(err, privileges) { | 					privileges.posts.canEdit(pid, uid, function(err, canEdit) { | ||||||
| 						if(err) { | 						if(err || !canEdit) { | ||||||
| 							return next(err); | 							return next(err); | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
| 						if(privileges.meta.editable) { |  | ||||||
| 						Topics.movePostToTopic(pid, tid, next); | 						Topics.movePostToTopic(pid, tid, next); | ||||||
| 						} else { |  | ||||||
| 							next(); |  | ||||||
| 						} |  | ||||||
| 					}); | 					}); | ||||||
| 				} | 				} | ||||||
| 			}); | 			}); | ||||||
|   | |||||||
| @@ -8,9 +8,7 @@ var async = require('async'), | |||||||
| 	emitter = require('./../emitter'), | 	emitter = require('./../emitter'), | ||||||
| 	favourites = require('./../favourites'), | 	favourites = require('./../favourites'), | ||||||
| 	posts = require('./../posts'), | 	posts = require('./../posts'), | ||||||
| 	postTools = require('./../postTools'); | 	privileges = require('../privileges'); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| module.exports = function(Topics) { | module.exports = function(Topics) { | ||||||
|  |  | ||||||
| @@ -52,7 +50,7 @@ module.exports = function(Topics) { | |||||||
| 				}, | 				}, | ||||||
| 				privileges : function(next) { | 				privileges : function(next) { | ||||||
| 					async.map(pids, function (pid, next) { | 					async.map(pids, function (pid, next) { | ||||||
| 						postTools.privileges(pid, uid, next); | 						privileges.posts.get(pid, uid, next); | ||||||
| 					}, next); | 					}, next); | ||||||
| 				} | 				} | ||||||
| 			}, function(err, results) { | 			}, function(err, results) { | ||||||
| @@ -66,7 +64,7 @@ module.exports = function(Topics) { | |||||||
| 					postData[i].upvoted = results.voteData[i].upvoted; | 					postData[i].upvoted = results.voteData[i].upvoted; | ||||||
| 					postData[i].downvoted = results.voteData[i].downvoted; | 					postData[i].downvoted = results.voteData[i].downvoted; | ||||||
| 					postData[i].votes = postData[i].votes || 0; | 					postData[i].votes = postData[i].votes || 0; | ||||||
| 					postData[i].display_moderator_tools = parseInt(uid, 10) !== 0 && results.privileges[i].meta.editable; | 					postData[i].display_moderator_tools = results.privileges[i].meta.editable; | ||||||
| 					postData[i].display_move_tools = results.privileges[i].meta.move; | 					postData[i].display_move_tools = results.privileges[i].meta.move; | ||||||
| 					postData[i].selfPost = parseInt(uid, 10) === parseInt(postData[i].uid, 10); | 					postData[i].selfPost = parseInt(uid, 10) === parseInt(postData[i].uid, 10); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user