From b97dfdfa8373e7ae371d125c263c9e204fdd12bc Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Wed, 28 Jan 2026 20:56:29 +0100 Subject: [PATCH] Use lean in more places --- website/server/controllers/api-v3/inbox.js | 2 +- website/server/controllers/api-v3/tasks.js | 4 ++-- website/server/controllers/api-v3/user.js | 2 +- website/server/controllers/api-v4/members.js | 1 + website/server/controllers/api-v4/user.js | 4 +++- website/server/controllers/top-level/dataexport.js | 5 ++--- website/server/libs/chat.js | 1 + website/server/libs/chat/group-chat.js | 4 ++-- website/server/libs/inbox/conversation.methods.js | 2 +- website/server/libs/payments/apple.js | 5 ++++- website/server/libs/tasks/index.js | 2 +- website/server/libs/user/index.js | 2 +- 12 files changed, 20 insertions(+), 14 deletions(-) diff --git a/website/server/controllers/api-v3/inbox.js b/website/server/controllers/api-v3/inbox.js index f2bb28d09f..931cb519c0 100644 --- a/website/server/controllers/api-v3/inbox.js +++ b/website/server/controllers/api-v3/inbox.js @@ -24,7 +24,7 @@ const api = {}; api.getInboxMessages = { method: 'GET', url: '/inbox/messages', - middlewares: [authWithHeaders({ userFieldsToInclude: ['profile', 'contributor', 'backer', 'inbox'] })], + middlewares: [authWithHeaders({ leanUser: true, userFieldsToInclude: ['profile', 'contributor', 'backer', 'inbox'] })], async handler (req, res) { const { user } = res.locals; const { page } = req.query; diff --git a/website/server/controllers/api-v3/tasks.js b/website/server/controllers/api-v3/tasks.js index 5d91b70557..172fb68fca 100644 --- a/website/server/controllers/api-v3/tasks.js +++ b/website/server/controllers/api-v3/tasks.js @@ -388,7 +388,7 @@ api.getUserTasks = { method: 'GET', url: '/tasks/user', middlewares: [authWithHeaders({ - // Some fields (including _id, preferences) are always loaded (see middlewares/auth) + leanUser: true, userFieldsToInclude: ['tasksOrder'], })], async handler (req, res) { @@ -953,7 +953,7 @@ api.addChecklistItem = { api.scoreCheckListItem = { method: 'POST', url: '/tasks/:taskId/checklist/:itemId/score', - middlewares: [authWithHeaders()], + middlewares: [authWithHeaders({ leanUser: true, userFieldsToInclude: ['_id'] })], async handler (req, res) { const { user } = res.locals; diff --git a/website/server/controllers/api-v3/user.js b/website/server/controllers/api-v3/user.js index ddc1f81ed0..13e7cf1570 100644 --- a/website/server/controllers/api-v3/user.js +++ b/website/server/controllers/api-v3/user.js @@ -406,7 +406,7 @@ api.getUserAnonymized = { { type: { $in: ['habit', 'daily', 'reward'] } }, ], }; - const tasks = await Tasks.Task.find(query).exec(); + const tasks = await Tasks.Task.find(query).lean().exec(); forEach(tasks, task => { task.text = 'task text'; diff --git a/website/server/controllers/api-v4/members.js b/website/server/controllers/api-v4/members.js index 9717907433..e0af76c0d1 100644 --- a/website/server/controllers/api-v4/members.js +++ b/website/server/controllers/api-v4/members.js @@ -22,6 +22,7 @@ api.purchaseHistory = { let transactions = await Transaction .find({ userId: req.params.memberId }) .sort({ createdAt: -1 }) + .lean() .exec(); if (!res.locals.user.hasPermission('userSupport')) { diff --git a/website/server/controllers/api-v4/user.js b/website/server/controllers/api-v4/user.js index 43694bd805..b31c09bb35 100644 --- a/website/server/controllers/api-v4/user.js +++ b/website/server/controllers/api-v4/user.js @@ -313,7 +313,9 @@ api.purchaseHistory = { url: '/user/purchase-history', async handler (req, res) { const { user } = res.locals; - const transactions = await Transaction.find({ userId: user._id }).sort({ createdAt: -1 }); + const transactions = await Transaction.find({ userId: user._id }) + .sort({ createdAt: -1 }) + .lean(); res.respond(200, transactions); }, }; diff --git a/website/server/controllers/top-level/dataexport.js b/website/server/controllers/top-level/dataexport.js index 942ec67274..2fd817c765 100644 --- a/website/server/controllers/top-level/dataexport.js +++ b/website/server/controllers/top-level/dataexport.js @@ -53,7 +53,7 @@ api.exportUserHistory = { const tasks = await Tasks.Task.find({ userId: user._id, type: { $in: ['habit', 'daily'] }, - }).exec(); + }).lean().exec(); const output = [ ['Task Name', 'Task ID', 'Task Type', 'Date', 'Value'], @@ -92,7 +92,7 @@ async function _getUserDataForExport (user) { const [tasks, messages] = await Promise.all([ Tasks.Task.find({ userId: user._id, - }).exec(), + }).lean().exec(), inboxLib.getUserInbox(user, { asArray: false }), ]); @@ -100,7 +100,6 @@ async function _getUserDataForExport (user) { userData.inbox.messages = messages; _(tasks) - .map(task => task.toJSON()) .groupBy(task => task.type) .forEach((tasksPerType, taskType) => { userData.tasks[`${taskType}s`] = tasksPerType; diff --git a/website/server/libs/chat.js b/website/server/libs/chat.js index f7c8d9cd38..841a3b9edc 100644 --- a/website/server/libs/chat.js +++ b/website/server/libs/chat.js @@ -22,6 +22,7 @@ export async function sendChatPushNotifications (user, group, message, mentions, 'party._id': group._id, _id: { $ne: user._id }, }) + .lean() .select('preferences.pushNotifications preferences.language profile.name pushDevices auth.local.username') .exec(); diff --git a/website/server/libs/chat/group-chat.js b/website/server/libs/chat/group-chat.js index 028f987b4a..d2c332d254 100644 --- a/website/server/libs/chat/group-chat.js +++ b/website/server/libs/chat/group-chat.js @@ -25,13 +25,13 @@ export async function getGroupChat (group, options = {}) { .sort('-timestamp'); if (before) { - const beforeMessage = await Chat.findOne({ _id: before }).exec(); + const beforeMessage = await Chat.findOne({ _id: before }, { timestamp: 1 }).lean().exec(); if (beforeMessage) { query = query.where('timestamp').lt(beforeMessage.timestamp); } } - const groupChat = await query.limit(effectiveLimit).exec(); + const groupChat = await query.limit(effectiveLimit).lean().exec(); // @TODO: Concat old chat to keep continuity of chat stored on group object const currentGroupChat = group.chat || []; diff --git a/website/server/libs/inbox/conversation.methods.js b/website/server/libs/inbox/conversation.methods.js index a2b68e2de0..45996e499d 100644 --- a/website/server/libs/inbox/conversation.methods.js +++ b/website/server/libs/inbox/conversation.methods.js @@ -22,7 +22,7 @@ async function usersMapByConversations (users) { stats: 1, flags: 1, inbox: 1, - }).exec(); + }).lean().exec(); for (const usr of loadedUsers) { const loadedUserConversation = { diff --git a/website/server/libs/payments/apple.js b/website/server/libs/payments/apple.js index bc7a364ba0..832bd7989e 100644 --- a/website/server/libs/payments/apple.js +++ b/website/server/libs/payments/apple.js @@ -169,7 +169,10 @@ api.subscribe = async function subscribe (user, receipt, headers, nextPaymentPro { 'purchased.plan.customerId': purchase.originalTransactionId }, { 'purchased.plan.customerId': purchase.transactionId }, ], - }).exec(); + }, { + _id: 1, + 'purchased.plan': 1, + }).lean().exec(); if (existingUsers.length > 0) { if (purchase.originalTransactionId === purchase.transactionId) { throw new NotAuthorized(this.constants.RESPONSE_ALREADY_USED); diff --git a/website/server/libs/tasks/index.js b/website/server/libs/tasks/index.js index 2b4c07464b..7f9ae7463c 100644 --- a/website/server/libs/tasks/index.js +++ b/website/server/libs/tasks/index.js @@ -178,7 +178,7 @@ async function getTasks (req, res, options = {}) { ], }, { _id: 1 }, - ).exec(); + ).lean().exec(); } if (upgradedGroups.length > 0) { for (const upgradedGroup of upgradedGroups) { diff --git a/website/server/libs/user/index.js b/website/server/libs/user/index.js index 74ba642d9b..6f4678197b 100644 --- a/website/server/libs/user/index.js +++ b/website/server/libs/user/index.js @@ -186,7 +186,7 @@ export async function update (req, res, { isV3 = false }) { ], }, { _id: 1, - }).exec(); + }).lean().exec(); matchingGroupsArray = _.map(matchingGroups, groupRecord => groupRecord._id); }