From 26ae33cac360fc8a7ecf9e17fe2254f8ae86322f Mon Sep 17 00:00:00 2001 From: Shi Jin Date: Sun, 12 May 2024 17:27:17 -0600 Subject: [PATCH 1/3] initial commit: add monthlyQuotaConsumed field to GET /api/user API --- api/server/controllers/UserController.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/api/server/controllers/UserController.js b/api/server/controllers/UserController.js index 4fd159ab756..5f42ab9b2fd 100644 --- a/api/server/controllers/UserController.js +++ b/api/server/controllers/UserController.js @@ -5,8 +5,19 @@ const User = require('../../models/User'); const getUserController = async (req, res) => { try { const { userId } = req.params; - if (userId == undefined || userId === req.user.id) {res.status(200).send(req.user);} - else { + if (userId == undefined || userId === req.user.id) { + // information about the current user + const monthlyQuotaConsumed = 250; // This value might be dynamic based on your application logic + + // Extend req.user with the new field + const response = { + ...req.user.toJSON(), + monthlyQuotaConsumed: monthlyQuotaConsumed, + }; + res.status(200).send(response); + } else { + // information about another user, without even authentification. + // TODO: this might be a security issue const user = await User.findById(userId).exec(); const id = user._id; const name = user.name; From c65a76f02e13078ae50d2a3439294af7ef819a6d Mon Sep 17 00:00:00 2001 From: Shi Jin Date: Sun, 12 May 2024 22:32:59 -0600 Subject: [PATCH 2/3] Got the API to return additional object for quota consumption --- api/server/controllers/UserController.js | 5 ++-- api/server/middleware/index.js | 2 ++ api/server/middleware/messageQuota.js | 31 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 api/server/middleware/messageQuota.js diff --git a/api/server/controllers/UserController.js b/api/server/controllers/UserController.js index 5f42ab9b2fd..eeb0df51eec 100644 --- a/api/server/controllers/UserController.js +++ b/api/server/controllers/UserController.js @@ -1,13 +1,14 @@ const { updateUserPluginsService } = require('../services/UserService'); const { updateUserPluginAuth, deleteUserPluginAuth } = require('../services/PluginService'); +const { getUserMessageQuotaUsagePastDays } = require('../middleware/messageQuota'); const User = require('../../models/User'); const getUserController = async (req, res) => { try { const { userId } = req.params; - if (userId == undefined || userId === req.user.id) { + if (userId === undefined || userId === req.user.id) { // information about the current user - const monthlyQuotaConsumed = 250; // This value might be dynamic based on your application logic + const monthlyQuotaConsumed = await getUserMessageQuotaUsagePastDays(req.user, 30); // This value might be dynamic based on your application logic // Extend req.user with the new field const response = { diff --git a/api/server/middleware/index.js b/api/server/middleware/index.js index 553f2c663ab..47932d8520d 100644 --- a/api/server/middleware/index.js +++ b/api/server/middleware/index.js @@ -12,6 +12,7 @@ const concurrentLimiter = require('./concurrentLimiter'); const validateMessageReq = require('./validateMessageReq'); const buildEndpointOption = require('./buildEndpointOption'); const validateRegistration = require('./validateRegistration'); +const messageQuota = require('./messageQuota'); module.exports = { ...abortMiddleware, @@ -28,4 +29,5 @@ module.exports = { validateMessageReq, buildEndpointOption, validateRegistration, + messageQuota, }; diff --git a/api/server/middleware/messageQuota.js b/api/server/middleware/messageQuota.js new file mode 100644 index 00000000000..269c19fcf00 --- /dev/null +++ b/api/server/middleware/messageQuota.js @@ -0,0 +1,31 @@ +const { getMessagesCount } = require('../../models'); + +const getUserMessageQuotaUsagePastDays = async (user, days = 30) => { + let currentTime = new Date(); + let quota = 0; + if ('proMemberExpiredAt' in user && user.proMemberExpiredAt > currentTime) { + // If not proMember, check quota + quota = JSON.parse(process.env['CHAT_QUOTA_PER_MONTH_PRO_MEMBER']); + } else { + quota = JSON.parse(process.env['CHAT_QUOTA_PER_MONTH']); + } + + let someTimeAgo = currentTime; + someTimeAgo.setSeconds(currentTime.getSeconds() - 60 * 60 * 24 * days); // 30 days + + let quotaUsage = {}; + + let promises = Object.keys(quota).map(async (model) => { + let messagesCount = await getMessagesCount({ + $and: [{ senderId: user.id }, { model: model }, { updatedAt: { $gte: someTimeAgo } }], + }); + quotaUsage[model] = messagesCount; + console.log('model=%s: %d/%d used', model, quotaUsage[model], quota[model]); + }); + await Promise.all(promises); + return quotaUsage; +}; + +module.exports = { + getUserMessageQuotaUsagePastDays, +}; From 96d6e1c7f86e9e24282fdb805ab6d75db97ada04 Mon Sep 17 00:00:00 2001 From: Shi Jin Date: Sun, 12 May 2024 22:42:43 -0600 Subject: [PATCH 3/3] restructure output to include both consumption and quota --- api/server/middleware/messageQuota.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/api/server/middleware/messageQuota.js b/api/server/middleware/messageQuota.js index 269c19fcf00..daa485490bd 100644 --- a/api/server/middleware/messageQuota.js +++ b/api/server/middleware/messageQuota.js @@ -19,8 +19,11 @@ const getUserMessageQuotaUsagePastDays = async (user, days = 30) => { let messagesCount = await getMessagesCount({ $and: [{ senderId: user.id }, { model: model }, { updatedAt: { $gte: someTimeAgo } }], }); - quotaUsage[model] = messagesCount; - console.log('model=%s: %d/%d used', model, quotaUsage[model], quota[model]); + quotaUsage[model] = { + consumed: messagesCount, + quota: quota[model], + }; + console.log(model, quotaUsage[model]); }); await Promise.all(promises); return quotaUsage;