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