mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 02:55:58 +01:00 
			
		
		
		
	closes #4800
This commit is contained in:
		| @@ -57,6 +57,13 @@ | ||||
| 	"post-edit-duration-expired-days": "You are only allowed to edit posts for %1 day(s) after posting", | ||||
| 	"post-edit-duration-expired-days-hours": "You are only allowed to edit posts for %1 day(s) %2 hour(s) after posting", | ||||
|  | ||||
| 	"post-delete-duration-expired": "You are only allowed to delete posts for %1 second(s) after posting", | ||||
| 	"post-delete-duration-expired-minutes": "You are only allowed to delete posts for %1 minute(s) after posting", | ||||
| 	"post-delete-duration-expired-minutes-seconds": "You are only allowed to delete posts for %1 minute(s) %2 second(s) after posting", | ||||
| 	"post-delete-duration-expired-hours": "You are only allowed to delete posts for %1 hour(s) after posting", | ||||
| 	"post-delete-duration-expired-hours-minutes": "You are only allowed to delete posts for %1 hour(s) %2 minute(s) after posting", | ||||
| 	"post-delete-duration-expired-days": "You are only allowed to delete posts for %1 day(s) after posting", | ||||
| 	"post-delete-duration-expired-days-hours": "You are only allowed to delete posts for %1 day(s) %2 hour(s) after posting", | ||||
|  | ||||
| 	"content-too-short": "Please enter a longer post. Posts should contain at least %1 character(s).", | ||||
| 	"content-too-long": "Please enter a shorter post. Posts can't be longer than %1 character(s).", | ||||
|   | ||||
| @@ -171,43 +171,55 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator | ||||
|  | ||||
| 			var timestamp = parseInt(getData(btn, 'data-timestamp'), 10); | ||||
| 			var postEditDuration = parseInt(ajaxify.data.postEditDuration, 10); | ||||
| 			if (!ajaxify.data.privileges.isAdminOrMod && postEditDuration && Date.now() - timestamp > postEditDuration * 1000) { | ||||
| 				var numDays = Math.floor(postEditDuration / 86400); | ||||
| 				var numHours = Math.floor((postEditDuration % 86400) / 3600); | ||||
| 				var numMinutes = Math.floor(((postEditDuration % 86400) % 3600) / 60); | ||||
| 				var numSeconds = ((postEditDuration % 86400) % 3600) % 60; | ||||
| 				var msg = '[[error:post-edit-duration-expired, ' + postEditDuration + ']]'; | ||||
| 				if (numDays) { | ||||
| 					if (numHours) { | ||||
| 						msg = '[[error:post-edit-duration-expired-days-hours, ' + numDays + ', ' + numHours + ']]'; | ||||
| 					} else { | ||||
| 						msg = '[[error:post-edit-duration-expired-days, ' + numDays + ']]'; | ||||
| 					} | ||||
| 				} else if (numHours) { | ||||
| 					if (numMinutes) { | ||||
| 						msg = '[[error:post-edit-duration-expired-hours-minutes, ' + numHours + ', ' + numMinutes + ']]'; | ||||
| 					} else { | ||||
| 						msg = '[[error:post-edit-duration-expired-hours, ' + numHours + ']]'; | ||||
| 					} | ||||
| 				} else if (numMinutes) { | ||||
| 					if (numSeconds) { | ||||
| 						msg = '[[error:post-edit-duration-expired-minutes-seconds, ' + numMinutes + ', ' + numSeconds + ']]'; | ||||
| 					} else { | ||||
| 						msg = '[[error:post-edit-duration-expired-minutes, ' + numMinutes + ']]'; | ||||
| 					} | ||||
| 				} | ||||
| 				return app.alertError(msg); | ||||
| 			} | ||||
|  | ||||
| 			if (checkDuration(postEditDuration, timestamp, 'post-edit-duration-expired')) { | ||||
| 				$(window).trigger('action:composer.post.edit', { | ||||
| 					pid: getData(btn, 'data-pid') | ||||
| 				}); | ||||
| 			} | ||||
| 		}); | ||||
|  | ||||
| 		postContainer.on('click', '[component="post/delete"]', function() { | ||||
| 			var btn = $(this); | ||||
| 			var timestamp = parseInt(getData(btn, 'data-timestamp'), 10); | ||||
| 			var postDeleteDuration = parseInt(ajaxify.data.postDeleteDuration, 10); | ||||
| 			if (checkDuration(postDeleteDuration, timestamp, 'post-delete-duration-expired')) { | ||||
| 				togglePostDelete($(this), tid); | ||||
| 			} | ||||
| 		}); | ||||
|  | ||||
| 		function checkDuration(duration, postTimestamp, languageKey) { | ||||
| 			if (!ajaxify.data.privileges.isAdminOrMod && duration && Date.now() - postTimestamp > duration * 1000) { | ||||
| 				var numDays = Math.floor(duration / 86400); | ||||
| 				var numHours = Math.floor((duration % 86400) / 3600); | ||||
| 				var numMinutes = Math.floor(((duration % 86400) % 3600) / 60); | ||||
| 				var numSeconds = ((duration % 86400) % 3600) % 60; | ||||
| 				var msg = '[[error:' + languageKey + ', ' + duration + ']]'; | ||||
| 				if (numDays) { | ||||
| 					if (numHours) { | ||||
| 						msg = '[[error:' + languageKey + '-days-hours, ' + numDays + ', ' + numHours + ']]'; | ||||
| 					} else { | ||||
| 						msg = '[[error:' + languageKey + '-days, ' + numDays + ']]'; | ||||
| 					} | ||||
| 				} else if (numHours) { | ||||
| 					if (numMinutes) { | ||||
| 						msg = '[[error:' + languageKey + '-hours-minutes, ' + numHours + ', ' + numMinutes + ']]'; | ||||
| 					} else { | ||||
| 						msg = '[[error:' + languageKey + '-hours, ' + numHours + ']]'; | ||||
| 					} | ||||
| 				} else if (numMinutes) { | ||||
| 					if (numSeconds) { | ||||
| 						msg = '[[error:' + languageKey + '-minutes-seconds, ' + numMinutes + ', ' + numSeconds + ']]'; | ||||
| 					} else { | ||||
| 						msg = '[[error:' + languageKey + '-minutes, ' + numMinutes + ']]'; | ||||
| 					} | ||||
| 				} | ||||
| 				app.alertError(msg); | ||||
| 				return false; | ||||
| 			} | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		postContainer.on('click', '[component="post/restore"]', function() { | ||||
| 			togglePostDelete($(this), tid); | ||||
| 		}); | ||||
| @@ -394,9 +406,9 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator | ||||
| 	} | ||||
|  | ||||
| 	function togglePostDelete(button, tid) { | ||||
| 		var pid = getData(button, 'data-pid'), | ||||
| 			postEl = components.get('post', 'pid', pid), | ||||
| 			action = !postEl.hasClass('deleted') ? 'delete' : 'restore'; | ||||
| 		var pid = getData(button, 'data-pid'); | ||||
| 		var postEl = components.get('post', 'pid', pid); | ||||
| 		var action = !postEl.hasClass('deleted') ? 'delete' : 'restore'; | ||||
|  | ||||
| 		postAction(action, pid, tid); | ||||
| 	} | ||||
|   | ||||
| @@ -264,7 +264,8 @@ topicsController.get = function(req, res, callback) { | ||||
| 		data['downvote:disabled'] = parseInt(meta.config['downvote:disabled'], 10) === 1; | ||||
| 		data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; | ||||
| 		data.bookmarkThreshold = parseInt(meta.config.bookmarkThreshold, 10) || 5; | ||||
| 		data.postEditDuration = parseInt(meta.config.postEditDuration, 10); | ||||
| 		data.postEditDuration = parseInt(meta.config.postEditDuration, 10) || 0; | ||||
| 		data.postDeleteDuration = parseInt(meta.config.postDeleteDuration, 10) || 0; | ||||
| 		data.scrollToMyPost = settings.scrollToMyPost; | ||||
| 		data.rssFeedUrl = nconf.get('relative_path') + '/topic/' + data.tid + '.rss'; | ||||
| 		data.pagination = pagination.create(currentPage, pageCount); | ||||
|   | ||||
| @@ -34,10 +34,10 @@ module.exports = function(Posts) { | ||||
| 					return next(new Error('[[error:post-already-restored]]')); | ||||
| 				} | ||||
|  | ||||
| 				privileges.posts.canEdit(pid, uid, next); | ||||
| 				privileges.posts.canDelete(pid, uid, next); | ||||
| 			}, | ||||
| 			function (canEdit, next) { | ||||
| 				if (!canEdit) { | ||||
| 			function (canDelete, next) { | ||||
| 				if (!canDelete) { | ||||
| 					return next(new Error('[[error:no-privileges]]')); | ||||
| 				} | ||||
|  | ||||
|   | ||||
| @@ -150,6 +150,38 @@ module.exports = function(privileges) { | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	privileges.posts.canDelete = function(pid, uid, callback) { | ||||
| 		var postData; | ||||
| 		async.waterfall([ | ||||
| 			function(next) { | ||||
| 				posts.getPostFields(pid, ['tid', 'timestamp'], next); | ||||
| 			}, | ||||
| 			function(_postData, next) { | ||||
| 				postData = _postData; | ||||
| 				async.parallel({ | ||||
| 					isAdminOrMod: async.apply(isAdminOrMod, pid, uid), | ||||
| 					isLocked: async.apply(topics.isLocked, postData.tid), | ||||
| 					isOwner: async.apply(posts.isOwner, pid, uid) | ||||
| 				}, next); | ||||
| 			} | ||||
| 		], function(err, results) { | ||||
| 			if (err) { | ||||
| 				return callback(err); | ||||
| 			} | ||||
| 			if (results.isAdminOrMod) { | ||||
| 				return callback(null, true); | ||||
| 			} | ||||
| 			if (results.isLocked) { | ||||
| 				return callback(new Error('[[error:topic-locked]]')); | ||||
| 			} | ||||
| 			var postDeleteDuration = parseInt(meta.config.postDeleteDuration, 10); | ||||
| 			if (postDeleteDuration && (Date.now() - parseInt(postData.timestamp, 10) > postDeleteDuration * 1000)) { | ||||
| 				return callback(new Error('[[error:post-delete-duration-expired, ' + meta.config.postDeleteDuration + ']]')); | ||||
| 			} | ||||
| 			callback(null, results.isOwner); | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	privileges.posts.canMove = function(pid, uid, callback) { | ||||
| 		posts.isMain(pid, function(err, isMain) { | ||||
| 			if (err || isMain) { | ||||
|   | ||||
| @@ -48,6 +48,10 @@ | ||||
| 				<label for="postEditDuration">Number of seconds users are allowed to edit posts after posting. (0 disabled)</label> | ||||
| 				<input id="postEditDuration" type="text" class="form-control" value="0" data-field="postEditDuration"> | ||||
| 			</div> | ||||
| 			<div class="form-group"> | ||||
| 				<label for="postDeleteDuration">Number of seconds users are allowed to delete posts after posting. (0 disabled)</label> | ||||
| 				<input id="postDeleteDuration" type="text" class="form-control" value="0" data-field="postDeleteDuration"> | ||||
| 			</div> | ||||
| 			<div class="form-group"> | ||||
| 				<label for="minimumTitleLength">Minimum Title Length</label> | ||||
| 				<input id="minimumTitleLength" type="text" class="form-control" value="3" data-field="minimumTitleLength"> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user