mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 19:15:58 +01:00 
			
		
		
		
	closes #5542
This commit is contained in:
		| @@ -149,5 +149,6 @@ | ||||
| 	"info.username-history": "Username History", | ||||
| 	"info.email-history": "Email History", | ||||
| 	"info.moderation-note": "Moderation Note", | ||||
| 	"info.moderation-note.success": "Moderation note saved" | ||||
| 	"info.moderation-note.success": "Moderation note saved", | ||||
| 	"info.moderation-note.add": "Add note" | ||||
| } | ||||
|   | ||||
| @@ -17,7 +17,19 @@ define('forum/account/info', ['forum/account/header', 'components'], function (h | ||||
| 				if (err) { | ||||
| 					return app.alertError(err.message); | ||||
| 				} | ||||
| 				$('[component="account/moderation-note"]').val(''); | ||||
| 				app.alertSuccess('[[user:info.moderation-note.success]]'); | ||||
| 				var timestamp = Date.now(); | ||||
| 				var data = [{ | ||||
| 					note: note, | ||||
| 					user: app.user, | ||||
| 					timestamp: timestamp, | ||||
| 					timestampISO: utils.toISOString(timestamp), | ||||
| 				}]; | ||||
| 				app.parseAndTranslate('account/info', 'moderationNotes', { moderationNotes: data }, function (html) { | ||||
| 					$('[component="account/moderation-note/list"]').prepend(html); | ||||
| 					html.find('.timeago').timeago(); | ||||
| 				}); | ||||
| 			}); | ||||
| 		}); | ||||
| 	} | ||||
|   | ||||
| @@ -2,14 +2,19 @@ | ||||
|  | ||||
| var async = require('async'); | ||||
|  | ||||
| var db = require('../../database'); | ||||
| var user = require('../../user'); | ||||
| var helpers = require('../helpers'); | ||||
| var accountHelpers = require('./helpers'); | ||||
| var pagination = require('../../pagination'); | ||||
|  | ||||
| var infoController = {}; | ||||
| var infoController = module.exports; | ||||
|  | ||||
| infoController.get = function (req, res, callback) { | ||||
| 	var userData; | ||||
| 	var page = Math.max(1, req.query.page || 1); | ||||
| 	var itemsPerPage = 10; | ||||
|  | ||||
| 	async.waterfall([ | ||||
| 		function (next) { | ||||
| 			accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, next); | ||||
| @@ -19,11 +24,27 @@ infoController.get = function (req, res, callback) { | ||||
| 			if (!userData) { | ||||
| 				return callback(); | ||||
| 			} | ||||
|  | ||||
| 			var start = (page - 1) * itemsPerPage; | ||||
| 			var stop = start + itemsPerPage - 1; | ||||
| 			async.parallel({ | ||||
| 				history: async.apply(user.getModerationHistory, userData.uid), | ||||
| 				sessions: async.apply(user.auth.getSessions, userData.uid, req.sessionID), | ||||
| 				usernames: async.apply(user.getHistory, 'user:' + userData.uid + ':usernames'), | ||||
| 				emails: async.apply(user.getHistory, 'user:' + userData.uid + ':emails'), | ||||
| 				notes: function (next) { | ||||
| 					if (!userData.isAdminOrGlobalModeratorOrModerator) { | ||||
| 						return setImmediate(next); | ||||
| 					} | ||||
| 					async.parallel({ | ||||
| 						notes: function (next) { | ||||
| 							user.getModerationNotes(userData.uid, start, stop, next); | ||||
| 						}, | ||||
| 						count: function (next) { | ||||
| 							db.sortedSetCard('uid:' + userData.uid + ':moderation:notes', next); | ||||
| 						}, | ||||
| 					}, next); | ||||
| 				}, | ||||
| 			}, next); | ||||
| 		}, | ||||
| 	], function (err, data) { | ||||
| @@ -35,11 +56,15 @@ infoController.get = function (req, res, callback) { | ||||
| 		userData.sessions = data.sessions; | ||||
| 		userData.usernames = data.usernames; | ||||
| 		userData.emails = data.emails; | ||||
|  | ||||
| 		if (userData.isAdminOrGlobalModeratorOrModerator) { | ||||
| 			userData.moderationNotes = data.notes.notes; | ||||
| 			var pageCount = Math.ceil(data.notes.count / itemsPerPage); | ||||
| 			userData.pagination = pagination.create(page, pageCount, req.query); | ||||
| 		} | ||||
| 		userData.title = '[[pages:account/info]]'; | ||||
| 		userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[user:account_info]]' }]); | ||||
|  | ||||
| 		res.render('account/info', userData); | ||||
| 	}); | ||||
| }; | ||||
|  | ||||
| module.exports = infoController; | ||||
|   | ||||
| @@ -316,7 +316,7 @@ SocketUser.getUserByEmail = function (socket, email, callback) { | ||||
| }; | ||||
|  | ||||
| SocketUser.setModerationNote = function (socket, data, callback) { | ||||
| 	if (!socket.uid || !data || !data.uid) { | ||||
| 	if (!socket.uid || !data || !data.uid || !data.note) { | ||||
| 		return callback(new Error('[[error:invalid-data]]')); | ||||
| 	} | ||||
|  | ||||
| @@ -335,11 +335,13 @@ SocketUser.setModerationNote = function (socket, data, callback) { | ||||
| 			if (!allowed) { | ||||
| 				return next(new Error('[[error:no-privileges]]')); | ||||
| 			} | ||||
| 			if (data.note) { | ||||
| 				user.setUserField(data.uid, 'moderationNote', data.note, next); | ||||
| 			} else { | ||||
| 				db.deleteObjectField('user:' + data.uid, 'moderationNote', next); | ||||
| 			} | ||||
|  | ||||
| 			var note = { | ||||
| 				uid: socket.uid, | ||||
| 				note: data.note, | ||||
| 				timestamp: Date.now(), | ||||
| 			}; | ||||
| 			db.sortedSetAdd('uid:' + data.uid + ':moderation:notes', note.timestamp, JSON.stringify(note), next); | ||||
| 		}, | ||||
| 	], callback); | ||||
| }; | ||||
|   | ||||
| @@ -51,7 +51,7 @@ var Upgrade = { | ||||
| 		}, | ||||
| 		{ | ||||
| 			version: 'develop',	// rename this to whatever the next NodeBB version is (breaking) | ||||
| 			upgrades: ['flags_refactor', 'post_votes_zset'], | ||||
| 			upgrades: ['flags_refactor', 'post_votes_zset', 'moderation_history_refactor'], | ||||
| 		}, | ||||
| 	], | ||||
| }; | ||||
|   | ||||
							
								
								
									
										30
									
								
								src/upgrades/1.5.0/moderation_history_refactor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/upgrades/1.5.0/moderation_history_refactor.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| /* jslint node: true */ | ||||
