| 
									
										
										
										
											2014-03-12 22:11:48 -04:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-17 12:56:00 +03:00
										 |  |  | var async = require('async'); | 
					
						
							| 
									
										
										
										
											2016-08-09 12:56:42 -04:00
										 |  |  | var winston = require('winston'); | 
					
						
							| 
									
										
										
										
											2015-09-25 15:56:58 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-22 13:06:22 +02:00
										 |  |  | var user = require('../user'); | 
					
						
							|  |  |  | var topics = require('../topics'); | 
					
						
							|  |  |  | var notifications = require('../notifications'); | 
					
						
							|  |  |  | var messaging = require('../messaging'); | 
					
						
							|  |  |  | var plugins = require('../plugins'); | 
					
						
							|  |  |  | var meta = require('../meta'); | 
					
						
							|  |  |  | var events = require('../events'); | 
					
						
							|  |  |  | var emailer = require('../emailer'); | 
					
						
							|  |  |  | var db = require('../database'); | 
					
						
							| 
									
										
										
										
											2017-03-02 16:11:11 +03:00
										 |  |  | var userController = require('../controllers/user'); | 
					
						
							| 
									
										
										
										
											2016-11-15 12:45:00 +03:00
										 |  |  | var privileges = require('../privileges'); | 
					
						
							| 
									
										
										
										
											2015-09-25 15:56:58 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-13 22:12:52 -04:00
										 |  |  | var SocketUser = module.exports; | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-25 15:56:58 -04:00
										 |  |  | require('./user/profile')(SocketUser); | 
					
						
							|  |  |  | require('./user/search')(SocketUser); | 
					
						
							|  |  |  | require('./user/status')(SocketUser); | 
					
						
							|  |  |  | require('./user/picture')(SocketUser); | 
					
						
							| 
									
										
										
										
											2016-01-25 13:36:10 +02:00
										 |  |  | require('./user/ban')(SocketUser); | 
					
						
							| 
									
										
										
										
											2015-09-25 15:56:58 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.exists = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	if (!data || !data.username) { | 
					
						
							|  |  |  | 		return callback(new Error('[[error:invalid-data]]')); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	meta.userOrGroupExists(data.username, callback); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.deleteAccount = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2015-04-22 10:41:44 -04:00
										 |  |  | 	if (!socket.uid) { | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 		return callback(new Error('[[error:no-privileges]]')); | 
					
						
							| 
									
										
										
										
											2015-04-22 10:41:44 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-08 18:11:17 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-22 13:06:22 +02:00
										 |  |  | 	async.waterfall([ | 
					
						
							| 
									
										
										
										
											2018-07-03 16:38:51 -04:00
										 |  |  | 		function (next) { | 
					
						
							| 
									
										
										
										
											2018-09-06 14:32:44 -04:00
										 |  |  | 			user.hasPassword(socket.uid, next); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		function (hasPassword, next) { | 
					
						
							|  |  |  | 			if (!hasPassword) { | 
					
						
							|  |  |  | 				return next(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-07-27 11:54:23 -04:00
										 |  |  | 			user.isPasswordCorrect(socket.uid, data.password, socket.ip, function (err, ok) { | 
					
						
							|  |  |  | 				next(err || (!ok ? new Error('[[error:invalid-password]]') : undefined)); | 
					
						
							| 
									
										
										
										
											2018-07-03 16:38:51 -04:00
										 |  |  | 			}); | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-01-22 13:06:22 +02:00
										 |  |  | 		function (next) { | 
					
						
							|  |  |  | 			user.isAdministrator(socket.uid, next); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		function (isAdmin, next) { | 
					
						
							|  |  |  | 			if (isAdmin) { | 
					
						
							|  |  |  | 				return next(new Error('[[error:cant-delete-admin]]')); | 
					
						
							| 
									
										
										
										
											2015-04-22 10:41:44 -04:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-01-22 13:06:22 +02:00
										 |  |  | 			user.deleteAccount(socket.uid, next); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		function (next) { | 
					
						
							| 
									
										
										
										
											2017-02-18 12:30:49 -07:00
										 |  |  | 			require('./index').server.sockets.emit('event:user_status_change', { uid: socket.uid, status: 'offline' }); | 
					
						
							| 
									
										
										
										
											2016-01-22 13:06:22 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			events.log({ | 
					
						
							|  |  |  | 				type: 'user-delete', | 
					
						
							|  |  |  | 				uid: socket.uid, | 
					
						
							|  |  |  | 				targetUid: socket.uid, | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 				ip: socket.ip, | 
					
						
							| 
									
										
										
										
											2016-01-22 13:06:22 +02:00
										 |  |  | 			}); | 
					
						
							|  |  |  | 			next(); | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2018-07-27 11:54:23 -04:00
										 |  |  | 	], callback); | 
					
						
							| 
									
										
										
										
											2014-08-26 13:47:48 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.emailExists = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	if (!data || !data.email) { | 
					
						
							|  |  |  | 		return callback(new Error('[[error:invalid-data]]')); | 
					
						
							| 
									
										
										
										
											2014-01-16 18:18:42 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	user.email.exists(data.email, callback); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.emailConfirm = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	if (!socket.uid) { | 
					
						
							|  |  |  | 		return callback(new Error('[[error:no-privileges]]')); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-06-03 18:39:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	if (parseInt(meta.config.requireEmailConfirmation, 10) !== 1) { | 
					
						
							| 
									
										
										
										
											2016-12-02 17:05:46 +03:00
										 |  |  | 		return callback(new Error('[[error:email-confirmations-are-disabled]]')); | 
					
						
							| 
									
										
										
										
											2014-06-03 18:39:54 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-30 13:17:26 -04:00
										 |  |  | 	user.email.sendValidationEmail(socket.uid, callback); | 
					
						
							| 
									
										
										
										
											2014-06-03 18:39:54 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-19 22:07:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | // Password Reset
 | 
					
						
							|  |  |  | SocketUser.reset = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.reset.send = function (socket, email, callback) { | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	if (!email) { | 
					
						
							|  |  |  | 		return callback(new Error('[[error:invalid-data]]')); | 
					
						
							| 
									
										
										
										
											2014-01-16 18:18:42 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | 	user.reset.send(email, function (err) { | 
					
						
							| 
									
										
										
										
											2018-04-04 13:09:53 -04:00
										 |  |  | 		if (err) { | 
					
						
							|  |  |  | 			switch (err.message) { | 
					
						
							|  |  |  | 			case '[[error:invalid-email]]': | 
					
						
							|  |  |  | 				winston.warn('[user/reset] Invalid email attempt: ' + email + ' by IP ' + socket.ip + (socket.uid ? ' (uid: ' + socket.uid + ')' : '')); | 
					
						
							|  |  |  | 				err = null; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case '[[error:reset-rate-limited]]': | 
					
						
							|  |  |  | 				err = null; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-08-09 12:56:42 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-04 13:09:53 -04:00
										 |  |  | 		setTimeout(callback.bind(err), 2500); | 
					
						
							| 
									
										
										
										
											2016-08-09 12:56:42 -04:00
										 |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.reset.commit = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2015-02-11 21:54:20 -05:00
										 |  |  | 	if (!data || !data.code || !data.password) { | 
					
						
							|  |  |  | 		return callback(new Error('[[error:invalid-data]]')); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-02 17:05:46 +03:00
										 |  |  | 	var uid; | 
					
						
							|  |  |  | 	async.waterfall([ | 
					
						
							|  |  |  | 		function (next) { | 
					
						
							|  |  |  | 			async.parallel({ | 
					
						
							|  |  |  | 				uid: async.apply(db.getObjectField, 'reset:uid', data.code), | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 				reset: async.apply(user.reset.commit, data.code, data.password), | 
					
						
							| 
									
										
										
										
											2018-06-29 14:16:28 -04:00
										 |  |  | 				hook: async.apply(plugins.fireHook, 'action:password.reset', { uid: socket.uid }), | 
					
						
							| 
									
										
										
										
											2016-12-02 17:05:46 +03:00
										 |  |  | 			}, next); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		function (results, next) { | 
					
						
							|  |  |  | 			uid = results.uid; | 
					
						
							|  |  |  | 			events.log({ | 
					
						
							|  |  |  | 				type: 'password-reset', | 
					
						
							|  |  |  | 				uid: uid, | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 				ip: socket.ip, | 
					
						
							| 
									
										
										
										
											2016-12-02 17:05:46 +03:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2015-02-08 21:06:38 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-02 17:05:46 +03:00
										 |  |  | 			user.getUserField(uid, 'username', next); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		function (username, next) { | 
					
						
							|  |  |  | 			var now = new Date(); | 
					
						
							|  |  |  | 			var parsedDate = now.getFullYear() + '/' + (now.getMonth() + 1) + '/' + now.getDate(); | 
					
						
							| 
									
										
										
										
											2015-02-11 21:54:20 -05:00
										 |  |  | 			emailer.send('reset_notify', uid, { | 
					
						
							|  |  |  | 				username: username, | 
					
						
							|  |  |  | 				date: parsedDate, | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 				subject: '[[email:reset.notify.subject]]', | 
					
						
							| 
									
										
										
										
											2015-02-01 19:11:58 -05:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2015-02-11 21:54:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-02 17:05:46 +03:00
										 |  |  | 			next(); | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-12-02 17:05:46 +03:00
										 |  |  | 	], callback); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.isFollowing = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2015-10-29 22:22:33 -04:00
										 |  |  | 	if (!socket.uid || !data.uid) { | 
					
						
							| 
									
										
										
										
											2015-10-30 00:10:48 -04:00
										 |  |  | 		return callback(null, false); | 
					
						
							| 
									
										
										
										
											2015-10-29 22:22:33 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	user.isFollowing(socket.uid, data.uid, callback); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.follow = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2014-09-08 23:03:37 -04:00
										 |  |  | 	if (!socket.uid || !data) { | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 		return callback(new Error('[[error:invalid-data]]')); | 
					
						
							| 
									
										
										
										
											2014-09-08 23:03:37 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-19 15:55:56 -04:00
										 |  |  | 	var userData; | 
					
						
							| 
									
										
										
										
											2015-02-27 17:57:09 -05:00
										 |  |  | 	async.waterfall([ | 
					
						
							| 
									
										
										
										
											2016-01-27 20:03:28 +02:00
										 |  |  | 		function (next) { | 
					
						
							| 
									
										
										
										
											2015-02-27 17:57:09 -05:00
										 |  |  | 			toggleFollow('follow', socket.uid, data.uid, next); | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-01-27 20:03:28 +02:00
										 |  |  | 		function (next) { | 
					
						
							| 
									
										
										
										
											2015-02-27 17:57:09 -05:00
										 |  |  | 			user.getUserFields(socket.uid, ['username', 'userslug'], next); | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-01-27 20:03:28 +02:00
										 |  |  | 		function (_userData, next) { | 
					
						
							| 
									
										
										
										
											2015-03-19 15:55:56 -04:00
										 |  |  | 			userData = _userData; | 
					
						
							| 
									
										
										
										
											2014-09-08 23:03:37 -04:00
										 |  |  | 			notifications.create({ | 
					
						
							| 
									
										
										
										
											2017-03-14 23:03:03 +03:00
										 |  |  | 				type: 'follow', | 
					
						
							| 
									
										
										
										
											2014-09-08 23:03:37 -04:00
										 |  |  | 				bodyShort: '[[notifications:user_started_following_you, ' + userData.username + ']]', | 
					
						
							| 
									
										
										
										
											2014-09-12 16:35:30 -04:00
										 |  |  | 				nid: 'follow:' + data.uid + ':uid:' + socket.uid, | 
					
						
							| 
									
										
										
										
											2015-08-20 11:23:16 -04:00
										 |  |  | 				from: socket.uid, | 
					
						
							| 
									
										
										
										
											2016-10-21 14:44:22 -04:00
										 |  |  | 				path: '/uid/' + data.uid + '/followers', | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 				mergeId: 'notifications:user_started_following_you', | 
					
						
							| 
									
										
										
										
											2015-02-27 17:57:09 -05:00
										 |  |  | 			}, next); | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-01-27 20:03:28 +02:00
										 |  |  | 		function (notification, next) { | 
					
						
							|  |  |  | 			if (!notification) { | 
					
						
							|  |  |  | 				return next(); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-03-19 15:55:56 -04:00
										 |  |  | 			notification.user = userData; | 
					
						
							| 
									
										
										
										
											2015-02-27 17:57:09 -05:00
										 |  |  | 			notifications.push(notification, [data.uid], next); | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2015-02-27 17:57:09 -05:00
										 |  |  | 	], callback); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.unfollow = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	if (!socket.uid || !data) { | 
					
						
							|  |  |  | 		return callback(new Error('[[error:invalid-data]]')); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	toggleFollow('unfollow', socket.uid, data.uid, callback); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-14 17:59:33 -04:00
										 |  |  | function toggleFollow(method, uid, theiruid, callback) { | 
					
						
							| 
									
										
										
										
											2017-05-26 00:02:20 -04:00
										 |  |  | 	async.waterfall([ | 
					
						
							|  |  |  | 		function (next) { | 
					
						
							|  |  |  | 			user[method](uid, theiruid, next); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		function (next) { | 
					
						
							|  |  |  | 			plugins.fireHook('action:user.' + method, { | 
					
						
							|  |  |  | 				fromUid: uid, | 
					
						
							|  |  |  | 				toUid: theiruid, | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 			next(); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	], callback); | 
					
						
							| 
									
										
										
										
											2014-08-14 17:59:33 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.saveSettings = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2014-07-20 21:10:23 -04:00
										 |  |  | 	if (!socket.uid || !data) { | 
					
						
							|  |  |  | 		return callback(new Error('[[error:invalid-data]]')); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-07-20 21:10:23 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-16 18:04:02 +02:00
										 |  |  | 	async.waterfall([ | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | 		function (next) { | 
					
						
							| 
									
										
										
										
											2016-11-15 12:45:00 +03:00
										 |  |  | 			privileges.users.canEdit(socket.uid, data.uid, next); | 
					
						
							| 
									
										
										
										
											2016-03-08 11:24:32 +02:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | 		function (allowed, next) { | 
					
						
							| 
									
										
										
										
											2016-02-16 18:04:02 +02:00
										 |  |  | 			if (!allowed) { | 
					
						
							|  |  |  | 				return next(new Error('[[error:no-privileges]]')); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			user.saveSettings(data.uid, data.settings, next); | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-02-16 18:04:02 +02:00
										 |  |  | 	], callback); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.setTopicSort = function (socket, sort, callback) { | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	user.setSetting(socket.uid, 'topicPostSort', sort, callback); | 
					
						
							| 
									
										
										
										
											2014-06-06 22:12:14 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.setCategorySort = function (socket, sort, callback) { | 
					
						
							| 
									
										
										
										
											2016-03-09 19:13:36 +02:00
										 |  |  | 	user.setSetting(socket.uid, 'categoryTopicSort', sort, callback); | 
					
						
							| 
									
										
										
										
											2015-01-08 13:47:15 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.getUnreadCount = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2014-11-01 16:55:50 -04:00
										 |  |  | 	if (!socket.uid) { | 
					
						
							|  |  |  | 		return callback(null, 0); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-03-09 14:02:30 -04:00
										 |  |  | 	topics.getTotalUnread(socket.uid, callback); | 
					
						
							| 
									
										
										
										
											2014-01-09 22:46:51 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.getUnreadChatCount = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2014-11-01 16:55:50 -04:00
										 |  |  | 	if (!socket.uid) { | 
					
						
							|  |  |  | 		return callback(null, 0); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-07-19 10:33:27 -04:00
										 |  |  | 	messaging.getUnreadCount(socket.uid, callback); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.getUnreadCounts = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2015-10-20 19:19:50 -04:00
										 |  |  | 	if (!socket.uid) { | 
					
						
							|  |  |  | 		return callback(null, {}); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	async.parallel({ | 
					
						
							|  |  |  | 		unreadTopicCount: async.apply(topics.getTotalUnread, socket.uid), | 
					
						
							| 
									
										
										
										
											2016-04-08 13:54:51 -05:00
										 |  |  | 		unreadNewTopicCount: async.apply(topics.getTotalUnread, socket.uid, 'new'), | 
					
						
							| 
									
										
										
										
											2017-04-21 21:36:42 -04:00
										 |  |  | 		unreadWatchedTopicCount: async.apply(topics.getTotalUnread, socket.uid, 'watched'), | 
					
						
							| 
									
										
										
										
											2015-10-20 19:19:50 -04:00
										 |  |  | 		unreadChatCount: async.apply(messaging.getUnreadCount, socket.uid), | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 		unreadNotificationCount: async.apply(user.notifications.getUnreadCount, socket.uid), | 
					
						
							| 
									
										
										
										
											2015-10-20 19:19:50 -04:00
										 |  |  | 	}, callback); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.invite = function (socket, email, callback) { | 
					
						
							| 
									
										
										
										
											2015-06-28 21:54:21 -04:00
										 |  |  | 	if (!email || !socket.uid) { | 
					
						
							| 
									
										
										
										
											2015-11-27 16:55:31 -07:00
										 |  |  | 		return callback(new Error('[[error:invalid-data]]')); | 
					
						
							| 
									
										
										
										
											2015-06-28 21:54:21 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-22 13:06:22 +02:00
										 |  |  | 	var registrationType = meta.config.registrationType; | 
					
						
							| 
									
										
										
										
											2015-11-28 15:33:17 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (registrationType !== 'invite-only' && registrationType !== 'admin-invite-only') { | 
					
						
							| 
									
										
										
										
											2015-06-28 21:54:21 -04:00
										 |  |  | 		return callback(new Error('[[error:forum-not-invite-only]]')); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 15:08:11 +03:00
										 |  |  | 	async.waterfall([ | 
					
						
							|  |  |  | 		function (next) { | 
					
						
							|  |  |  | 			user.isAdministrator(socket.uid, next); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		function (isAdmin, next) { | 
					
						
							|  |  |  | 			if (registrationType === 'admin-invite-only' && !isAdmin) { | 
					
						
							|  |  |  | 				return next(new Error('[[error:no-privileges]]')); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-09-20 11:55:53 -04:00
										 |  |  | 			var max = parseInt(meta.config.maximumInvites, 10); | 
					
						
							|  |  |  | 			email = email.split(',').map(email => email.trim()).filter(Boolean); | 
					
						
							|  |  |  | 			async.eachSeries(email, function (email, next) { | 
					
						
							|  |  |  | 				async.waterfall([ | 
					
						
							|  |  |  | 					function (next) { | 
					
						
							|  |  |  | 						if (max) { | 
					
						
							|  |  |  | 							user.getInvitesNumber(socket.uid, next); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							next(null, 0); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 					function (invites, next) { | 
					
						
							|  |  |  | 						if (!isAdmin && max && invites >= max) { | 
					
						
							|  |  |  | 							return next(new Error('[[error:invite-maximum-met, ' + invites + ', ' + max + ']]')); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2017-02-21 15:08:11 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-19 14:38:07 -04:00
										 |  |  | 						user.sendInvitationEmail(socket.uid, email, next); | 
					
						
							| 
									
										
										
										
											2018-09-20 11:55:53 -04:00
										 |  |  | 					}, | 
					
						
							|  |  |  | 				], next); | 
					
						
							|  |  |  | 			}, next); | 
					
						
							| 
									
										
										
										
											2017-02-23 18:31:49 -07:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2017-02-21 15:08:11 +03:00
										 |  |  | 	], callback); | 
					
						
							| 
									
										
										
										
											2015-06-28 21:54:21 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.getUserByUID = function (socket, uid, callback) { | 
					
						
							| 
									
										
										
										
											2017-03-02 16:11:11 +03:00
										 |  |  | 	userController.getUserDataByField(socket.uid, 'uid', uid, callback); | 
					
						
							| 
									
										
										
										
											2016-03-08 11:24:32 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.getUserByUsername = function (socket, username, callback) { | 
					
						
							| 
									
										
										
										
											2017-03-02 16:11:11 +03:00
										 |  |  | 	userController.getUserDataByField(socket.uid, 'username', username, callback); | 
					
						
							| 
									
										
										
										
											2016-03-08 11:24:32 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.getUserByEmail = function (socket, email, callback) { | 
					
						
							| 
									
										
										
										
											2017-03-02 16:11:11 +03:00
										 |  |  | 	userController.getUserDataByField(socket.uid, 'email', email, callback); | 
					
						
							| 
									
										
										
										
											2016-03-08 11:24:32 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | SocketUser.setModerationNote = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2017-03-23 10:58:17 +03:00
										 |  |  | 	if (!socket.uid || !data || !data.uid || !data.note) { | 
					
						
							| 
									
										
										
										
											2016-09-21 12:55:44 +03:00
										 |  |  | 		return callback(new Error('[[error:invalid-data]]')); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	async.waterfall([ | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | 		function (next) { | 
					
						
							| 
									
										
										
										
											2016-11-15 12:45:00 +03:00
										 |  |  | 			privileges.users.canEdit(socket.uid, data.uid, next); | 
					
						
							| 
									
										
										
										
											2016-09-21 12:55:44 +03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-10-24 15:58:57 -04:00
										 |  |  | 		function (allowed, next) { | 
					
						
							|  |  |  | 			if (allowed) { | 
					
						
							| 
									
										
										
										
											2017-05-13 22:12:52 -04:00
										 |  |  | 				return setImmediate(next, null, allowed); | 
					
						
							| 
									
										
										
										
											2016-10-24 15:58:57 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			user.isModeratorOfAnyCategory(socket.uid, next); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		function (allowed, next) { | 
					
						
							|  |  |  | 			if (!allowed) { | 
					
						
							| 
									
										
										
										
											2016-09-21 12:55:44 +03:00
										 |  |  | 				return next(new Error('[[error:no-privileges]]')); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-03-23 10:58:17 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			var note = { | 
					
						
							|  |  |  | 				uid: socket.uid, | 
					
						
							|  |  |  | 				note: data.note, | 
					
						
							|  |  |  | 				timestamp: Date.now(), | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			db.sortedSetAdd('uid:' + data.uid + ':moderation:notes', note.timestamp, JSON.stringify(note), next); | 
					
						
							| 
									
										
										
										
											2017-02-17 19:31:21 -07:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2016-09-21 12:55:44 +03:00
										 |  |  | 	], callback); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-04-09 12:22:44 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-09 20:22:36 -04:00
										 |  |  | SocketUser.deleteUpload = function (socket, data, callback) { | 
					
						
							| 
									
										
										
										
											2018-04-12 12:35:05 -04:00
										 |  |  | 	if (!data || !data.name || !data.uid) { | 
					
						
							| 
									
										
										
										
											2018-04-09 20:03:33 -04:00
										 |  |  | 		return callback(new Error('[[error:invalid-data]]')); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-12 12:35:05 -04:00
										 |  |  | 	user.deleteUpload(socket.uid, data.uid, data.name, callback); | 
					
						
							| 
									
										
										
										
											2018-04-09 20:03:33 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-09 12:22:44 -04:00
										 |  |  | SocketUser.gdpr = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SocketUser.gdpr.consent = function (socket, data, callback) { | 
					
						
							|  |  |  | 	user.setUserField(socket.uid, 'gdpr_consent', 1, callback); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-05-11 12:18:51 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | SocketUser.gdpr.check = function (socket, data, callback) { | 
					
						
							|  |  |  | 	async.waterfall([ | 
					
						
							|  |  |  | 		async.apply(user.isAdministrator, socket.uid), | 
					
						
							|  |  |  | 		function (isAdmin, next) { | 
					
						
							|  |  |  | 			if (!isAdmin) { | 
					
						
							|  |  |  | 				data.uid = socket.uid; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			db.getObjectField('user:' + data.uid, 'gdpr_consent', next); | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	], callback); | 
					
						
							|  |  |  | }; |