mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 11:05:54 +01:00 
			
		
		
		
	feat: async/await refactor
controllers/accounts
This commit is contained in:
		| @@ -1,35 +1,23 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| var async = require('async'); | const user = require('../../user'); | ||||||
|  | const meta = require('../../meta'); | ||||||
|  | const plugins = require('../../plugins'); | ||||||
|  | const helpers = require('../helpers'); | ||||||
|  | const groups = require('../../groups'); | ||||||
|  | const accountHelpers = require('./helpers'); | ||||||
|  | const privileges = require('../../privileges'); | ||||||
|  | const file = require('../../file'); | ||||||
|  |  | ||||||
| var db = require('../../database'); | const editController = module.exports; | ||||||
| var user = require('../../user'); |  | ||||||
| var meta = require('../../meta'); |  | ||||||
| var plugins = require('../../plugins'); |  | ||||||
| var helpers = require('../helpers'); |  | ||||||
| var groups = require('../../groups'); |  | ||||||
| var accountHelpers = require('./helpers'); |  | ||||||
| var privileges = require('../../privileges'); |  | ||||||
| var file = require('../../file'); |  | ||||||
|  |  | ||||||
| var editController = module.exports; | editController.get = async function (req, res, next) { | ||||||
|  | 	const [userData, canUseSignature] = await Promise.all([ | ||||||
| editController.get = function (req, res, callback) { | 		accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid), | ||||||
| 	async.waterfall([ | 		privileges.global.can('signature', req.uid), | ||||||
| 		function (next) { | 	]); | ||||||
| 			async.parallel({ |  | ||||||
| 				userData: function (next) { |  | ||||||
| 					accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, next); |  | ||||||
| 				}, |  | ||||||
| 				canUseSignature: function (next) { |  | ||||||
| 					privileges.global.can('signature', req.uid, next); |  | ||||||
| 				}, |  | ||||||
| 			}, next); |  | ||||||
| 		}, |  | ||||||
| 		function (results, next) { |  | ||||||
| 			var userData = results.userData; |  | ||||||
| 	if (!userData) { | 	if (!userData) { | ||||||
| 				return callback(); | 		return next(); | ||||||
| 	} | 	} | ||||||
| 	userData.maximumSignatureLength = meta.config.maximumSignatureLength; | 	userData.maximumSignatureLength = meta.config.maximumSignatureLength; | ||||||
| 	userData.maximumAboutMeLength = meta.config.maximumAboutMeLength; | 	userData.maximumAboutMeLength = meta.config.maximumAboutMeLength; | ||||||
| @@ -41,13 +29,11 @@ editController.get = function (req, res, callback) { | |||||||
| 	userData.allowAccountDelete = meta.config.allowAccountDelete === 1; | 	userData.allowAccountDelete = meta.config.allowAccountDelete === 1; | ||||||
| 	userData.allowWebsite = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:website']; | 	userData.allowWebsite = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:website']; | ||||||
| 	userData.allowAboutMe = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:aboutme']; | 	userData.allowAboutMe = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:aboutme']; | ||||||
| 			userData.allowSignature = results.canUseSignature && (!userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:signature']); | 	userData.allowSignature = canUseSignature && (!userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:signature']); | ||||||
| 	userData.profileImageDimension = meta.config.profileImageDimension; | 	userData.profileImageDimension = meta.config.profileImageDimension; | ||||||
| 	userData.defaultAvatar = user.getDefaultAvatar(); | 	userData.defaultAvatar = user.getDefaultAvatar(); | ||||||
|  |  | ||||||
| 			userData.groups = userData.groups.filter(function (group) { | 	userData.groups = userData.groups.filter(g => g && g.userTitleEnabled && !groups.isPrivilegeGroup(g.name) && g.name !== 'registered-users'); | ||||||
| 				return group && group.userTitleEnabled && !groups.isPrivilegeGroup(group.name) && group.name !== 'registered-users'; |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 	if (!userData.allowMultipleBadges) { | 	if (!userData.allowMultipleBadges) { | ||||||
| 		userData.groupTitle = userData.groupTitleArray[0]; | 		userData.groupTitle = userData.groupTitleArray[0]; | ||||||
| @@ -68,36 +54,27 @@ editController.get = function (req, res, callback) { | |||||||
| 	]); | 	]); | ||||||
| 	userData.editButtons = []; | 	userData.editButtons = []; | ||||||
|  |  | ||||||
| 			plugins.fireHook('filter:user.account.edit', userData, next); | 	const result = await plugins.fireHook('filter:user.account.edit', userData); | ||||||
| 		}, | 	res.render('account/edit', result); | ||||||
| 		function (userData) { |  | ||||||
| 			res.render('account/edit', userData); |  | ||||||
| 		}, |  | ||||||
| 	], callback); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| editController.password = function (req, res, next) { | editController.password = async function (req, res, next) { | ||||||
| 	renderRoute('password', req, res, next); | 	await renderRoute('password', req, res, next); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| editController.username = function (req, res, next) { | editController.username = async function (req, res, next) { | ||||||
| 	renderRoute('username', req, res, next); | 	await renderRoute('username', req, res, next); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| editController.email = function (req, res, next) { | editController.email = async function (req, res, next) { | ||||||
| 	renderRoute('email', req, res, next); | 	await renderRoute('email', req, res, next); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| function renderRoute(name, req, res, next) { | async function renderRoute(name, req, res, next) { | ||||||
| 	async.waterfall([ | 	const userData = await getUserData(req, next); | ||||||
| 		function (next) { |  | ||||||
| 			getUserData(req, next, next); |  | ||||||
| 		}, |  | ||||||
| 		function (userData) { |  | ||||||
| 	if (!userData) { | 	if (!userData) { | ||||||
| 		return next(); | 		return next(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (meta.config[name + ':disableEdit'] && !userData.isAdmin) { | 	if (meta.config[name + ':disableEdit'] && !userData.isAdmin) { | ||||||
| 		return helpers.notAllowed(req, res); | 		return helpers.notAllowed(req, res); | ||||||
| 	} | 	} | ||||||
| @@ -123,90 +100,57 @@ function renderRoute(name, req, res, next) { | |||||||
| 	]); | 	]); | ||||||
|  |  | ||||||
| 	res.render('account/edit/' + name, userData); | 	res.render('account/edit/' + name, userData); | ||||||
| 		}, |  | ||||||
| 	], next); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| function getUserData(req, next, callback) { | async function getUserData(req) { | ||||||
| 	var userData; | 	const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid); | ||||||
| 	async.waterfall([ |  | ||||||
| 		function (next) { |  | ||||||
| 			accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, next); |  | ||||||
| 		}, |  | ||||||
| 		function (data, next) { |  | ||||||
| 			userData = data; |  | ||||||
| 	if (!userData) { | 	if (!userData) { | ||||||
| 				return callback(null, null); | 		return null; | ||||||
| 	} | 	} | ||||||
| 			db.getObjectField('user:' + userData.uid, 'password', next); |  | ||||||
| 		}, | 	userData.hasPassword = await user.hasPassword(userData.uid); | ||||||
| 		function (password, next) { | 	return userData; | ||||||
| 			userData.hasPassword = !!password; |  | ||||||
| 			next(null, userData); |  | ||||||
| 		}, |  | ||||||
| 	], callback); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| editController.uploadPicture = function (req, res, next) { | editController.uploadPicture = async function (req, res, next) { | ||||||
| 	var userPhoto = req.files.files[0]; | 	const userPhoto = req.files.files[0]; | ||||||
|  | 	try { | ||||||
| 	var updateUid; | 		const updateUid = await user.getUidByUserslug(req.params.userslug); | ||||||
|  | 		const isAllowed = await privileges.users.canEdit(req.uid, updateUid); | ||||||
| 	async.waterfall([ |  | ||||||
| 		function (next) { |  | ||||||
| 			user.getUidByUserslug(req.params.userslug, next); |  | ||||||
| 		}, |  | ||||||
| 		function (uid, next) { |  | ||||||
| 			updateUid = uid; |  | ||||||
|  |  | ||||||
| 			privileges.users.canEdit(req.uid, uid, next); |  | ||||||
| 		}, |  | ||||||
| 		function (isAllowed, next) { |  | ||||||
| 		if (!isAllowed) { | 		if (!isAllowed) { | ||||||
| 			return helpers.notAllowed(req, res); | 			return helpers.notAllowed(req, res); | ||||||
| 		} | 		} | ||||||
| 			user.checkMinReputation(req.uid, updateUid, 'min:rep:profile-picture', next); | 		await user.checkMinReputation(req.uid, updateUid, 'min:rep:profile-picture'); | ||||||
| 		}, | 		const image = await user.uploadCroppedPicture({ | ||||||
| 		function (next) { |  | ||||||
| 			user.uploadCroppedPicture({ |  | ||||||
| 			uid: updateUid, | 			uid: updateUid, | ||||||
| 			file: userPhoto, | 			file: userPhoto, | ||||||
| 			}, next); | 		}); | ||||||
| 		}, |  | ||||||
| 	], function (err, image) { |  | ||||||
| 		file.delete(userPhoto.path); |  | ||||||
| 		if (err) { |  | ||||||
| 			return next(err); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		res.json([{ | 		res.json([{ | ||||||
| 			name: userPhoto.name, | 			name: userPhoto.name, | ||||||
| 			url: image.url, | 			url: image.url, | ||||||
| 		}]); | 		}]); | ||||||
| 	}); | 	} catch (err) { | ||||||
|  | 		next(err); | ||||||
|  | 	} finally { | ||||||
|  | 		file.delete(userPhoto.path); | ||||||
|  | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| editController.uploadCoverPicture = function (req, res, next) { | editController.uploadCoverPicture = async function (req, res, next) { | ||||||
| 	var params = JSON.parse(req.body.params); | 	var params = JSON.parse(req.body.params); | ||||||
| 	var coverPhoto = req.files.files[0]; | 	var coverPhoto = req.files.files[0]; | ||||||
|  | 	try { | ||||||
| 	async.waterfall([ | 		await user.checkMinReputation(req.uid, params.uid, 'min:rep:cover-picture'); | ||||||
| 		function (next) { | 		const image = await user.updateCoverPicture({ | ||||||
| 			user.checkMinReputation(req.uid, params.uid, 'min:rep:cover-picture', next); |  | ||||||
| 		}, |  | ||||||
| 		function (next) { |  | ||||||
| 			user.updateCoverPicture({ |  | ||||||
| 			file: coverPhoto, | 			file: coverPhoto, | ||||||
| 			uid: params.uid, | 			uid: params.uid, | ||||||
| 			}, next); | 		}); | ||||||
| 		}, |  | ||||||
| 	], function (err, image) { |  | ||||||
| 		file.delete(coverPhoto.path); |  | ||||||
| 		if (err) { |  | ||||||
| 			return next(err); |  | ||||||
| 		} |  | ||||||
| 		res.json([{ | 		res.json([{ | ||||||
| 			url: image.url, | 			url: image.url, | ||||||
| 		}]); | 		}]); | ||||||
| 	}); | 	} catch (err) { | ||||||
|  | 		next(err); | ||||||
|  | 	} finally { | ||||||
|  | 		file.delete(coverPhoto.path); | ||||||
|  | 	} | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,16 +1,14 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| var async = require('async'); | const user = require('../../user'); | ||||||
|  | const helpers = require('../helpers'); | ||||||
|  | const plugins = require('../../plugins'); | ||||||
|  | const pagination = require('../../pagination'); | ||||||
|  |  | ||||||
| var user = require('../../user'); | const notificationsController = module.exports; | ||||||
| var helpers = require('../helpers'); |  | ||||||
| var plugins = require('../../plugins'); |  | ||||||
| var pagination = require('../../pagination'); |  | ||||||
|  |  | ||||||
| var notificationsController = module.exports; | notificationsController.get = async function (req, res, next) { | ||||||
|  | 	const regularFilters = [ | ||||||
| notificationsController.get = function (req, res, next) { |  | ||||||
| 	var regularFilters = [ |  | ||||||
| 		{ name: '[[notifications:all]]', filter: '' }, | 		{ name: '[[notifications:all]]', filter: '' }, | ||||||
| 		{ name: '[[global:topics]]', filter: 'new-topic' }, | 		{ name: '[[global:topics]]', filter: 'new-topic' }, | ||||||
| 		{ name: '[[notifications:replies]]', filter: 'new-reply' }, | 		{ name: '[[notifications:replies]]', filter: 'new-reply' }, | ||||||
| @@ -19,76 +17,50 @@ notificationsController.get = function (req, res, next) { | |||||||
| 		{ name: '[[notifications:upvote]]', filter: 'upvote' }, | 		{ name: '[[notifications:upvote]]', filter: 'upvote' }, | ||||||
| 	]; | 	]; | ||||||
|  |  | ||||||
| 	var moderatorFilters = [ | 	const moderatorFilters = [ | ||||||
| 		{ name: '[[notifications:new-flags]]', filter: 'new-post-flag' }, | 		{ name: '[[notifications:new-flags]]', filter: 'new-post-flag' }, | ||||||
| 		{ name: '[[notifications:my-flags]]', filter: 'my-flags' }, | 		{ name: '[[notifications:my-flags]]', filter: 'my-flags' }, | ||||||
| 		{ name: '[[notifications:bans]]', filter: 'ban' }, | 		{ name: '[[notifications:bans]]', filter: 'ban' }, | ||||||
| 	]; | 	]; | ||||||
|  |  | ||||||
| 	var filter = req.query.filter || ''; | 	const filter = req.query.filter || ''; | ||||||
| 	var page = Math.max(1, req.query.page || 1); | 	const page = Math.max(1, req.query.page || 1); | ||||||
| 	var itemsPerPage = 20; | 	const itemsPerPage = 20; | ||||||
| 	var start = (page - 1) * itemsPerPage; | 	const start = (page - 1) * itemsPerPage; | ||||||
| 	var stop = start + itemsPerPage - 1; | 	const stop = start + itemsPerPage - 1; | ||||||
| 	var selectedFilter; |  | ||||||
| 	var pageCount = 1; |  | ||||||
| 	var allFilters = []; |  | ||||||
|  |  | ||||||
| 	async.waterfall([ | 	const [filters, isPrivileged] = await Promise.all([ | ||||||
| 		function (next) { |  | ||||||
| 			async.parallel({ |  | ||||||
| 				filters: function (next) { |  | ||||||
| 		plugins.fireHook('filter:notifications.addFilters', { | 		plugins.fireHook('filter:notifications.addFilters', { | ||||||
| 			regularFilters: regularFilters, | 			regularFilters: regularFilters, | ||||||
| 			moderatorFilters: moderatorFilters, | 			moderatorFilters: moderatorFilters, | ||||||
| 			uid: req.uid, | 			uid: req.uid, | ||||||
| 					}, next); | 		}), | ||||||
| 				}, | 		user.isPrivileged(req.uid), | ||||||
| 				isPrivileged: function (next) { | 	]); | ||||||
| 					user.isPrivileged(req.uid, next); |  | ||||||
| 				}, |  | ||||||
| 			}, next); |  | ||||||
| 		}, |  | ||||||
| 		function (data, _next) { |  | ||||||
| 			allFilters = data.filters.regularFilters; |  | ||||||
|  |  | ||||||
| 			if (data.isPrivileged) { | 	let allFilters = filters.regularFilters; | ||||||
|  | 	if (isPrivileged) { | ||||||
| 		allFilters = allFilters.concat([ | 		allFilters = allFilters.concat([ | ||||||
| 			{ separator: true }, | 			{ separator: true }, | ||||||
| 				]).concat(data.filters.moderatorFilters); | 		]).concat(filters.moderatorFilters); | ||||||
| 	} | 	} | ||||||
|  | 	const selectedFilter = allFilters.find(function (filterData) { | ||||||
| 			selectedFilter = allFilters.find(function (filterData) { |  | ||||||
| 		filterData.selected = filterData.filter === filter; | 		filterData.selected = filterData.filter === filter; | ||||||
| 		return filterData.selected; | 		return filterData.selected; | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	if (!selectedFilter) { | 	if (!selectedFilter) { | ||||||
| 		return next(); | 		return next(); | ||||||
| 	} | 	} | ||||||
|  | 	let nids = await user.notifications.getAll(req.uid, selectedFilter.filter); | ||||||
| 			user.notifications.getAll(req.uid, selectedFilter.filter, _next); | 	const pageCount = Math.max(1, Math.ceil(nids.length / itemsPerPage)); | ||||||
| 		}, |  | ||||||
| 		function (nids, next) { |  | ||||||
| 			pageCount = Math.max(1, Math.ceil(nids.length / itemsPerPage)); |  | ||||||
| 	nids = nids.slice(start, stop + 1); | 	nids = nids.slice(start, stop + 1); | ||||||
|  |  | ||||||
| 			user.notifications.getNotifications(nids, req.uid, next); | 	const notifications = await user.notifications.getNotifications(nids, req.uid); | ||||||
| 		}, | 	const data = await plugins.fireHook('filter:notifications.get', { | ||||||
| 		function (notifications, next) { |  | ||||||
| 			plugins.fireHook('filter:notifications.get', { |  | ||||||
| 		notifications: notifications, | 		notifications: notifications, | ||||||
| 			}, function (err, data) { |  | ||||||
| 				if (err) { |  | ||||||
| 					return next(err); |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				next(null, data.notifications); |  | ||||||
| 	}); | 	}); | ||||||
| 		}, |  | ||||||
| 		function (notifications) { |  | ||||||
| 	res.render('notifications', { | 	res.render('notifications', { | ||||||
| 				notifications: notifications, | 		notifications: data.notifications, | ||||||
| 		pagination: pagination.create(page, pageCount, req.query), | 		pagination: pagination.create(page, pageCount, req.query), | ||||||
| 		filters: allFilters, | 		filters: allFilters, | ||||||
| 		regularFilters: regularFilters, | 		regularFilters: regularFilters, | ||||||
| @@ -97,6 +69,4 @@ notificationsController.get = function (req, res, next) { | |||||||
| 		title: '[[pages:notifications]]', | 		title: '[[pages:notifications]]', | ||||||
| 		breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:notifications]]' }]), | 		breadcrumbs: helpers.buildBreadcrumbs([{ text: '[[pages:notifications]]' }]), | ||||||
| 	}); | 	}); | ||||||
| 		}, |  | ||||||
| 	], next); |  | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,23 +1,22 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| var nconf = require('nconf'); | const nconf = require('nconf'); | ||||||
| var async = require('async'); |  | ||||||
|  |  | ||||||
| const db = require('../../database'); | const db = require('../../database'); | ||||||
| var user = require('../../user'); | const user = require('../../user'); | ||||||
| var posts = require('../../posts'); | const posts = require('../../posts'); | ||||||
| const categories = require('../../categories'); | const categories = require('../../categories'); | ||||||
| var plugins = require('../../plugins'); | const plugins = require('../../plugins'); | ||||||
| var meta = require('../../meta'); | const meta = require('../../meta'); | ||||||
| var accountHelpers = require('./helpers'); | const accountHelpers = require('./helpers'); | ||||||
| var helpers = require('../helpers'); | const helpers = require('../helpers'); | ||||||
| var messaging = require('../../messaging'); | const messaging = require('../../messaging'); | ||||||
| var utils = require('../../utils'); | const utils = require('../../utils'); | ||||||
|  |  | ||||||
| var profileController = module.exports; | const profileController = module.exports; | ||||||
|  |  | ||||||
| profileController.get = function (req, res, callback) { | profileController.get = async function (req, res, next) { | ||||||
| 	var lowercaseSlug = req.params.userslug.toLowerCase(); | 	const lowercaseSlug = req.params.userslug.toLowerCase(); | ||||||
|  |  | ||||||
| 	if (req.params.userslug !== lowercaseSlug) { | 	if (req.params.userslug !== lowercaseSlug) { | ||||||
| 		if (res.locals.isAPI) { | 		if (res.locals.isAPI) { | ||||||
| @@ -27,50 +26,28 @@ profileController.get = function (req, res, callback) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var userData; | 	const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid); | ||||||
| 	async.waterfall([ | 	if (!userData) { | ||||||
| 		function (next) { | 		return next(); | ||||||
| 			accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, next); |  | ||||||
| 		}, |  | ||||||
| 		function (_userData, next) { |  | ||||||
| 			if (!_userData) { |  | ||||||
| 				return callback(); |  | ||||||
| 			} |  | ||||||
| 			userData = _userData; |  | ||||||
|  |  | ||||||
| 			if (req.uid >= 0) { |  | ||||||
| 				req.session.uids_viewed = req.session.uids_viewed || {}; |  | ||||||
|  |  | ||||||
| 				if (req.uid !== userData.uid && (!req.session.uids_viewed[userData.uid] || req.session.uids_viewed[userData.uid] < Date.now() - 3600000)) { |  | ||||||
| 					user.incrementUserFieldBy(userData.uid, 'profileviews', 1); |  | ||||||
| 					req.session.uids_viewed[userData.uid] = Date.now(); |  | ||||||
| 				} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			async.parallel({ | 	await incrementProfileViews(req, userData); | ||||||
| 				hasPrivateChat: function (next) { |  | ||||||
| 					messaging.hasPrivateChat(req.uid, userData.uid, next); | 	const [hasPrivateChat, latestPosts, bestPosts] = await Promise.all([ | ||||||
| 				}, | 		messaging.hasPrivateChat(req.uid, userData.uid), | ||||||
| 				latestPosts: function (next) { | 		getLatestPosts(req.uid, userData), | ||||||
| 					getLatestPosts(req.uid, userData, next); | 		getBestPosts(req.uid, userData), | ||||||
| 				}, | 		posts.parseSignature(userData, req.uid), | ||||||
| 				bestPosts: function (next) { | 	]); | ||||||
| 					getBestPosts(req.uid, userData, next); |  | ||||||
| 				}, |  | ||||||
| 				signature: function (next) { |  | ||||||
| 					posts.parseSignature(userData, req.uid, next); |  | ||||||
| 				}, |  | ||||||
| 			}, next); |  | ||||||
| 		}, |  | ||||||
| 		function (results, next) { |  | ||||||
| 	if (meta.config['reputation:disabled']) { | 	if (meta.config['reputation:disabled']) { | ||||||
| 		delete userData.reputation; | 		delete userData.reputation; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			userData.posts = results.latestPosts; // for backwards compat. | 	userData.posts = latestPosts; // for backwards compat. | ||||||
| 			userData.latestPosts = results.latestPosts; | 	userData.latestPosts = latestPosts; | ||||||
| 			userData.bestPosts = results.bestPosts; | 	userData.bestPosts = bestPosts; | ||||||
| 			userData.hasPrivateChat = results.hasPrivateChat; | 	userData.hasPrivateChat = hasPrivateChat; | ||||||
| 	userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username }]); | 	userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username }]); | ||||||
| 	userData.title = userData.username; | 	userData.title = userData.username; | ||||||
| 	userData.allowCoverPicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:cover-picture']; | 	userData.allowCoverPicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:cover-picture']; | ||||||
| @@ -85,39 +62,35 @@ profileController.get = function (req, res, callback) { | |||||||
| 		return group && userData.groupTitleArray.includes(group.name); | 		return group && userData.groupTitleArray.includes(group.name); | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 			plugins.fireHook('filter:user.account', { userData: userData, uid: req.uid }, next); | 	const results = await plugins.fireHook('filter:user.account', { userData: userData, uid: req.uid }); | ||||||
| 		}, |  | ||||||
| 		function (results) { |  | ||||||
| 	res.render('account/profile', results.userData); | 	res.render('account/profile', results.userData); | ||||||
| 		}, |  | ||||||
| 	], callback); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| function getLatestPosts(callerUid, userData, callback) { | async function incrementProfileViews(req, userData) { | ||||||
| 	getPosts(callerUid, userData, 'pids', callback); | 	if (req.uid >= 0) { | ||||||
|  | 		req.session.uids_viewed = req.session.uids_viewed || {}; | ||||||
|  |  | ||||||
|  | 		if (req.uid !== userData.uid && (!req.session.uids_viewed[userData.uid] || req.session.uids_viewed[userData.uid] < Date.now() - 3600000)) { | ||||||
|  | 			await user.incrementUserFieldBy(userData.uid, 'profileviews', 1); | ||||||
|  | 			req.session.uids_viewed[userData.uid] = Date.now(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| function getBestPosts(callerUid, userData, callback) { | async function getLatestPosts(callerUid, userData) { | ||||||
| 	getPosts(callerUid, userData, 'pids:votes', callback); | 	return await getPosts(callerUid, userData, 'pids'); | ||||||
| } | } | ||||||
|  |  | ||||||
| function getPosts(callerUid, userData, setSuffix, callback) { | async function getBestPosts(callerUid, userData) { | ||||||
| 	async.waterfall([ | 	return await getPosts(callerUid, userData, 'pids:votes'); | ||||||
| 		function (next) { | } | ||||||
| 			categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read', next); |  | ||||||
| 		}, | async function getPosts(callerUid, userData, setSuffix) { | ||||||
| 		function (cids, next) { | 	const cids = await categories.getCidsByPrivilege('categories:cid', callerUid, 'topics:read'); | ||||||
| 	const keys = cids.map(c => 'cid:' + c + ':uid:' + userData.uid + ':' + setSuffix); | 	const keys = cids.map(c => 'cid:' + c + ':uid:' + userData.uid + ':' + setSuffix); | ||||||
| 			db.getSortedSetRevRange(keys, 0, 9, next); | 	const pids = await db.getSortedSetRevRange(keys, 0, 9); | ||||||
| 		}, | 	const postData = await posts.getPostSummaryByPids(pids, callerUid, { stripTags: false }); | ||||||
| 		function (pids, next) { | 	return postData.filter(p => p && !p.deleted); | ||||||
| 			posts.getPostSummaryByPids(pids, callerUid, { stripTags: false }, next); |  | ||||||
| 		}, |  | ||||||
| 		function (posts, next) { |  | ||||||
| 			posts = posts.filter(p => p && !p.deleted); |  | ||||||
| 			next(null, posts); |  | ||||||
| 		}, |  | ||||||
| 	], callback); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| function addMetaTags(res, userData) { | function addMetaTags(res, userData) { | ||||||
|   | |||||||
| @@ -1,80 +1,59 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| var async = require('async'); | const util = require('util'); | ||||||
|  |  | ||||||
| var db = require('../../database'); | const db = require('../../database'); | ||||||
| var user = require('../../user'); | const user = require('../../user'); | ||||||
| var helpers = require('../helpers'); | const helpers = require('../helpers'); | ||||||
| var accountHelpers = require('./helpers'); | const accountHelpers = require('./helpers'); | ||||||
|  |  | ||||||
| var sessionController = module.exports; | const sessionController = module.exports; | ||||||
|  |  | ||||||
| sessionController.get = function (req, res, callback) { | sessionController.get = async function (req, res, next) { | ||||||
| 	var userData; | 	const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid); | ||||||
|  |  | ||||||
| 	async.waterfall([ |  | ||||||
| 		function (next) { |  | ||||||
| 			accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, next); |  | ||||||
| 		}, |  | ||||||
| 		function (_userData, next) { |  | ||||||
| 			userData = _userData; |  | ||||||
| 	if (!userData) { | 	if (!userData) { | ||||||
| 				return callback(); | 		return next(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			user.auth.getSessions(userData.uid, req.sessionID, next); | 	userData.sessions = await user.auth.getSessions(userData.uid, req.sessionID); | ||||||
| 		}, |  | ||||||
| 		function (sessions) { |  | ||||||
| 			userData.sessions = sessions; |  | ||||||
|  |  | ||||||
| 	userData.title = '[[pages:account/sessions]]'; | 	userData.title = '[[pages:account/sessions]]'; | ||||||
| 	userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[pages:account/sessions]]' }]); | 	userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[pages:account/sessions]]' }]); | ||||||
|  |  | ||||||
| 	res.render('account/sessions', userData); | 	res.render('account/sessions', userData); | ||||||
| 		}, |  | ||||||
| 	], callback); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| sessionController.revoke = function (req, res, next) { | const getSessionAsync = util.promisify(function (sid, callback) { | ||||||
|  | 	db.sessionStore.get(sid, (err, sessionObj) => callback(err, sessionObj || null)); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | sessionController.revoke = async function (req, res, next) { | ||||||
| 	if (!req.params.hasOwnProperty('uuid')) { | 	if (!req.params.hasOwnProperty('uuid')) { | ||||||
| 		return next(); | 		return next(); | ||||||
| 	} | 	} | ||||||
|  | 	try { | ||||||
| 	var _id; | 		const uid = await user.getUidByUserslug(req.params.userslug); | ||||||
| 	var uid = res.locals.uid; |  | ||||||
| 	async.waterfall([ |  | ||||||
| 		function (next) { |  | ||||||
| 		if (!uid) { | 		if (!uid) { | ||||||
| 				return next(new Error('[[error:no-session-found]]')); | 			throw new Error('[[error:no-session-found]]'); | ||||||
| 			} |  | ||||||
| 			db.getSortedSetRange('uid:' + uid + ':sessions', 0, -1, next); |  | ||||||
| 		}, |  | ||||||
| 		function (sids, done) { |  | ||||||
| 			async.eachSeries(sids, function (sid, next) { |  | ||||||
| 				db.sessionStore.get(sid, function (err, sessionObj) { |  | ||||||
| 					if (err) { |  | ||||||
| 						return next(err); |  | ||||||
| 		} | 		} | ||||||
|  | 		const sids = await db.getSortedSetRange('uid:' + uid + ':sessions', 0, -1); | ||||||
|  | 		let _id; | ||||||
|  | 		for (const sid of sids) { | ||||||
|  | 			/* eslint-disable no-await-in-loop */ | ||||||
|  | 			const sessionObj = await getSessionAsync(sid); | ||||||
| 			if (sessionObj && sessionObj.meta && sessionObj.meta.uuid === req.params.uuid) { | 			if (sessionObj && sessionObj.meta && sessionObj.meta.uuid === req.params.uuid) { | ||||||
| 				_id = sid; | 				_id = sid; | ||||||
| 						done(); | 				break; | ||||||
| 					} else { |  | ||||||
| 						next(); |  | ||||||
| 			} | 			} | ||||||
| 				}); |  | ||||||
| 			}, next); |  | ||||||
| 		}, |  | ||||||
| 		function (next) { |  | ||||||
| 			if (!_id) { |  | ||||||
| 				return next(new Error('[[error:no-session-found]]')); |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 			user.auth.revokeSession(_id, uid, next); | 		if (!_id) { | ||||||
| 		}, | 			throw new Error('[[error:no-session-found]]'); | ||||||
| 	], function (err) { | 		} | ||||||
| 		if (err) { |  | ||||||
|  | 		await user.auth.revokeSession(_id, uid); | ||||||
|  | 	} catch (err) { | ||||||
| 		return res.status(500).send(err.message); | 		return res.status(500).send(err.message); | ||||||
| 	} | 	} | ||||||
| 		return res.sendStatus(200); |  | ||||||
| 	}); | 	res.sendStatus(200); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,110 +1,58 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| var async = require('async'); | const nconf = require('nconf'); | ||||||
| var nconf = require('nconf'); | const winston = require('winston'); | ||||||
| var winston = require('winston'); | const _ = require('lodash'); | ||||||
| var _ = require('lodash'); | const jwt = require('jsonwebtoken'); | ||||||
| var jwt = require('jsonwebtoken'); | const util = require('util'); | ||||||
|  |  | ||||||
| var user = require('../../user'); | const user = require('../../user'); | ||||||
| var languages = require('../../languages'); | const languages = require('../../languages'); | ||||||
| var meta = require('../../meta'); | const meta = require('../../meta'); | ||||||
| var plugins = require('../../plugins'); | const plugins = require('../../plugins'); | ||||||
| var privileges = require('../../privileges'); | const privileges = require('../../privileges'); | ||||||
| var categories = require('../../categories'); | const categories = require('../../categories'); | ||||||
| var notifications = require('../../notifications'); | const notifications = require('../../notifications'); | ||||||
| var db = require('../../database'); | const db = require('../../database'); | ||||||
| var helpers = require('../helpers'); | const helpers = require('../helpers'); | ||||||
| var accountHelpers = require('./helpers'); | const accountHelpers = require('./helpers'); | ||||||
|  |  | ||||||
| var settingsController = module.exports; | const settingsController = module.exports; | ||||||
|  |  | ||||||
| settingsController.get = function (req, res, callback) { | settingsController.get = async function (req, res, next) { | ||||||
| 	var userData; | 	const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid); | ||||||
| 	async.waterfall([ |  | ||||||
| 		function (next) { |  | ||||||
| 			accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, next); |  | ||||||
| 		}, |  | ||||||
| 		function (_userData, next) { |  | ||||||
| 			userData = _userData; |  | ||||||
| 	if (!userData) { | 	if (!userData) { | ||||||
| 				return callback(); | 		return next(); | ||||||
| 	} | 	} | ||||||
| 			async.parallel({ | 	const [settings, languagesData, soundsMapping] = await Promise.all([ | ||||||
| 				settings: function (next) { | 		user.getSettings(userData.uid), | ||||||
| 					user.getSettings(userData.uid, next); | 		languages.list(), | ||||||
| 				}, | 		meta.sounds.getUserSoundMap(userData.uid), | ||||||
| 				languages: function (next) { |  | ||||||
| 					languages.list(next); | 	]); | ||||||
| 				}, |  | ||||||
| 				soundsMapping: function (next) { | 	userData.settings = settings; | ||||||
| 					meta.sounds.getUserSoundMap(userData.uid, next); | 	userData.languages = languagesData; | ||||||
| 				}, |  | ||||||
| 			}, next); |  | ||||||
| 		}, |  | ||||||
| 		function (results, next) { |  | ||||||
| 			userData.settings = results.settings; |  | ||||||
| 			userData.languages = results.languages; |  | ||||||
| 	if (userData.isAdmin && userData.isSelf) { | 	if (userData.isAdmin && userData.isSelf) { | ||||||
| 				userData.acpLanguages = _.cloneDeep(results.languages); | 		userData.acpLanguages = _.cloneDeep(languagesData); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			var types = [ | 	addSoundSettings(userData, soundsMapping); | ||||||
| 				'notification', |  | ||||||
| 				'chat-incoming', |  | ||||||
| 				'chat-outgoing', |  | ||||||
| 			]; |  | ||||||
| 			var aliases = { |  | ||||||
| 				notification: 'notificationSound', |  | ||||||
| 				'chat-incoming': 'incomingChatSound', |  | ||||||
| 				'chat-outgoing': 'outgoingChatSound', |  | ||||||
| 			}; |  | ||||||
|  |  | ||||||
| 			types.forEach(function (type) { | 	const data = await plugins.fireHook('filter:user.customSettings', { | ||||||
| 				var soundpacks = plugins.soundpacks.map(function (pack) { | 		settings: settings, | ||||||
| 					var sounds = Object.keys(pack.sounds).map(function (soundName) { | 		customSettings: [], | ||||||
| 						var value = pack.name + ' | ' + soundName; | 		uid: req.uid, | ||||||
| 						return { |  | ||||||
| 							name: soundName, |  | ||||||
| 							value: value, |  | ||||||
| 							selected: value === results.soundsMapping[type], |  | ||||||
| 						}; |  | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 					return { | 	const [notificationSettings, routes] = await Promise.all([ | ||||||
| 						name: pack.name, | 		getNotificationSettings(userData), | ||||||
| 						sounds: sounds, | 		getHomePageRoutes(userData), | ||||||
| 					}; | 	]); | ||||||
| 				}); |  | ||||||
|  |  | ||||||
| 				userData[type + '-sound'] = soundpacks; |  | ||||||
| 				// fallback |  | ||||||
| 				userData[aliases[type]] = soundpacks.concat.apply([], soundpacks.map(function (pack) { |  | ||||||
| 					return pack.sounds.map(function (sound) { |  | ||||||
| 						return { |  | ||||||
| 							name: sound.value, |  | ||||||
| 							selected: sound.selected, |  | ||||||
| 						}; |  | ||||||
| 					}); |  | ||||||
| 				})); |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 			plugins.fireHook('filter:user.customSettings', { settings: results.settings, customSettings: [], uid: req.uid }, next); |  | ||||||
| 		}, |  | ||||||
| 		function (data, next) { |  | ||||||
| 	userData.customSettings = data.customSettings; | 	userData.customSettings = data.customSettings; | ||||||
| 			async.parallel({ | 	userData.homePageRoutes = routes; | ||||||
| 				notificationSettings: function (next) { | 	userData.notificationSettings = notificationSettings; | ||||||
| 					getNotificationSettings(userData, next); |  | ||||||
| 				}, |  | ||||||
| 				routes: function (next) { |  | ||||||
| 					getHomePageRoutes(userData, next); |  | ||||||
| 				}, |  | ||||||
| 			}, next); |  | ||||||
| 		}, |  | ||||||
| 		function (results) { |  | ||||||
| 			userData.homePageRoutes = results.routes; |  | ||||||
| 			userData.notificationSettings = results.notificationSettings; |  | ||||||
| 	userData.disableEmailSubscriptions = meta.config.disableEmailSubscriptions; | 	userData.disableEmailSubscriptions = meta.config.disableEmailSubscriptions; | ||||||
|  |  | ||||||
| 	userData.dailyDigestFreqOptions = [ | 	userData.dailyDigestFreqOptions = [ | ||||||
| @@ -148,7 +96,7 @@ settingsController.get = function (req, res, callback) { | |||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			var notifFreqOptions = [ | 	const notifFreqOptions = [ | ||||||
| 		'all', | 		'all', | ||||||
| 		'first', | 		'first', | ||||||
| 		'everyTen', | 		'everyTen', | ||||||
| @@ -157,12 +105,7 @@ settingsController.get = function (req, res, callback) { | |||||||
| 		'disabled', | 		'disabled', | ||||||
| 	]; | 	]; | ||||||
|  |  | ||||||
| 			userData.upvoteNotifFreq = notifFreqOptions.map(function (name) { | 	userData.upvoteNotifFreq = notifFreqOptions.map(name => ({ name: name, selected: name === userData.settings.upvoteNotifFreq })); | ||||||
| 				return { |  | ||||||
| 					name: name, |  | ||||||
| 					selected: name === userData.settings.upvoteNotifFreq, |  | ||||||
| 				}; |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 	userData.categoryWatchState = { [userData.settings.categoryWatchState]: true }; | 	userData.categoryWatchState = { [userData.settings.categoryWatchState]: true }; | ||||||
|  |  | ||||||
| @@ -182,64 +125,88 @@ settingsController.get = function (req, res, callback) { | |||||||
| 	userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[user:settings]]' }]); | 	userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[user:settings]]' }]); | ||||||
|  |  | ||||||
| 	res.render('account/settings', userData); | 	res.render('account/settings', userData); | ||||||
| 		}, |  | ||||||
| 	], callback); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| settingsController.unsubscribe = function (req, res) { | function addSoundSettings(userData, soundsMapping) { | ||||||
|  | 	const types = [ | ||||||
|  | 		'notification', | ||||||
|  | 		'chat-incoming', | ||||||
|  | 		'chat-outgoing', | ||||||
|  | 	]; | ||||||
|  | 	const aliases = { | ||||||
|  | 		notification: 'notificationSound', | ||||||
|  | 		'chat-incoming': 'incomingChatSound', | ||||||
|  | 		'chat-outgoing': 'outgoingChatSound', | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	types.forEach(function (type) { | ||||||
|  | 		const soundpacks = plugins.soundpacks.map(function (pack) { | ||||||
|  | 			const sounds = Object.keys(pack.sounds).map(function (soundName) { | ||||||
|  | 				const value = pack.name + ' | ' + soundName; | ||||||
|  | 				return { | ||||||
|  | 					name: soundName, | ||||||
|  | 					value: value, | ||||||
|  | 					selected: value === soundsMapping[type], | ||||||
|  | 				}; | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  | 			return { | ||||||
|  | 				name: pack.name, | ||||||
|  | 				sounds: sounds, | ||||||
|  | 			}; | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		userData[type + '-sound'] = soundpacks; | ||||||
|  | 		// fallback | ||||||
|  | 		userData[aliases[type]] = soundpacks.concat.apply([], soundpacks.map(function (pack) { | ||||||
|  | 			return pack.sounds.map(function (sound) { | ||||||
|  | 				return { | ||||||
|  | 					name: sound.value, | ||||||
|  | 					selected: sound.selected, | ||||||
|  | 				}; | ||||||
|  | 			}); | ||||||
|  | 		})); | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const jwtVerifyAsync = util.promisify(function (token, callback) { | ||||||
|  | 	jwt.verify(token, nconf.get('secret'), (err, payload) => callback(err, payload)); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | settingsController.unsubscribe = async function (req, res) { | ||||||
| 	if (!req.params.token) { | 	if (!req.params.token) { | ||||||
| 		return res.sendStatus(404); | 		return res.sendStatus(404); | ||||||
| 	} | 	} | ||||||
|  | 	let payload; | ||||||
| 	jwt.verify(req.params.token, nconf.get('secret'), function (err, payload) { | 	try { | ||||||
| 		if (err) { | 		payload = await jwtVerifyAsync(req.params.token); | ||||||
|  | 		if (!payload || (payload.template !== 'notification' && payload.template !== 'digest')) { | ||||||
|  | 			return res.sendStatus(404); | ||||||
|  | 		} | ||||||
|  | 	} catch (err) { | ||||||
| 		return res.sendStatus(403); | 		return res.sendStatus(403); | ||||||
| 	} | 	} | ||||||
|  | 	try { | ||||||
| 		switch (payload.template) { | 		if (payload.template === 'digest') { | ||||||
| 		case 'digest': | 			await Promise.all([ | ||||||
| 			async.parallel([ | 				user.setSetting(payload.uid, 'dailyDigestFreq', 'off'), | ||||||
| 				async.apply(user.setSetting, payload.uid, 'dailyDigestFreq', 'off'), | 				user.updateDigestSetting(payload.uid, 'off'), | ||||||
| 				async.apply(user.updateDigestSetting, payload.uid, 'off'), | 			]); | ||||||
| 			], function (err) { | 		} else if (payload.template === 'notification') { | ||||||
| 				if (err) { | 			const current = await db.getObjectField('user:' + payload.uid + ':settings', 'notificationType_' + payload.type); | ||||||
|  | 			await user.setSetting(payload.uid, 'notificationType_' + payload.type, (current === 'notificationemail' ? 'notification' : 'none')); | ||||||
|  | 		} | ||||||
|  | 		res.sendStatus(200); | ||||||
|  | 	} catch (err) { | ||||||
| 		winston.error('[settings/unsubscribe] One-click unsubscribe failed with error: ' + err.message); | 		winston.error('[settings/unsubscribe] One-click unsubscribe failed with error: ' + err.message); | ||||||
| 					return res.sendStatus(500); | 		res.sendStatus(500); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 				return res.sendStatus(200); |  | ||||||
| 			}); |  | ||||||
| 			break; |  | ||||||
| 		case 'notification': |  | ||||||
| 			async.waterfall([ |  | ||||||
| 				async.apply(db.getObjectField, 'user:' + payload.uid + ':settings', 'notificationType_' + payload.type), |  | ||||||
| 				(current, next) => { |  | ||||||
| 					user.setSetting(payload.uid, 'notificationType_' + payload.type, (current === 'notificationemail' ? 'notification' : 'none'), next); |  | ||||||
| 				}, |  | ||||||
| 			], function (err) { |  | ||||||
| 				if (err) { |  | ||||||
| 					winston.error('[settings/unsubscribe] One-click unsubscribe failed with error: ' + err.message); |  | ||||||
| 					return res.sendStatus(500); |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				return res.sendStatus(200); |  | ||||||
| 			}); |  | ||||||
| 			break; |  | ||||||
| 		default: |  | ||||||
| 			res.sendStatus(404); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| function getNotificationSettings(userData, callback) { | async function getNotificationSettings(userData) { | ||||||
| 	var privilegedTypes = []; | 	const privilegedTypes = []; | ||||||
|  |  | ||||||
| 	async.waterfall([ | 	const privileges = await user.getPrivileges(userData.uid); | ||||||
| 		function (next) { |  | ||||||
| 			user.getPrivileges(userData.uid, next); |  | ||||||
| 		}, |  | ||||||
| 		function (privileges, next) { |  | ||||||
| 	if (privileges.isAdmin) { | 	if (privileges.isAdmin) { | ||||||
| 		privilegedTypes.push('notificationType_new-register'); | 		privilegedTypes.push('notificationType_new-register'); | ||||||
| 	} | 	} | ||||||
| @@ -249,15 +216,13 @@ function getNotificationSettings(userData, callback) { | |||||||
| 	if (privileges.isAdmin || privileges.isGlobalMod) { | 	if (privileges.isAdmin || privileges.isGlobalMod) { | ||||||
| 		privilegedTypes.push('notificationType_new-user-flag'); | 		privilegedTypes.push('notificationType_new-user-flag'); | ||||||
| 	} | 	} | ||||||
| 			plugins.fireHook('filter:user.notificationTypes', { | 	const results = await plugins.fireHook('filter:user.notificationTypes', { | ||||||
| 		types: notifications.baseTypes.slice(), | 		types: notifications.baseTypes.slice(), | ||||||
| 		privilegedTypes: privilegedTypes, | 		privilegedTypes: privilegedTypes, | ||||||
| 			}, next); | 	}); | ||||||
| 		}, |  | ||||||
| 		function (results, next) { |  | ||||||
| 			function modifyType(type) { |  | ||||||
| 				var setting = userData.settings[type]; |  | ||||||
|  |  | ||||||
|  | 	function modifyType(type) { | ||||||
|  | 		const setting = userData.settings[type]; | ||||||
| 		return { | 		return { | ||||||
| 			name: type, | 			name: type, | ||||||
| 			label: '[[notifications:' + type + ']]', | 			label: '[[notifications:' + type + ']]', | ||||||
| @@ -272,24 +237,14 @@ function getNotificationSettings(userData, callback) { | |||||||
| 		results.types = results.types.filter(type => type !== 'notificationType_new-chat'); | 		results.types = results.types.filter(type => type !== 'notificationType_new-chat'); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			var notificationSettings = results.types.map(modifyType).concat(results.privilegedTypes.map(modifyType)); | 	return results.types.map(modifyType).concat(results.privilegedTypes.map(modifyType)); | ||||||
| 			next(null, notificationSettings); |  | ||||||
| 		}, |  | ||||||
| 	], callback); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| function getHomePageRoutes(userData, callback) { | async function getHomePageRoutes(userData) { | ||||||
| 	async.waterfall([ | 	let cids = await categories.getAllCidsFromSet('cid:0:children'); | ||||||
| 		function (next) { | 	cids = await privileges.categories.filterCids('find', cids, userData.uid); | ||||||
| 			db.getSortedSetRange('cid:0:children', 0, -1, next); | 	let categoryData = await categories.getCategoriesFields(cids, ['name', 'slug']); | ||||||
| 		}, |  | ||||||
| 		function (cids, next) { |  | ||||||
| 			privileges.categories.filterCids('find', cids, 0, next); |  | ||||||
| 		}, |  | ||||||
| 		function (cids, next) { |  | ||||||
| 			categories.getCategoriesFields(cids, ['name', 'slug'], next); |  | ||||||
| 		}, |  | ||||||
| 		function (categoryData, next) { |  | ||||||
| 	categoryData = categoryData.map(function (category) { | 	categoryData = categoryData.map(function (category) { | ||||||
| 		return { | 		return { | ||||||
| 			route: 'category/' + category.slug, | 			route: 'category/' + category.slug, | ||||||
| @@ -297,9 +252,7 @@ function getHomePageRoutes(userData, callback) { | |||||||
| 		}; | 		}; | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 			categoryData = categoryData || []; | 	const data = await plugins.fireHook('filter:homepage.get', { routes: [ | ||||||
|  |  | ||||||
| 			plugins.fireHook('filter:homepage.get', { routes: [ |  | ||||||
| 		{ | 		{ | ||||||
| 			route: 'categories', | 			route: 'categories', | ||||||
| 			name: 'Categories', | 			name: 'Categories', | ||||||
| @@ -325,9 +278,8 @@ function getHomePageRoutes(userData, callback) { | |||||||
| 			route: 'custom', | 			route: 'custom', | ||||||
| 			name: 'Custom', | 			name: 'Custom', | ||||||
| 		}, | 		}, | ||||||
| 			]) }, next); | 	]) }); | ||||||
| 		}, |  | ||||||
| 		function (data, next) { |  | ||||||
| 	// Set selected for each route | 	// Set selected for each route | ||||||
| 	var customIdx; | 	var customIdx; | ||||||
| 	var hasSelected = false; | 	var hasSelected = false; | ||||||
| @@ -350,7 +302,5 @@ function getHomePageRoutes(userData, callback) { | |||||||
| 		data.routes[customIdx].selected = true; | 		data.routes[customIdx].selected = true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			next(null, data.routes); | 	return data.routes; | ||||||
| 		}, |  | ||||||
| 	], callback); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,57 +1,40 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
|  | const nconf = require('nconf'); | ||||||
|  |  | ||||||
| var async = require('async'); | const db = require('../../database'); | ||||||
| var nconf = require('nconf'); | const helpers = require('../helpers'); | ||||||
|  | const meta = require('../../meta'); | ||||||
|  | const pagination = require('../../pagination'); | ||||||
|  | const accountHelpers = require('./helpers'); | ||||||
|  |  | ||||||
| var db = require('../../database'); | const uploadsController = module.exports; | ||||||
| var helpers = require('../helpers'); |  | ||||||
| var meta = require('../../meta'); |  | ||||||
| var pagination = require('../../pagination'); |  | ||||||
| var accountHelpers = require('./helpers'); |  | ||||||
|  |  | ||||||
| var uploadsController = module.exports; | uploadsController.get = async function (req, res, next) { | ||||||
|  | 	const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid); | ||||||
| uploadsController.get = function (req, res, callback) { |  | ||||||
| 	var userData; |  | ||||||
|  |  | ||||||
| 	var page = Math.max(1, parseInt(req.query.page, 10) || 1); |  | ||||||
| 	var itemsPerPage = 25; |  | ||||||
|  |  | ||||||
| 	async.waterfall([ |  | ||||||
| 		function (next) { |  | ||||||
| 			accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, next); |  | ||||||
| 		}, |  | ||||||
| 		function (_userData, next) { |  | ||||||
| 			userData = _userData; |  | ||||||
| 	if (!userData) { | 	if (!userData) { | ||||||
| 				return callback(); | 		return next(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 			var start = (page - 1) * itemsPerPage; | 	const page = Math.max(1, parseInt(req.query.page, 10) || 1); | ||||||
| 			var stop = start + itemsPerPage - 1; | 	const itemsPerPage = 25; | ||||||
| 			async.parallel({ | 	const start = (page - 1) * itemsPerPage; | ||||||
| 				itemCount: function (next) { | 	const stop = start + itemsPerPage - 1; | ||||||
| 					db.sortedSetCard('uid:' + userData.uid + ':uploads', next); | 	const [itemCount, uploadNames] = await Promise.all([ | ||||||
| 				}, | 		db.sortedSetCard('uid:' + userData.uid + ':uploads'), | ||||||
| 				uploadNames: function (next) { | 		db.getSortedSetRevRange('uid:' + userData.uid + ':uploads', start, stop), | ||||||
| 					db.getSortedSetRevRange('uid:' + userData.uid + ':uploads', start, stop, next); | 	]); | ||||||
| 				}, |  | ||||||
| 			}, next); | 	userData.uploads = uploadNames.map(function (uploadName) { | ||||||
| 		}, |  | ||||||
| 		function (results) { |  | ||||||
| 			userData.uploads = results.uploadNames.map(function (uploadName) { |  | ||||||
| 		return { | 		return { | ||||||
| 			name: uploadName, | 			name: uploadName, | ||||||
| 			url: nconf.get('upload_url') + uploadName, | 			url: nconf.get('upload_url') + uploadName, | ||||||
| 		}; | 		}; | ||||||
| 	}); | 	}); | ||||||
| 			var pageCount = Math.ceil(results.itemCount / itemsPerPage); | 	const pageCount = Math.ceil(itemCount / itemsPerPage); | ||||||
| 	userData.pagination = pagination.create(page, pageCount, req.query); | 	userData.pagination = pagination.create(page, pageCount, req.query); | ||||||
| 	userData.privateUploads = meta.config.privateUploads === 1; | 	userData.privateUploads = meta.config.privateUploads === 1; | ||||||
| 	userData.title = '[[pages:account/uploads, ' + userData.username + ']]'; | 	userData.title = '[[pages:account/uploads, ' + userData.username + ']]'; | ||||||
| 	userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[global:uploads]]' }]); | 	userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[global:uploads]]' }]); | ||||||
| 	res.render('account/uploads', userData); | 	res.render('account/uploads', userData); | ||||||
| 		}, |  | ||||||
| 	], callback); |  | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -7,6 +7,9 @@ const utils = require('../utils'); | |||||||
| module.exports = function (Plugins) { | module.exports = function (Plugins) { | ||||||
| 	Plugins.deprecatedHooks = { | 	Plugins.deprecatedHooks = { | ||||||
| 		'filter:controllers.topic.get': 'filter:topic.build', | 		'filter:controllers.topic.get': 'filter:topic.build', | ||||||
|  | 		'filter:user.account': 'filter:account/profile.build', | ||||||
|  | 		'filter:user.account.edit': 'filter:account/edit.build', | ||||||
|  | 		'filter:notifications.get': 'filter:notifications.build', | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Plugins.internals = { | 	Plugins.internals = { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user