| 
									
										
										
										
											2015-09-25 01:52:41 -04:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | const validator = require('validator'); | 
					
						
							|  |  |  | const nconf = require('nconf'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 13:58:44 -05:00
										 |  |  | const db = require('../../database'); | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | const user = require('../../user'); | 
					
						
							|  |  |  | const groups = require('../../groups'); | 
					
						
							|  |  |  | const plugins = require('../../plugins'); | 
					
						
							|  |  |  | const meta = require('../../meta'); | 
					
						
							|  |  |  | const utils = require('../../utils'); | 
					
						
							|  |  |  | const privileges = require('../../privileges'); | 
					
						
							| 
									
										
										
										
											2019-07-20 23:18:45 -04:00
										 |  |  | const translator = require('../../translator'); | 
					
						
							| 
									
										
										
										
											2019-12-05 14:56:01 -05:00
										 |  |  | const messaging = require('../../messaging'); | 
					
						
							| 
									
										
										
										
											2020-11-23 13:58:44 -05:00
										 |  |  | const categories = require('../../categories'); | 
					
						
							| 
									
										
										
										
											2015-09-25 01:52:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | const helpers = module.exports; | 
					
						
							| 
									
										
										
										
											2015-09-25 01:52:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | helpers.getUserDataByUserSlug = async function (userslug, callerUID) { | 
					
						
							|  |  |  | 	const uid = await user.getUidByUserslug(userslug); | 
					
						
							|  |  |  | 	if (!uid) { | 
					
						
							|  |  |  | 		return null; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-26 15:20:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	const results = await getAllData(uid, callerUID); | 
					
						
							|  |  |  | 	if (!results.userData) { | 
					
						
							|  |  |  | 		throw new Error('[[error:invalid-uid]]'); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	await parseAboutMe(results.userData); | 
					
						
							| 
									
										
										
										
											2018-10-26 15:20:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	const userData = results.userData; | 
					
						
							|  |  |  | 	const userSettings = results.userSettings; | 
					
						
							|  |  |  | 	const isAdmin = results.isAdmin; | 
					
						
							|  |  |  | 	const isGlobalModerator = results.isGlobalModerator; | 
					
						
							|  |  |  | 	const isModerator = results.isModerator; | 
					
						
							| 
									
										
										
										
											2019-09-17 18:02:52 +00:00
										 |  |  | 	const canViewInfo = results.canViewInfo; | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	const isSelf = parseInt(callerUID, 10) === parseInt(userData.uid, 10); | 
					
						
							| 
									
										
										
										
											2015-09-25 01:52:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	userData.age = Math.max(0, userData.birthday ? Math.floor((new Date().getTime() - new Date(userData.birthday).getTime()) / 31536000000) : 0); | 
					
						
							| 
									
										
										
										
											2015-09-25 01:52:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	userData.emailClass = 'hide'; | 
					
						
							| 
									
										
										
										
											2016-03-20 15:07:11 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	if (!isAdmin && !isGlobalModerator && !isSelf && (!userSettings.showemail || meta.config.hideEmail)) { | 
					
						
							|  |  |  | 		userData.email = ''; | 
					
						
							|  |  |  | 	} else if (!userSettings.showemail) { | 
					
						
							|  |  |  | 		userData.emailClass = ''; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-25 01:52:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	if (!isAdmin && !isGlobalModerator && !isSelf && (!userSettings.showfullname || meta.config.hideFullname)) { | 
					
						
							|  |  |  | 		userData.fullname = ''; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-25 01:52:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-17 18:02:52 +00:00
										 |  |  | 	if (isAdmin || isSelf || (canViewInfo && !results.isTargetAdmin)) { | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 		userData.ips = results.ips; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-25 01:52:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	if (!isAdmin && !isGlobalModerator && !isModerator) { | 
					
						
							|  |  |  | 		userData.moderationNote = undefined; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-30 18:42:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	userData.isBlocked = results.isBlocked; | 
					
						
							|  |  |  | 	userData.yourid = callerUID; | 
					
						
							|  |  |  | 	userData.theirid = userData.uid; | 
					
						
							|  |  |  | 	userData.isTargetAdmin = results.isTargetAdmin; | 
					
						
							|  |  |  | 	userData.isAdmin = isAdmin; | 
					
						
							|  |  |  | 	userData.isGlobalModerator = isGlobalModerator; | 
					
						
							|  |  |  | 	userData.isModerator = isModerator; | 
					
						
							|  |  |  | 	userData.isAdminOrGlobalModerator = isAdmin || isGlobalModerator; | 
					
						
							|  |  |  | 	userData.isAdminOrGlobalModeratorOrModerator = isAdmin || isGlobalModerator || isModerator; | 
					
						
							|  |  |  | 	userData.isSelfOrAdminOrGlobalModerator = isSelf || isAdmin || isGlobalModerator; | 
					
						
							|  |  |  | 	userData.canEdit = results.canEdit; | 
					
						
							|  |  |  | 	userData.canBan = results.canBanUser; | 
					
						
							| 
									
										
										
										
											2020-11-27 11:54:27 -05:00
										 |  |  | 	userData.canFlag = (await privileges.users.canFlag(callerUID, userData.uid)).flag; | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	userData.canChangePassword = isAdmin || (isSelf && !meta.config['password:disableEdit']); | 
					
						
							|  |  |  | 	userData.isSelf = isSelf; | 
					
						
							|  |  |  | 	userData.isFollowing = results.isFollowing; | 
					
						
							| 
									
										
										
										
											2019-12-05 14:56:01 -05:00
										 |  |  | 	userData.hasPrivateChat = results.hasPrivateChat; | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	userData.showHidden = isSelf || isAdmin || (isGlobalModerator && !results.isTargetAdmin); | 
					
						
							|  |  |  | 	userData.groups = Array.isArray(results.groups) && results.groups.length ? results.groups[0] : []; | 
					
						
							|  |  |  | 	userData.disableSignatures = meta.config.disableSignatures === 1; | 
					
						
							|  |  |  | 	userData['reputation:disabled'] = meta.config['reputation:disabled'] === 1; | 
					
						
							|  |  |  | 	userData['downvote:disabled'] = meta.config['downvote:disabled'] === 1; | 
					
						
							|  |  |  | 	userData['email:confirmed'] = !!userData['email:confirmed']; | 
					
						
							| 
									
										
										
										
											2020-08-07 12:25:17 -04:00
										 |  |  | 	userData.profile_links = filterLinks(results.profile_menu.links, { | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 		self: isSelf, | 
					
						
							|  |  |  | 		other: !isSelf, | 
					
						
							|  |  |  | 		moderator: isModerator, | 
					
						
							|  |  |  | 		globalMod: isGlobalModerator, | 
					
						
							|  |  |  | 		admin: isAdmin, | 
					
						
							| 
									
										
										
										
											2019-09-17 18:02:52 +00:00
										 |  |  | 		canViewInfo: canViewInfo, | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2016-09-14 15:56:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	userData.sso = results.sso.associations; | 
					
						
							|  |  |  | 	userData.website = validator.escape(String(userData.website || '')); | 
					
						
							|  |  |  | 	userData.websiteLink = !userData.website.startsWith('http') ? 'http://' + userData.website : userData.website; | 
					
						
							|  |  |  | 	userData.websiteName = userData.website.replace(validator.escape('http://'), '').replace(validator.escape('https://'), ''); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userData.fullname = validator.escape(String(userData.fullname || '')); | 
					
						
							|  |  |  | 	userData.location = validator.escape(String(userData.location || '')); | 
					
						
							|  |  |  | 	userData.signature = validator.escape(String(userData.signature || '')); | 
					
						
							|  |  |  | 	userData.birthday = validator.escape(String(userData.birthday || '')); | 
					
						
							|  |  |  | 	userData.moderationNote = validator.escape(String(userData.moderationNote || '')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (userData['cover:url']) { | 
					
						
							|  |  |  | 		userData['cover:url'] = userData['cover:url'].startsWith('http') ? userData['cover:url'] : (nconf.get('relative_path') + userData['cover:url']); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		userData['cover:url'] = require('../../coverPhoto').getDefaultProfileCover(userData.uid); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-25 01:52:41 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	userData['cover:position'] = validator.escape(String(userData['cover:position'] || '50% 50%')); | 
					
						
							|  |  |  | 	userData['username:disableEdit'] = !userData.isAdmin && meta.config['username:disableEdit']; | 
					
						
							|  |  |  | 	userData['email:disableEdit'] = !userData.isAdmin && meta.config['email:disableEdit']; | 
					
						
							| 
									
										
										
										
											2020-11-23 13:58:44 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	await getCounts(userData, callerUID); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 16:06:26 -05:00
										 |  |  | 	const hookData = await plugins.hooks.fire('filter:helpers.getUserDataByUserSlug', { userData: userData, callerUID: callerUID }); | 
					
						
							| 
									
										
										
										
											2020-04-02 16:00:48 -04:00
										 |  |  | 	return hookData.userData; | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2017-11-08 16:32:16 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | async function getAllData(uid, callerUID) { | 
					
						
							|  |  |  | 	return await utils.promiseParallel({ | 
					
						
							|  |  |  | 		userData: user.getUserData(uid), | 
					
						
							|  |  |  | 		isTargetAdmin: user.isAdministrator(uid), | 
					
						
							|  |  |  | 		userSettings: user.getSettings(uid), | 
					
						
							|  |  |  | 		isAdmin: user.isAdministrator(callerUID), | 
					
						
							|  |  |  | 		isGlobalModerator: user.isGlobalModerator(callerUID), | 
					
						
							|  |  |  | 		isModerator: user.isModeratorOfAnyCategory(callerUID), | 
					
						
							|  |  |  | 		isFollowing: user.isFollowing(callerUID, uid), | 
					
						
							|  |  |  | 		ips: user.getIPs(uid, 4), | 
					
						
							| 
									
										
										
										
											2020-08-07 12:25:17 -04:00
										 |  |  | 		profile_menu: getProfileMenu(uid, callerUID), | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 		groups: groups.getUserGroups([uid]), | 
					
						
							| 
									
										
										
										
											2020-11-20 16:06:26 -05:00
										 |  |  | 		sso: plugins.hooks.fire('filter:auth.list', { uid: uid, associations: [] }), | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 		canEdit: privileges.users.canEdit(callerUID, uid), | 
					
						
							|  |  |  | 		canBanUser: privileges.users.canBanUser(callerUID, uid), | 
					
						
							|  |  |  | 		isBlocked: user.blocks.is(uid, callerUID), | 
					
						
							| 
									
										
										
										
											2019-09-17 18:02:52 +00:00
										 |  |  | 		canViewInfo: privileges.global.can('view:users:info', callerUID), | 
					
						
							| 
									
										
										
										
											2019-12-05 14:56:01 -05:00
										 |  |  | 		hasPrivateChat: messaging.hasPrivateChat(callerUID, uid), | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	}); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-10-29 15:56:48 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-23 13:58:44 -05:00
										 |  |  | async function getCounts(userData, callerUID) { | 
					
						
							|  |  |  | 	const uid = userData.uid; | 
					
						
							|  |  |  | 	const cids = await categories.getCidsByPrivilege('categories:cid', callerUID, 'topics:read'); | 
					
						
							|  |  |  | 	const promises = { | 
					
						
							|  |  |  | 		posts: db.sortedSetsCardSum(cids.map(c => 'cid:' + c + ':uid:' + uid + ':pids')), | 
					
						
							|  |  |  | 		best: db.sortedSetsCardSum(cids.map(c => 'cid:' + c + ':uid:' + uid + ':pids:votes')), | 
					
						
							|  |  |  | 		topics: db.sortedSetsCardSum(cids.map(c => 'cid:' + c + ':uid:' + uid + ':tids')), | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 	if (userData.isAdmin || userData.isSelf) { | 
					
						
							|  |  |  | 		promises.ignored = db.sortedSetCard('uid:' + uid + ':ignored_tids'); | 
					
						
							|  |  |  | 		promises.watched = db.sortedSetCard('uid:' + uid + ':followed_tids'); | 
					
						
							|  |  |  | 		promises.upvoted = db.sortedSetCard('uid:' + uid + ':upvote'); | 
					
						
							|  |  |  | 		promises.downvoted = db.sortedSetCard('uid:' + uid + ':downvote'); | 
					
						
							|  |  |  | 		promises.bookmarks = db.sortedSetCard('uid:' + uid + ':bookmarks'); | 
					
						
							|  |  |  | 		promises.uploaded = db.sortedSetCard('uid:' + uid + ':uploads'); | 
					
						
							|  |  |  | 		promises.categoriesWatched = user.getWatchedCategories(uid); | 
					
						
							|  |  |  | 		promises.blocks = user.getUserField(userData.uid, 'blocksCount'); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	const counts = await utils.promiseParallel(promises); | 
					
						
							|  |  |  | 	counts.categoriesWatched = counts.categoriesWatched && counts.categoriesWatched.length; | 
					
						
							|  |  |  | 	counts.groups = userData.groups.length; | 
					
						
							|  |  |  | 	counts.following = userData.followingCount; | 
					
						
							|  |  |  | 	counts.followers = userData.followerCount; | 
					
						
							| 
									
										
										
										
											2020-11-23 14:18:47 -05:00
										 |  |  | 	userData.blocksCount = counts.blocks || 0; // for backwards compatibility, remove in 1.16.0
 | 
					
						
							| 
									
										
										
										
											2020-11-23 13:58:44 -05:00
										 |  |  | 	userData.counts = counts; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 12:25:17 -04:00
										 |  |  | async function getProfileMenu(uid, callerUID) { | 
					
						
							|  |  |  | 	const links = [{ | 
					
						
							|  |  |  | 		id: 'info', | 
					
						
							|  |  |  | 		route: 'info', | 
					
						
							|  |  |  | 		name: '[[user:account_info]]', | 
					
						
							|  |  |  | 		icon: 'fa-info', | 
					
						
							|  |  |  | 		visibility: { | 
					
						
							|  |  |  | 			self: false, | 
					
						
							|  |  |  | 			other: false, | 
					
						
							|  |  |  | 			moderator: false, | 
					
						
							|  |  |  | 			globalMod: false, | 
					
						
							|  |  |  | 			admin: true, | 
					
						
							|  |  |  | 			canViewInfo: true, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}, { | 
					
						
							|  |  |  | 		id: 'sessions', | 
					
						
							|  |  |  | 		route: 'sessions', | 
					
						
							|  |  |  | 		name: '[[pages:account/sessions]]', | 
					
						
							|  |  |  | 		icon: 'fa-group', | 
					
						
							|  |  |  | 		visibility: { | 
					
						
							|  |  |  | 			self: true, | 
					
						
							|  |  |  | 			other: false, | 
					
						
							|  |  |  | 			moderator: false, | 
					
						
							|  |  |  | 			globalMod: false, | 
					
						
							|  |  |  | 			admin: false, | 
					
						
							|  |  |  | 			canViewInfo: false, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (meta.config.gdpr_enabled) { | 
					
						
							|  |  |  | 		links.push({ | 
					
						
							|  |  |  | 			id: 'consent', | 
					
						
							|  |  |  | 			route: 'consent', | 
					
						
							|  |  |  | 			name: '[[user:consent.title]]', | 
					
						
							|  |  |  | 			icon: 'fa-thumbs-o-up', | 
					
						
							|  |  |  | 			visibility: { | 
					
						
							|  |  |  | 				self: true, | 
					
						
							|  |  |  | 				other: false, | 
					
						
							|  |  |  | 				moderator: false, | 
					
						
							|  |  |  | 				globalMod: false, | 
					
						
							|  |  |  | 				admin: false, | 
					
						
							|  |  |  | 				canViewInfo: false, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 16:06:26 -05:00
										 |  |  | 	return await plugins.hooks.fire('filter:user.profileMenu', { | 
					
						
							| 
									
										
										
										
											2020-08-07 12:25:17 -04:00
										 |  |  | 		uid: uid, | 
					
						
							|  |  |  | 		callerUID: callerUID, | 
					
						
							|  |  |  | 		links: links, | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | async function parseAboutMe(userData) { | 
					
						
							| 
									
										
										
										
											2019-07-20 23:18:45 -04:00
										 |  |  | 	if (!userData.aboutme) { | 
					
						
							| 
									
										
										
										
											2020-04-23 21:50:08 -04:00
										 |  |  | 		userData.aboutme = ''; | 
					
						
							|  |  |  | 		userData.aboutmeParsed = ''; | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2019-07-20 23:18:45 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	userData.aboutme = validator.escape(String(userData.aboutme || '')); | 
					
						
							| 
									
										
										
										
											2020-11-20 16:06:26 -05:00
										 |  |  | 	const parsed = await plugins.hooks.fire('filter:parse.aboutme', userData.aboutme); | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | 	userData.aboutmeParsed = translator.escape(parsed); | 
					
						
							| 
									
										
										
										
											2019-07-20 23:18:45 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-07 12:25:17 -04:00
										 |  |  | function filterLinks(links, states) { | 
					
						
							|  |  |  | 	return links.filter(function (link, index) { | 
					
						
							|  |  |  | 		// Default visibility
 | 
					
						
							|  |  |  | 		link.visibility = { self: true, | 
					
						
							|  |  |  | 			other: true, | 
					
						
							|  |  |  | 			moderator: true, | 
					
						
							|  |  |  | 			globalMod: true, | 
					
						
							|  |  |  | 			admin: true, | 
					
						
							|  |  |  | 			canViewInfo: true, | 
					
						
							|  |  |  | 			...link.visibility }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var permit = Object.keys(states).some(function (state) { | 
					
						
							|  |  |  | 			return states[state] && link.visibility[state]; | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		links[index].public = permit; | 
					
						
							|  |  |  | 		return permit; | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-22 19:41:18 -04:00
										 |  |  | require('../../promisify')(helpers); |