mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 11:05:54 +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": "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-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-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).", | 	"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 timestamp = parseInt(getData(btn, 'data-timestamp'), 10); | ||||||
| 			var postEditDuration = parseInt(ajaxify.data.postEditDuration, 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', { | 				$(window).trigger('action:composer.post.edit', { | ||||||
| 					pid: getData(btn, 'data-pid') | 					pid: getData(btn, 'data-pid') | ||||||
| 				}); | 				}); | ||||||
|  | 			} | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
| 		postContainer.on('click', '[component="post/delete"]', function() { | 		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); | 				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() { | 		postContainer.on('click', '[component="post/restore"]', function() { | ||||||
| 			togglePostDelete($(this), tid); | 			togglePostDelete($(this), tid); | ||||||
| 		}); | 		}); | ||||||
| @@ -394,9 +406,9 @@ define('forum/topic/postTools', ['share', 'navigator', 'components', 'translator | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	function togglePostDelete(button, tid) { | 	function togglePostDelete(button, tid) { | ||||||
| 		var pid = getData(button, 'data-pid'), | 		var pid = getData(button, 'data-pid'); | ||||||
| 			postEl = components.get('post', 'pid', pid), | 		var postEl = components.get('post', 'pid', pid); | ||||||
| 			action = !postEl.hasClass('deleted') ? 'delete' : 'restore'; | 		var action = !postEl.hasClass('deleted') ? 'delete' : 'restore'; | ||||||
|  |  | ||||||
| 		postAction(action, pid, tid); | 		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['downvote:disabled'] = parseInt(meta.config['downvote:disabled'], 10) === 1; | ||||||
| 		data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; | 		data['feeds:disableRSS'] = parseInt(meta.config['feeds:disableRSS'], 10) === 1; | ||||||
| 		data.bookmarkThreshold = parseInt(meta.config.bookmarkThreshold, 10) || 5; | 		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.scrollToMyPost = settings.scrollToMyPost; | ||||||
| 		data.rssFeedUrl = nconf.get('relative_path') + '/topic/' + data.tid + '.rss'; | 		data.rssFeedUrl = nconf.get('relative_path') + '/topic/' + data.tid + '.rss'; | ||||||
| 		data.pagination = pagination.create(currentPage, pageCount); | 		data.pagination = pagination.create(currentPage, pageCount); | ||||||
|   | |||||||
| @@ -34,10 +34,10 @@ module.exports = function(Posts) { | |||||||
| 					return next(new Error('[[error:post-already-restored]]')); | 					return next(new Error('[[error:post-already-restored]]')); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				privileges.posts.canEdit(pid, uid, next); | 				privileges.posts.canDelete(pid, uid, next); | ||||||
| 			}, | 			}, | ||||||
| 			function (canEdit, next) { | 			function (canDelete, next) { | ||||||
| 				if (!canEdit) { | 				if (!canDelete) { | ||||||
| 					return next(new Error('[[error:no-privileges]]')); | 					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) { | 	privileges.posts.canMove = function(pid, uid, callback) { | ||||||
| 		posts.isMain(pid, function(err, isMain) { | 		posts.isMain(pid, function(err, isMain) { | ||||||
| 			if (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> | 				<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"> | 				<input id="postEditDuration" type="text" class="form-control" value="0" data-field="postEditDuration"> | ||||||
| 			</div> | 			</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"> | 			<div class="form-group"> | ||||||
| 				<label for="minimumTitleLength">Minimum Title Length</label> | 				<label for="minimumTitleLength">Minimum Title Length</label> | ||||||
| 				<input id="minimumTitleLength" type="text" class="form-control" value="3" data-field="minimumTitleLength"> | 				<input id="minimumTitleLength" type="text" class="form-control" value="3" data-field="minimumTitleLength"> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user