|  | ||||
| 'use strict'; | ||||
|  | ||||
| var db = require('../../database'); | ||||
| var batch = require('../../batch'); | ||||
|  | ||||
| var async = require('async'); | ||||
|  | ||||
| module.exports = { | ||||
| 	name: 'Update moderation notes to zset', | ||||
| 	timestamp: Date.UTC(2017, 2, 22), | ||||
| 	method: function (callback) { | ||||
| 		batch.processSortedSet('users:joindate', function (ids, next) { | ||||
| 			async.each(ids, function (uid, next) { | ||||
| 				db.getObjectField('user:' + uid, 'moderationNote', function (err, moderationNote) { | ||||
| 					if (err || !moderationNote) { | ||||
| 						return next(err); | ||||
| 					} | ||||
| 					var note = { | ||||
| 						uid: 1, | ||||
| 						note: moderationNote, | ||||
| 						timestamp: Date.now(), | ||||
| 					}; | ||||
| 					db.sortedSetAdd('uid:' + uid + ':moderation:notes', note.timestamp, JSON.stringify(note), next); | ||||
| 				}); | ||||
| 			}, next); | ||||
| 		}, callback); | ||||
| 	}, | ||||
| }; | ||||
| @@ -7,6 +7,7 @@ var validator = require('validator'); | ||||
| var db = require('../database'); | ||||
| var posts = require('../posts'); | ||||
| var topics = require('../topics'); | ||||
| var utils = require('../../public/src/utils'); | ||||
|  | ||||
| module.exports = function (User) { | ||||
| 	User.getLatestBanInfo = function (uid, callback) { | ||||
| @@ -74,7 +75,7 @@ module.exports = function (User) { | ||||
| 			} | ||||
| 			callback(null, data.map(function (set) { | ||||
| 				set.timestamp = set.score; | ||||
| 				set.timestampISO = new Date(set.score).toISOString(); | ||||
| 				set.timestampISO = utils.toISOString(set.score); | ||||
| 				set.value = validator.escape(String(set.value.split(':')[0])); | ||||
| 				delete set.score; | ||||
| 				return set; | ||||
| @@ -138,4 +139,36 @@ module.exports = function (User) { | ||||
| 			return banObj; | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	User.getModerationNotes = function (uid, start, stop, callback) { | ||||
| 		var noteData; | ||||
| 		async.waterfall([ | ||||
| 			function (next) { | ||||
| 				db.getSortedSetRevRange('uid:' + uid + ':moderation:notes', start, stop, next); | ||||
| 			}, | ||||
| 			function (notes, next) { | ||||
| 				var uids = []; | ||||
| 				noteData = notes.map(function (note) { | ||||
| 					try { | ||||
| 						var data = JSON.parse(note); | ||||
| 						uids.push(data.uid); | ||||
| 						data.timestampISO = utils.toISOString(data.timestamp); | ||||
| 						return data; | ||||
| 					} catch (err) { | ||||
| 						return next(err); | ||||
| 					} | ||||
| 				}); | ||||
|  | ||||
| 				User.getUsersFields(uids, ['uid', 'username', 'userslug', 'picture'], next); | ||||
| 			}, | ||||
| 			function (userData, next) { | ||||
| 				noteData.forEach(function (note, index) { | ||||
| 					if (note) { | ||||
| 						note.user = userData[index]; | ||||
| 					} | ||||
| 				}); | ||||
| 				next(null, noteData); | ||||
| 			}, | ||||
| 		], callback); | ||||
| 	}; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user