From 44ea9da022d8c02c0f1c8edc97959f7736c2c31e Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Tue, 24 Jan 2023 21:35:09 -0500 Subject: [PATCH] refactor: remove calls to getUserDataByUserSlug for most account routes, since it is populated via middleware now --- src/controllers/accounts/blocks.js | 2 +- src/controllers/accounts/edit.js | 111 ++++++++++++++------------- src/controllers/accounts/follow.js | 21 +++-- src/controllers/accounts/groups.js | 22 +++--- src/controllers/accounts/info.js | 51 ++++++------ src/controllers/accounts/posts.js | 36 ++++----- src/controllers/accounts/sessions.js | 18 ++--- src/controllers/accounts/uploads.js | 28 ++++--- src/socket.io/topics/unread.js | 1 - 9 files changed, 141 insertions(+), 149 deletions(-) diff --git a/src/controllers/accounts/blocks.js b/src/controllers/accounts/blocks.js index c181dd6726..a3f6cba3ff 100644 --- a/src/controllers/accounts/blocks.js +++ b/src/controllers/accounts/blocks.js @@ -7,7 +7,7 @@ const plugins = require('../../plugins'); const blocksController = module.exports; -blocksController.getBlocks = async function (req, res, next) { +blocksController.getBlocks = async function (req, res) { const page = parseInt(req.query.page, 10) || 1; const resultsPerPage = 50; const start = Math.max(0, page - 1) * resultsPerPage; diff --git a/src/controllers/accounts/edit.js b/src/controllers/accounts/edit.js index 7a1e5489bc..2009ff98f9 100644 --- a/src/controllers/accounts/edit.js +++ b/src/controllers/accounts/edit.js @@ -4,40 +4,47 @@ const user = require('../../user'); const meta = require('../../meta'); const helpers = require('../helpers'); const groups = require('../../groups'); -const accountHelpers = require('./helpers'); const privileges = require('../../privileges'); +const accountHelpers = require('./helpers'); const file = require('../../file'); const editController = module.exports; -editController.get = async function (req, res, next) { - const [userData, canUseSignature] = await Promise.all([ +editController.get = async function (req, res) { + const [{ + username, + userslug, + isSelf, + reputation, + groups: _groups, + groupTitleArray, + allowMultipleBadges, + }, canUseSignature] = await Promise.all([ accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query), privileges.global.can('signature', req.uid), ]); - if (!userData) { - return next(); - } - userData.maximumSignatureLength = meta.config.maximumSignatureLength; - userData.maximumAboutMeLength = meta.config.maximumAboutMeLength; - userData.maximumProfileImageSize = meta.config.maximumProfileImageSize; - userData.allowMultipleBadges = meta.config.allowMultipleBadges === 1; - 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 = 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(g => g && g.userTitleEnabled && !groups.isPrivilegeGroup(g.name) && g.name !== 'registered-users'); + const payload = {}; + payload.maximumSignatureLength = meta.config.maximumSignatureLength; + payload.maximumAboutMeLength = meta.config.maximumAboutMeLength; + payload.maximumProfileImageSize = meta.config.maximumProfileImageSize; + payload.allowMultipleBadges = meta.config.allowMultipleBadges === 1; + payload.allowAccountDelete = meta.config.allowAccountDelete === 1; + payload.allowWebsite = !isSelf || !!meta.config['reputation:disabled'] || reputation >= meta.config['min:rep:website']; + payload.allowAboutMe = !isSelf || !!meta.config['reputation:disabled'] || reputation >= meta.config['min:rep:aboutme']; + payload.allowSignature = canUseSignature && (!isSelf || !!meta.config['reputation:disabled'] || reputation >= meta.config['min:rep:signature']); + payload.profileImageDimension = meta.config.profileImageDimension; + payload.defaultAvatar = user.getDefaultAvatar(); - if (!userData.allowMultipleBadges) { - userData.groupTitle = userData.groupTitleArray[0]; + payload.groups = _groups.filter(g => g && g.userTitleEnabled && !groups.isPrivilegeGroup(g.name) && g.name !== 'registered-users'); + + if (!allowMultipleBadges) { + payload.groupTitle = groupTitleArray[0]; } - userData.groups.sort((a, b) => { - const i1 = userData.groupTitleArray.indexOf(a.name); - const i2 = userData.groupTitleArray.indexOf(b.name); + payload.groups.sort((a, b) => { + const i1 = groupTitleArray.indexOf(a.name); + const i2 = groupTitleArray.indexOf(b.name); if (i1 === -1) { return 1; } else if (i2 === -1) { @@ -45,24 +52,25 @@ editController.get = async function (req, res, next) { } return i1 - i2; }); - userData.groups.forEach((group) => { + payload.groups.forEach((group) => { group.userTitle = group.userTitle || group.displayName; - group.selected = userData.groupTitleArray.includes(group.name); + group.selected = groupTitleArray.includes(group.name); }); - userData.groupSelectSize = Math.min(10, Math.max(5, userData.groups.length + 1)); + payload.groupSelectSize = Math.min(10, Math.max(5, payload.groups.length + 1)); - userData.title = `[[pages:account/edit, ${userData.username}]]`; - userData.breadcrumbs = helpers.buildBreadcrumbs([ + payload.title = `[[pages:account/edit, ${username}]]`; + payload.breadcrumbs = helpers.buildBreadcrumbs([ { - text: userData.username, - url: `/user/${userData.userslug}`, + text: username, + url: `/user/${userslug}`, }, { text: '[[user:edit]]', }, ]); - userData.editButtons = []; - res.render('account/edit', userData); + payload.editButtons = []; + + res.render('account/edit', payload); }; editController.password = async function (req, res, next) { @@ -95,46 +103,39 @@ editController.email = async function (req, res, next) { helpers.redirect(res, '/register/complete'); }; -async function renderRoute(name, req, res, next) { - const userData = await getUserData(req, next); - if (!userData) { - return next(); - } - if (meta.config[`${name}:disableEdit`] && !userData.isAdmin) { +async function renderRoute(name, req, res) { + const [isAdmin, { username, userslug }, hasPassword] = await Promise.all([ + privileges.admin.can('admin:users', res.locals.uid), + user.getUserFields(res.locals.uid, ['username', 'userslug']), + user.hasPassword(res.locals.uid), + ]); + + if (meta.config[`${name}:disableEdit`] && !isAdmin) { return helpers.notAllowed(req, res); } + const payload = { hasPassword }; if (name === 'password') { - userData.minimumPasswordLength = meta.config.minimumPasswordLength; - userData.minimumPasswordStrength = meta.config.minimumPasswordStrength; + payload.minimumPasswordLength = meta.config.minimumPasswordLength; + payload.minimumPasswordStrength = meta.config.minimumPasswordStrength; } - userData.title = `[[pages:account/edit/${name}, ${userData.username}]]`; - userData.breadcrumbs = helpers.buildBreadcrumbs([ + payload.title = `[[pages:account/edit/${name}, ${username}]]`; + payload.breadcrumbs = helpers.buildBreadcrumbs([ { - text: userData.username, - url: `/user/${userData.userslug}`, + text: username, + url: `/user/${userslug}`, }, { text: '[[user:edit]]', - url: `/user/${userData.userslug}/edit`, + url: `/user/${userslug}/edit`, }, { text: `[[user:${name}]]`, }, ]); - res.render(`account/edit/${name}`, userData); -} - -async function getUserData(req) { - const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query); - if (!userData) { - return null; - } - - userData.hasPassword = await user.hasPassword(userData.uid); - return userData; + res.render(`account/edit/${name}`, payload); } editController.uploadPicture = async function (req, res, next) { diff --git a/src/controllers/accounts/follow.js b/src/controllers/accounts/follow.js index 82b23cb2f9..b573418aad 100644 --- a/src/controllers/accounts/follow.js +++ b/src/controllers/accounts/follow.js @@ -2,7 +2,6 @@ const user = require('../../user'); const helpers = require('../helpers'); -const accountHelpers = require('./helpers'); const pagination = require('../../pagination'); const followController = module.exports; @@ -15,27 +14,25 @@ followController.getFollowers = async function (req, res, next) { await getFollow('account/followers', 'followers', req, res, next); }; -async function getFollow(tpl, name, req, res, next) { - const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query); - if (!userData) { - return next(); - } +async function getFollow(tpl, name, req, res) { + const { username, userslug, followerCount, followingCount } = await user.getUserFields(res.locals.uid, ['username', 'userslug']); const page = parseInt(req.query.page, 10) || 1; const resultsPerPage = 50; const start = Math.max(0, page - 1) * resultsPerPage; const stop = start + resultsPerPage - 1; - userData.title = `[[pages:${tpl}, ${userData.username}]]`; + const payload = {}; + payload.title = `[[pages:${tpl}, ${username}]]`; const method = name === 'following' ? 'getFollowing' : 'getFollowers'; - userData.users = await user[method](userData.uid, start, stop); + payload.users = await user[method](res.locals.uid, start, stop); - const count = name === 'following' ? userData.followingCount : userData.followerCount; + const count = name === 'following' ? followingCount : followerCount; const pageCount = Math.ceil(count / resultsPerPage); - userData.pagination = pagination.create(page, pageCount); + payload.pagination = pagination.create(page, pageCount); - userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: `[[user:${name}]]` }]); + payload.breadcrumbs = helpers.buildBreadcrumbs([{ text: username, url: `/user/${userslug}` }, { text: `[[user:${name}]]` }]); - res.render(tpl, userData); + res.render(tpl, payload); } diff --git a/src/controllers/accounts/groups.js b/src/controllers/accounts/groups.js index 7d2f03cbf3..27c0797afe 100644 --- a/src/controllers/accounts/groups.js +++ b/src/controllers/accounts/groups.js @@ -1,25 +1,25 @@ 'use strict'; +const user = require('../../user'); const groups = require('../../groups'); const helpers = require('../helpers'); -const accountHelpers = require('./helpers'); const groupsController = module.exports; -groupsController.get = async function (req, res, next) { - const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query); - if (!userData) { - return next(); - } - let groupsData = await groups.getUserGroups([userData.uid]); +groupsController.get = async function (req, res) { + const { username, userslug } = await user.getUserFields(res.locals.uid, ['username', 'userslug']); + + const payload = {}; + + let groupsData = await groups.getUserGroups([res.locals.uid]); groupsData = groupsData[0]; const groupNames = groupsData.filter(Boolean).map(group => group.name); const members = await groups.getMemberUsers(groupNames, 0, 3); groupsData.forEach((group, index) => { group.members = members[index]; }); - userData.groups = groupsData; - userData.title = `[[pages:account/groups, ${userData.username}]]`; - userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[global:header.groups]]' }]); - res.render('account/groups', userData); + payload.groups = groupsData; + payload.title = `[[pages:account/groups, ${username}]]`; + payload.breadcrumbs = helpers.buildBreadcrumbs([{ text: username, url: `/user/${userslug}` }, { text: '[[global:header.groups]]' }]); + res.render('account/groups', payload); }; diff --git a/src/controllers/accounts/info.js b/src/controllers/accounts/info.js index 950b74945d..2b60ba9212 100644 --- a/src/controllers/accounts/info.js +++ b/src/controllers/accounts/info.js @@ -3,52 +3,53 @@ const db = require('../../database'); const user = require('../../user'); const helpers = require('../helpers'); -const accountHelpers = require('./helpers'); const pagination = require('../../pagination'); const infoController = module.exports; -infoController.get = async function (req, res, next) { - const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query); - if (!userData) { - return next(); - } +infoController.get = async function (req, res) { const page = Math.max(1, req.query.page || 1); const itemsPerPage = 10; const start = (page - 1) * itemsPerPage; const stop = start + itemsPerPage - 1; + const [{ username, userslug }, isPrivileged] = await Promise.all([ + user.getUserFields(res.locals.uid, ['username', 'userslug']), + user.isPrivileged(res.locals.uid), + ]); const [history, sessions, usernames, emails, notes] = await Promise.all([ - user.getModerationHistory(userData.uid), - user.auth.getSessions(userData.uid, req.sessionID), - user.getHistory(`user:${userData.uid}:usernames`), - user.getHistory(`user:${userData.uid}:emails`), - getNotes(userData, start, stop), + user.getModerationHistory(res.locals.uid), + user.auth.getSessions(res.locals.uid, req.sessionID), + user.getHistory(`user:${res.locals.uid}:usernames`), + user.getHistory(`user:${res.locals.uid}:emails`), + getNotes({ uid: res.locals.uid, isPrivileged }, start, stop), ]); - userData.history = history; - userData.sessions = sessions; - userData.usernames = usernames; - userData.emails = emails; + const payload = {}; - if (userData.isAdminOrGlobalModeratorOrModerator) { - userData.moderationNotes = notes.notes; + payload.history = history; + payload.sessions = sessions; + payload.usernames = usernames; + payload.emails = emails; + + if (isPrivileged) { + payload.moderationNotes = notes.notes; const pageCount = Math.ceil(notes.count / itemsPerPage); - userData.pagination = pagination.create(page, pageCount, req.query); + payload.pagination = pagination.create(page, pageCount, req.query); } - userData.title = '[[pages:account/info]]'; - userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: '[[user:account_info]]' }]); + payload.title = '[[pages:account/info]]'; + payload.breadcrumbs = helpers.buildBreadcrumbs([{ text: username, url: `/user/${userslug}` }, { text: '[[user:account_info]]' }]); - res.render('account/info', userData); + res.render('account/info', payload); }; -async function getNotes(userData, start, stop) { - if (!userData.isAdminOrGlobalModeratorOrModerator) { +async function getNotes({ uid, isPrivileged }, start, stop) { + if (!isPrivileged) { return; } const [notes, count] = await Promise.all([ - user.getModerationNotes(userData.uid, start, stop), - db.sortedSetCard(`uid:${userData.uid}:moderation:notes`), + user.getModerationNotes(uid, start, stop), + db.sortedSetCard(`uid:${uid}:moderation:notes`), ]); return { notes: notes, count: count }; } diff --git a/src/controllers/accounts/posts.js b/src/controllers/accounts/posts.js index 94bc2d9169..b1ac6a4250 100644 --- a/src/controllers/accounts/posts.js +++ b/src/controllers/accounts/posts.js @@ -8,7 +8,6 @@ const categories = require('../../categories'); const privileges = require('../../privileges'); const pagination = require('../../pagination'); const helpers = require('../helpers'); -const accountHelpers = require('./helpers'); const plugins = require('../../plugins'); const utils = require('../../utils'); @@ -174,28 +173,25 @@ postsController.getTopics = async function (req, res, next) { await getPostsFromUserSet('account/topics', req, res, next); }; -async function getPostsFromUserSet(template, req, res, next) { +async function getPostsFromUserSet(template, req, res) { const data = templateToData[template]; const page = Math.max(1, parseInt(req.query.page, 10) || 1); - const [userData, settings] = await Promise.all([ - accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query), + const [{ username, userslug }, settings] = await Promise.all([ + user.getUserFields(res.locals.uid, ['username', 'userslug']), user.getSettings(req.uid), ]); - if (!userData) { - return next(); - } const itemsPerPage = data.type === 'topics' ? settings.topicsPerPage : settings.postsPerPage; const start = (page - 1) * itemsPerPage; const stop = start + itemsPerPage - 1; - const sets = await data.getSets(req.uid, userData); + const sets = await data.getSets(req.uid, { uid: res.locals.uid, username, userslug }); let result; if (plugins.hooks.hasListeners('filter:account.getPostsFromUserSet')) { result = await plugins.hooks.fire('filter:account.getPostsFromUserSet', { req: req, template: template, - userData: userData, + userData: { uid: res.locals.uid, username, userslug }, settings: settings, data: data, start: start, @@ -210,29 +206,31 @@ async function getPostsFromUserSet(template, req, res, next) { }); } const { itemCount, itemData } = result; - userData[data.type] = itemData[data.type]; - userData.nextStart = itemData.nextStart; + + const payload = {}; + payload[data.type] = itemData[data.type]; + payload.nextStart = itemData.nextStart; const pageCount = Math.ceil(itemCount / itemsPerPage); - userData.pagination = pagination.create(page, pageCount, req.query); + payload.pagination = pagination.create(page, pageCount, req.query); - userData.noItemsFoundKey = data.noItemsFoundKey; - userData.title = `[[pages:${template}, ${userData.username}]]`; - userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: `/user/${userData.userslug}` }, { text: data.crumb }]); - userData.showSort = template === 'account/watched'; + payload.noItemsFoundKey = data.noItemsFoundKey; + payload.title = `[[pages:${template}, ${username}]]`; + payload.breadcrumbs = helpers.buildBreadcrumbs([{ text: username, url: `/user/${userslug}` }, { text: data.crumb }]); + payload.showSort = template === 'account/watched'; const baseUrl = (req.baseUrl + req.path.replace(/^\/api/, '')); - userData.sortOptions = [ + payload.sortOptions = [ { url: `${baseUrl}?sort=votes`, name: '[[global:votes]]' }, { url: `${baseUrl}?sort=posts`, name: '[[global:posts]]' }, { url: `${baseUrl}?sort=views`, name: '[[global:views]]' }, { url: `${baseUrl}?sort=lastpost`, name: '[[global:lastpost]]' }, { url: `${baseUrl}?sort=firstpost`, name: '[[global:firstpost]]' }, ]; - userData.sortOptions.forEach((option) => { + payload.sortOptions.forEach((option) => { option.selected = option.url.includes(`sort=${req.query.sort}`); }); - res.render(template, userData); + res.render(template, payload); } async function getItemData(sets, data, req, start, stop) { diff --git a/src/controllers/accounts/sessions.js b/src/controllers/accounts/sessions.js index c1713d3d62..74896346d7 100644 --- a/src/controllers/accounts/sessions.js +++ b/src/controllers/accounts/sessions.js @@ -2,19 +2,17 @@ const user = require('../../user'); const helpers = require('../helpers'); -const accountHelpers = require('./helpers'); const sessionController = module.exports; -sessionController.get = async function (req, res, next) { - const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query); - if (!userData) { - return next(); - } +sessionController.get = async function (req, res) { + const { username, userslug } = await user.getUserFields(res.locals.uid, ['username', 'userslug']); - 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]]' }]); + const payload = { + sessions: await user.auth.getSessions(res.locals.uid, req.sessionID), + title: '[[pages:account/sessions]]', + breadcrumbs: helpers.buildBreadcrumbs([{ text: username, url: `/user/${userslug}` }, { text: '[[pages:account/sessions]]' }]), + }; - res.render('account/sessions', userData); + res.render('account/sessions', payload); }; diff --git a/src/controllers/accounts/uploads.js b/src/controllers/accounts/uploads.js index b8afa0d1fe..edfbe23740 100644 --- a/src/controllers/accounts/uploads.js +++ b/src/controllers/accounts/uploads.js @@ -6,35 +6,33 @@ const nconf = require('nconf'); const db = require('../../database'); const helpers = require('../helpers'); +const user = require('../../user'); const meta = require('../../meta'); const pagination = require('../../pagination'); -const accountHelpers = require('./helpers'); const uploadsController = module.exports; -uploadsController.get = async function (req, res, next) { - const userData = await accountHelpers.getUserDataByUserSlug(req.params.userslug, req.uid, req.query); - if (!userData) { - return next(); - } - +uploadsController.get = async function (req, res) { + const { username, userslug } = await user.getUserFields(res.locals.uid, ['username', 'userslug']); 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), + db.sortedSetCard(`uid:${res.locals.uid}:uploads`), + db.getSortedSetRevRange(`uid:${res.locals.uid}:uploads`, start, stop), ]); - userData.uploads = uploadNames.map(uploadName => ({ + const payload = {}; + payload.uploads = uploadNames.map(uploadName => ({ name: uploadName, url: path.resolve(nconf.get('upload_url'), uploadName), })); 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); + payload.pagination = pagination.create(page, pageCount, req.query); + payload.privateUploads = meta.config.privateUploads === 1; + payload.title = `[[pages:account/uploads, ${username}]]`; + payload.breadcrumbs = helpers.buildBreadcrumbs([{ text: username, url: `/user/${userslug}` }, { text: '[[global:uploads]]' }]); + + res.render('account/uploads', payload); }; diff --git a/src/socket.io/topics/unread.js b/src/socket.io/topics/unread.js index cd93169983..983a9634c6 100644 --- a/src/socket.io/topics/unread.js +++ b/src/socket.io/topics/unread.js @@ -1,6 +1,5 @@ 'use strict'; -const db = require('../../database'); const user = require('../../user'); const topics = require('../../topics');