mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 19:15:58 +01:00 
			
		
		
		
	closes #6020
This commit is contained in:
		| @@ -14,31 +14,51 @@ var postQueueController = module.exports; | ||||
| postQueueController.get = function (req, res, next) { | ||||
| 	var page = parseInt(req.query.page, 10) || 1; | ||||
| 	var postsPerPage = 20; | ||||
| 	var pageCount = 0; | ||||
|  | ||||
| 	var start = (page - 1) * postsPerPage; | ||||
| 	var stop = start + postsPerPage - 1; | ||||
|  | ||||
| 	var postData; | ||||
|  | ||||
| 	var results; | ||||
| 	async.waterfall([ | ||||
| 		function (next) { | ||||
| 			async.parallel({ | ||||
| 				count: function (next) { | ||||
| 					db.sortedSetCard('post:queue', next); | ||||
| 				}, | ||||
| 				ids: function (next) { | ||||
| 					db.getSortedSetRange('post:queue', start, stop, next); | ||||
| 					db.getSortedSetRange('post:queue', 0, -1, next); | ||||
| 				}, | ||||
| 				isAdminOrGlobalMod: function (next) { | ||||
| 					user.isAdminOrGlobalMod(req.uid, next); | ||||
| 				}, | ||||
| 				moderatedCids: function (next) { | ||||
| 					user.getModeratedCids(req.uid, next); | ||||
| 				}, | ||||
| 			}, next); | ||||
| 		}, | ||||
| 		function (results, next) { | ||||
| 			pageCount = Math.ceil(results.count / postsPerPage); | ||||
|  | ||||
| 			var keys = results.ids.map(function (id) { | ||||
| 				return 'post:queue:' + id; | ||||
| 		function (_results, next) { | ||||
| 			results = _results; | ||||
| 			getQueuedPosts(results.ids, next); | ||||
| 		}, | ||||
| 		function (postData) { | ||||
| 			postData = postData.filter(function (postData) { | ||||
| 				return postData && (results.isAdminOrGlobalMod || results.moderatedCids.includes(String(postData.category.cid))); | ||||
| 			}); | ||||
|  | ||||
| 			var pageCount = Math.max(1, Math.ceil(postData.length / postsPerPage)); | ||||
| 			var start = (page - 1) * postsPerPage; | ||||
| 			var stop = start + postsPerPage - 1; | ||||
| 			postData = postData.slice(start, stop + 1); | ||||
|  | ||||
| 			res.render('admin/manage/post-queue', { | ||||
| 				title: '[[pages:post-queue]]', | ||||
| 				posts: postData, | ||||
| 				pagination: pagination.create(page, pageCount), | ||||
| 			}); | ||||
| 		}, | ||||
| 	], next); | ||||
| }; | ||||
|  | ||||
| function getQueuedPosts(ids, callback) { | ||||
| 	var keys = ids.map(function (id) { | ||||
| 		return 'post:queue:' + id; | ||||
| 	}); | ||||
| 	var postData; | ||||
| 	async.waterfall([ | ||||
| 		function (next) { | ||||
| 			db.getObjects(keys, next); | ||||
| 		}, | ||||
| 		function (data, next) { | ||||
| @@ -80,12 +100,5 @@ postQueueController.get = function (req, res, next) { | ||||
| 				], next); | ||||
| 			}, next); | ||||
| 		}, | ||||
| 		function (postData) { | ||||
| 			res.render('admin/manage/post-queue', { | ||||
| 				title: '[[pages:post-queue]]', | ||||
| 				posts: postData, | ||||
| 				pagination: pagination.create(page, pageCount), | ||||
| 			}); | ||||
| 		}, | ||||
| 	], next); | ||||
| }; | ||||
| 	], callback); | ||||
| } | ||||
|   | ||||
| @@ -4,7 +4,6 @@ var async = require('async'); | ||||
|  | ||||
| var user = require('../user'); | ||||
| var adminBlacklistController = require('./admin/blacklist'); | ||||
| var adminPostQueueController = require('./admin/postqueue'); | ||||
|  | ||||
| var globalModsController = module.exports; | ||||
|  | ||||
| @@ -21,17 +20,3 @@ globalModsController.ipBlacklist = function (req, res, next) { | ||||
| 		}, | ||||
| 	], next); | ||||
| }; | ||||
|  | ||||
| globalModsController.postQueue = function (req, res, next) { | ||||
| 	async.waterfall([ | ||||
| 		function (next) { | ||||
| 			user.isAdminOrGlobalMod(req.uid, next); | ||||
| 		}, | ||||
| 		function (isAdminOrGlobalMod, next) { | ||||
| 			if (!isAdminOrGlobalMod) { | ||||
| 				return next(); | ||||
| 			} | ||||
| 			adminPostQueueController.get(req, res, next); | ||||
| 		}, | ||||
| 	], next); | ||||
| }; | ||||
|   | ||||
| @@ -7,6 +7,7 @@ var categories = require('../categories'); | ||||
| var flags = require('../flags'); | ||||
| var analytics = require('../analytics'); | ||||
| var plugins = require('../plugins'); | ||||
| var adminPostQueueController = require('./admin/postqueue'); | ||||
|  | ||||
| var modsController = module.exports; | ||||
| modsController.flags = {}; | ||||
| @@ -136,3 +137,18 @@ modsController.flags.detail = function (req, res, next) { | ||||
| 		})); | ||||
| 	}); | ||||
| }; | ||||
|  | ||||
| modsController.postQueue = function (req, res, next) { | ||||
| 	async.waterfall([ | ||||
| 		function (next) { | ||||
| 			user.isPrivileged(req.uid, next); | ||||
| 		}, | ||||
| 		function (isPrivileged, next) { | ||||
| 			if (!isPrivileged) { | ||||
| 				return next(); | ||||
| 			} | ||||
| 			adminPostQueueController.get(req, res, next); | ||||
| 		}, | ||||
| 	], next); | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -128,18 +128,12 @@ module.exports = function (Posts) { | ||||
| 	Posts.submitFromQueue = function (id, callback) { | ||||
| 		async.waterfall([ | ||||
| 			function (next) { | ||||
| 				db.getObject('post:queue:' + id, next); | ||||
| 				getParsedObject(id, next); | ||||
| 			}, | ||||
| 			function (data, next) { | ||||
| 				if (!data) { | ||||
| 					return callback(); | ||||
| 				} | ||||
| 				try { | ||||
| 					data.data = JSON.parse(data.data); | ||||
| 				} catch (err) { | ||||
| 					return next(err); | ||||
| 				} | ||||
|  | ||||
| 				if (data.type === 'topic') { | ||||
| 					createTopic(data.data, next); | ||||
| 				} else if (data.type === 'reply') { | ||||
| @@ -152,6 +146,25 @@ module.exports = function (Posts) { | ||||
| 		], callback); | ||||
| 	}; | ||||
|  | ||||
| 	function getParsedObject(id, callback) { | ||||
| 		async.waterfall([ | ||||
| 			function (next) { | ||||
| 				db.getObject('post:queue:' + id, next); | ||||
| 			}, | ||||
| 			function (data, next) { | ||||
| 				if (!data) { | ||||
| 					return callback(); | ||||
| 				} | ||||
| 				try { | ||||
| 					data.data = JSON.parse(data.data); | ||||
| 				} catch (err) { | ||||
| 					return next(err); | ||||
| 				} | ||||
| 				next(null, data); | ||||
| 			}, | ||||
| 		], callback); | ||||
| 	} | ||||
|  | ||||
| 	function createTopic(data, callback) { | ||||
| 		async.waterfall([ | ||||
| 			function (next) { | ||||
| @@ -184,23 +197,52 @@ module.exports = function (Posts) { | ||||
| 	Posts.editQueuedContent = function (uid, id, content, callback) { | ||||
| 		async.waterfall([ | ||||
| 			function (next) { | ||||
| 				user.isAdminOrGlobalMod(uid, next); | ||||
| 				Posts.canEditQueue(uid, id, next); | ||||
| 			}, | ||||
| 			function (isAdminOrGlobalMod, next) { | ||||
| 				if (!isAdminOrGlobalMod) { | ||||
| 			function (canEditQueue, next) { | ||||
| 				if (!canEditQueue) { | ||||
| 					return callback(new Error('[[error:no-privileges]]')); | ||||
| 				} | ||||
| 				db.getObject('post:queue:' + id, next); | ||||
| 				getParsedObject(id, next); | ||||
| 			}, | ||||
| 			function (data, next) { | ||||
| 				try { | ||||
| 					data.data = JSON.parse(data.data); | ||||
| 				} catch (err) { | ||||
| 					return next(err); | ||||
| 				if (!data) { | ||||
| 					return callback(); | ||||
| 				} | ||||
| 				data.data.content = content; | ||||
| 				db.setObjectField('post:queue:' + id, 'data', JSON.stringify(data.data), next); | ||||
| 			}, | ||||
| 		], callback); | ||||
| 	}; | ||||
|  | ||||
| 	Posts.canEditQueue = function (uid, id, callback) { | ||||
| 		async.waterfall([ | ||||
| 			function (next) { | ||||
| 				async.parallel({ | ||||
| 					isAdminOrGlobalMod: function (next) { | ||||
| 						user.isAdminOrGlobalMod(uid, next); | ||||
| 					}, | ||||
| 					data: function (next) { | ||||
| 						getParsedObject(id, next); | ||||
| 					}, | ||||
| 				}, next); | ||||
| 			}, | ||||
| 			function (results, next) { | ||||
| 				if (results.isAdminOrGlobalMod) { | ||||
| 					return callback(null, true); | ||||
| 				} | ||||
| 				if (!results.data) { | ||||
| 					return callback(null, false); | ||||
| 				} | ||||
| 				if (results.data.type === 'topic') { | ||||
| 					next(null, results.data.data.cid); | ||||
| 				} else if (results.data.type === 'reply') { | ||||
| 					topics.getTopicField(results.data.data.tid, 'cid', next); | ||||
| 				} | ||||
| 			}, | ||||
| 			function (cid, next) { | ||||
| 				user.isModerator(uid, cid, next); | ||||
| 			}, | ||||
| 		], callback); | ||||
| 	}; | ||||
| }; | ||||
|   | ||||
| @@ -42,10 +42,10 @@ function mainRoutes(app, middleware, controllers) { | ||||
| function modRoutes(app, middleware, controllers) { | ||||
| 	setupPageRoute(app, '/flags', middleware, [], controllers.mods.flags.list); | ||||
| 	setupPageRoute(app, '/flags/:flagId', middleware, [], controllers.mods.flags.detail); | ||||
| 	setupPageRoute(app, '/post-queue', middleware, [], controllers.mods.postQueue); | ||||
| } | ||||
|  | ||||
| function globalModRoutes(app, middleware, controllers) { | ||||
| 	setupPageRoute(app, '/post-queue', middleware, [], controllers.globalMods.postQueue); | ||||
| 	setupPageRoute(app, '/ip-blacklist', middleware, [], controllers.globalMods.ipBlacklist); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -175,6 +175,7 @@ SocketPosts.accept = function (socket, data, callback) { | ||||
| SocketPosts.reject = function (socket, data, callback) { | ||||
| 	acceptOrReject(posts.removeFromQueue, socket, data, callback); | ||||
| }; | ||||
|  | ||||
| SocketPosts.editQueuedContent = function (socket, data, callback) { | ||||
| 	if (!data || !data.id || !data.content) { | ||||
| 		return callback(new Error('[[error:invalid-data]]')); | ||||
| @@ -185,10 +186,10 @@ SocketPosts.editQueuedContent = function (socket, data, callback) { | ||||
| function acceptOrReject(method, socket, data, callback) { | ||||
| 	async.waterfall([ | ||||
| 		function (next) { | ||||
| 			user.isAdminOrGlobalMod(socket.uid, next); | ||||
| 			posts.canEditQueue(socket.uid, data.id, next); | ||||
| 		}, | ||||
| 		function (isAdminOrGlobalMod, next) { | ||||
| 			if (!isAdminOrGlobalMod) { | ||||
| 		function (canEditQueue, next) { | ||||
| 			if (!canEditQueue) { | ||||
| 				return callback(new Error('[[error:no-privileges]]')); | ||||
| 			} | ||||
|  | ||||
|   | ||||
| @@ -831,7 +831,21 @@ describe('Post\'s', function () { | ||||
| 			}); | ||||
| 		}); | ||||
|  | ||||
| 		it('should accept queued posts submit', function (done) { | ||||
| 		it('should prevent regular users from approving posts', function (done) { | ||||
| 			socketPosts.accept({ uid: uid }, { id: queueId }, function (err) { | ||||
| 				assert.equal(err.message, '[[error:no-privileges]]'); | ||||
| 				done(); | ||||
| 			}); | ||||
| 		}); | ||||
|  | ||||
| 		it('should prevent regular users from approving non existing posts', function (done) { | ||||
| 			socketPosts.accept({ uid: uid }, { id: 123123 }, function (err) { | ||||
| 				assert.equal(err.message, '[[error:no-privileges]]'); | ||||
| 				done(); | ||||
| 			}); | ||||
| 		}); | ||||
|  | ||||
| 		it('should accept queued posts and submit', function (done) { | ||||
| 			var ids; | ||||
| 			async.waterfall([ | ||||
| 				function (next) { | ||||
| @@ -846,12 +860,5 @@ describe('Post\'s', function () { | ||||
| 				}, | ||||
| 			], done); | ||||
| 		}); | ||||
|  | ||||
| 		it('should prevent regular users from approving posts', function (done) { | ||||
| 			socketPosts.accept({ uid: uid }, { id: 1 }, function (err) { | ||||
| 				assert.equal(err.message, '[[error:no-privileges]]'); | ||||
| 				done(); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user