refactor: original changes

This commit is contained in:
Danny Avila 2025-05-30 04:28:22 -04:00
parent fa9177180f
commit f9c0e9853f
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
83 changed files with 413 additions and 505 deletions

View file

@ -1,6 +1,7 @@
const openIdClient = require('openid-client');
const cookies = require('cookie');
const jwt = require('jsonwebtoken');
const openIdClient = require('openid-client');
const { User, Session, logger } = require('@librechat/data-schemas');
const {
registerUser,
resetPassword,
@ -9,9 +10,7 @@ const {
setOpenIDAuthTokens,
} = require('~/server/services/AuthService');
const { getOpenIdConfig } = require('~/strategies');
const { logger } = require('~/config');
const { isEnabled } = require('~/server/utils');
const db = require('~/lib/db/connectDb');
const registrationController = async (req, res) => {
try {
@ -48,7 +47,7 @@ const resetPasswordController = async (req, res) => {
if (resetPasswordService instanceof Error) {
return res.status(400).json(resetPasswordService);
} else {
await db.models.Session.deleteAllUserSessions({ userId: req.body.userId });
await Session.deleteAllUserSessions({ userId: req.body.userId });
return res.status(200).json(resetPasswordService);
}
} catch (e) {
@ -70,7 +69,7 @@ const refreshController = async (req, res) => {
const openIdConfig = getOpenIdConfig();
const tokenset = await openIdClient.refreshTokenGrant(openIdConfig, refreshToken);
const claims = tokenset.claims();
const user = await findUser({ email: claims.email });
const user = await User.findUser({ email: claims.email });
if (!user) {
return res.status(401).redirect('/login');
}
@ -83,7 +82,7 @@ const refreshController = async (req, res) => {
}
try {
const payload = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET);
const user = await db.models.User.getUserById(payload.id, '-password -__v -totpSecret');
const user = await User.getUserById(payload.id, '-password -__v -totpSecret');
if (!user) {
return res.status(401).redirect('/login');
}
@ -96,7 +95,7 @@ const refreshController = async (req, res) => {
}
// Find the session with the hashed refresh token
const session = await db.models.Session.findSession({
const session = await Session.findSession({
userId: userId,
refreshToken: refreshToken,
});

View file

@ -1,6 +1,6 @@
const db = require('~/lib/db/connectDb');
const { Balance } = require('@librechat/data-schemas');
async function balanceController(req, res) {
const balanceData = await db.models.Balance.findOne(
const balanceData = await Balance.findOne(
{ user: req.user.id },
'-_id tokenCredits autoRefillEnabled refillIntervalValue refillIntervalUnit lastRefill refillAmount',
).lean();

View file

@ -1,3 +1,4 @@
const { User, logger } = require('@librechat/data-schemas');
const {
generateTOTPSecret,
generateBackupCodes,
@ -5,9 +6,7 @@ const {
verifyBackupCode,
getTOTPSecret,
} = require('~/server/services/twoFactorService');
const { logger } = require('~/config');
const { encryptV3 } = require('~/server/utils/crypto');
const db = require('~/lib/db/connectDb');
const safeAppTitle = (process.env.APP_TITLE || 'LibreChat').replace(/\s+/g, '');
/**
@ -24,7 +23,7 @@ const enable2FA = async (req, res) => {
const encryptedSecret = encryptV3(secret);
// Update the user record: store the secret & backup codes and set twoFactorEnabled to false.
const user = await db.models.User.updateUser(userId, {
const user = await User.updateUser(userId, {
totpSecret: encryptedSecret,
backupCodes: codeObjects,
twoFactorEnabled: false,
@ -46,7 +45,7 @@ const verify2FA = async (req, res) => {
try {
const userId = req.user.id;
const { token, backupCode } = req.body;
const user = await db.models.User.getUserById(userId);
const user = await User.getUserById(userId);
if (!user || !user.totpSecret) {
return res.status(400).json({ message: '2FA not initiated' });
@ -78,7 +77,6 @@ const confirm2FA = async (req, res) => {
try {
const userId = req.user.id;
const { token } = req.body;
const { User } = db.models;
const user = await User.getUserById(userId);
if (!user || !user.totpSecret) {
@ -103,7 +101,7 @@ const confirm2FA = async (req, res) => {
const disable2FA = async (req, res) => {
try {
const userId = req.user.id;
await db.models.User.updateUser(userId, { totpSecret: null, backupCodes: [], twoFactorEnabled: false });
await User.updateUser(userId, { totpSecret: null, backupCodes: [], twoFactorEnabled: false });
return res.status(200).json();
} catch (err) {
logger.error('[disable2FA]', err);
@ -118,7 +116,7 @@ const regenerateBackupCodes = async (req, res) => {
try {
const userId = req.user.id;
const { plainCodes, codeObjects } = await generateBackupCodes();
await db.models.User.updateUser(userId, { backupCodes: codeObjects });
await User.updateUser(userId, { backupCodes: codeObjects });
return res.status(200).json({
backupCodes: plainCodes,
backupCodesHash: codeObjects,

View file

@ -1,18 +1,11 @@
const {
Tools,
Constants,
FileSources,
webSearchKeys,
extractWebSearchEnvVars,
} = require('librechat-data-provider');
const {
Balance,
getFiles,
deleteFiles,
deleteConvos,
deletePresets,
deleteMessages,
} = require('~/models');
const { User, Session, Transaction, Balance, logger } = require('@librechat/data-schemas');
const { getFiles, deleteFiles, deleteConvos, deletePresets, deleteMessages } = require('~/models');
const { updateUserPluginAuth, deleteUserPluginAuth } = require('~/server/services/PluginService');
const { updateUserPluginsService, deleteUserKey } = require('~/server/services/UserService');
const { verifyEmail, resendVerificationEmail } = require('~/server/services/AuthService');
@ -20,9 +13,6 @@ const { needsRefresh, getNewS3URL } = require('~/server/services/Files/S3/crud')
const { processDeleteRequest } = require('~/server/services/Files/process');
const { deleteAllSharedLinks } = require('~/models/Share');
const { deleteToolCalls } = require('~/models/ToolCall');
const { Transaction } = require('~/models/Transaction');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const getUserController = async (req, res) => {
/** @type {MongoUser} */
@ -36,7 +26,7 @@ const getUserController = async (req, res) => {
const originalAvatar = userData.avatar;
try {
userData.avatar = await getNewS3URL(userData.avatar);
await db.models.User.updateUser(userData.id, { avatar: userData.avatar });
await User.updateUser(userData.id, { avatar: userData.avatar });
} catch (error) {
userData.avatar = originalAvatar;
logger.error('Error getting new S3 URL for avatar:', error);
@ -47,7 +37,7 @@ const getUserController = async (req, res) => {
const getTermsStatusController = async (req, res) => {
try {
const user = await db.models.User.findById(req.user.id);
const user = await User.findById(req.user.id);
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
@ -60,7 +50,7 @@ const getTermsStatusController = async (req, res) => {
const acceptTermsController = async (req, res) => {
try {
const user = await db.models.User.findByIdAndUpdate(req.user.id, { termsAccepted: true }, { new: true });
const user = await User.findByIdAndUpdate(req.user.id, { termsAccepted: true }, { new: true });
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
@ -157,7 +147,7 @@ const deleteUserController = async (req, res) => {
try {
await deleteMessages({ user: user.id }); // delete user messages
await db.models.Session.deleteAllUserSessions({ userId: user.id }); // delete user sessions
await Session.deleteAllUserSessions({ userId: user.id }); // delete user sessions
await Transaction.deleteMany({ user: user.id }); // delete user transactions
await deleteUserKey({ userId: user.id, all: true }); // delete user keys
await Balance.deleteMany({ user: user._id }); // delete user balances
@ -165,7 +155,7 @@ const deleteUserController = async (req, res) => {
/* TODO: Delete Assistant Threads */
await deleteConvos(user.id); // delete user convos
await deleteUserPluginAuth(user.id, null, true); // delete user plugin auth
await db.models.User.deleteUserById(user.id); // delete user
await User.deleteUserById(user.id); // delete user
await deleteAllSharedLinks(user.id); // delete user shared links
await deleteUserFiles(req); // delete user files
await deleteFiles(null, user.id); // delete database files in case of orphaned files from previous steps

View file

@ -5,8 +5,7 @@ const {
getTOTPSecret,
} = require('~/server/services/twoFactorService');
const { setAuthTokens } = require('~/server/services/AuthService');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const { User, logger } = require('@librechat/data-schemas');
/**
* Verifies the 2FA code during login using a temporary token.
@ -25,7 +24,7 @@ const verify2FAWithTempToken = async (req, res) => {
return res.status(401).json({ message: 'Invalid or expired temporary token' });
}
const user = await db.models.User.getUserById(payload.userId);
const user = await User.getUserById(payload.userId);
if (!user || !user.twoFactorEnabled) {
return res.status(400).json({ message: '2FA is not enabled for this user' });
}

View file

@ -5,9 +5,7 @@ const { isEnabled, removePorts } = require('~/server/utils');
const keyvMongo = require('~/cache/keyvMongo');
const denyRequest = require('./denyRequest');
const { getLogStores } = require('~/cache');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const { User, logger } = require('@librechat/data-schemas');
const banCache = new Keyv({ store: keyvMongo, namespace: ViolationTypes.BAN, ttl: 0 });
const message = 'Your account has been temporarily banned due to violations of our service.';
@ -58,7 +56,7 @@ const checkBan = async (req, res, next = () => {}) => {
let userId = req.user?.id ?? req.user?._id ?? null;
if (!userId && req?.body?.email) {
const user = await db.models.User.findUser({ email: req.body.email }, '_id');
const user = await User.findUser({ email: req.body.email }, '_id');
userId = user?._id ? user._id.toString() : userId;
}

View file

@ -1,5 +1,5 @@
const { deleteTokens } = require('@librechat/data-schemas');
const { getInvite } = require('~/models/inviteUser');
const db = require('~/lib/db/connectDb');
async function checkInviteUser(req, res, next) {
const token = req.body.token;
@ -16,7 +16,7 @@ async function checkInviteUser(req, res, next) {
return res.status(400).json({ message: 'Invalid invite token' });
}
await db.models.Token.deleteTokens({ token: invite.token });
await deleteTokens({ token: invite.token });
req.invite = invite;
next();
} catch (error) {

View file

@ -1,6 +1,5 @@
const { Balance, logger } = require('@librechat/data-schemas');
const { getBalanceConfig } = require('~/server/services/Config');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
/**
* Middleware to synchronize user balance settings with current balance configuration.
@ -20,14 +19,14 @@ const setBalanceConfig = async (req, res, next) => {
}
const userId = req.user._id;
const userBalanceRecord = await db.models.Balance.findOne({ user: userId }).lean();
const userBalanceRecord = await Balance.findOne({ user: userId }).lean();
const updateFields = buildUpdateFields(balanceConfig, userBalanceRecord);
if (Object.keys(updateFields).length === 0) {
return next();
}
await db.models.Balance.findOneAndUpdate(
await Balance.findOneAndUpdate(
{ user: userId },
{ $set: updateFields },
{ upsert: true, new: true },

View file

@ -1,5 +1,6 @@
const express = require('express');
const { ContentTypes } = require('librechat-data-provider');
const { Message, logger } = require('@librechat/data-schemas');
const {
saveConvo,
saveMessage,
@ -13,8 +14,6 @@ const { requireJwtAuth, validateMessageReq } = require('~/server/middleware');
const { cleanUpPrimaryKeyValue } = require('~/lib/utils/misc');
const { getConvosQueried } = require('~/models/Conversation');
const { countTokens } = require('~/server/utils');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const router = express.Router();
router.use(requireJwtAuth);
@ -40,7 +39,7 @@ router.get('/', async (req, res) => {
const sortOrder = sortDirection === 'asc' ? 1 : -1;
if (conversationId && messageId) {
const message = await db.models.Message.findOne({
const message = await Message.findOne({
conversationId,
messageId,
user: user,
@ -51,14 +50,14 @@ router.get('/', async (req, res) => {
if (cursor) {
filter[sortField] = sortOrder === 1 ? { $gt: cursor } : { $lt: cursor };
}
const messages = await db.models.Message.find(filter)
const messages = await Message.find(filter)
.sort({ [sortField]: sortOrder })
.limit(pageSize + 1)
.lean();
const nextCursor = messages.length > pageSize ? messages.pop()[sortField] : null;
response = { messages, nextCursor };
} else if (search) {
const searchResults = await db.models.Message.meiliSearch(search, undefined, true);
const searchResults = await Message.meiliSearch(search, undefined, true);
const messages = searchResults.hits || [];

View file

@ -1,6 +1,7 @@
const jwt = require('jsonwebtoken');
const { nanoid } = require('nanoid');
const { tool } = require('@langchain/core/tools');
const { findToken } = require('@librechat/data-schemas');
const { GraphEvents, sleep } = require('@librechat/agents');
const {
Time,
@ -231,10 +232,9 @@ async function createActionTool({
};
const tokenPromises = [];
const { Token } = db.models;
tokenPromises.push(Token.findToken({ userId, type: 'oauth', identifier }));
tokenPromises.push(findToken({ userId, type: 'oauth', identifier }));
tokenPromises.push(
Token.findToken({
findToken({
userId,
type: 'oauth_refresh',
identifier: `${identifier}:refresh`,

View file

@ -1,11 +1,11 @@
const fs = require('fs');
const path = require('path');
const sharp = require('sharp');
const { updateUser, logger } = require('@librechat/data-schemas');
const { resizeImageBuffer } = require('../images/resize');
const { updateFile } = require('~/models/File');
const { logger } = require('~/config');
const { saveBufferToAzure } = require('./crud');
const db = require('~/lib/db/connectDb');
/**
* Uploads an image file to Azure Blob Storage.
* It resizes and converts the image similar to your Firebase implementation.
@ -107,7 +107,7 @@ async function processAzureAvatar({ buffer, userId, manual, basePath = 'images',
const isManual = manual === 'true';
const url = `${downloadURL}?manual=${isManual}`;
if (isManual) {
await db.models?.User.updateUser(userId, { avatar: url });
await updateUser(userId, { avatar: url });
}
return url;
} catch (error) {

View file

@ -4,8 +4,7 @@ const sharp = require('sharp');
const { resizeImageBuffer } = require('../images/resize');
const { saveBufferToFirebase } = require('./crud');
const { updateFile } = require('~/models/File');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const { logger, updateUser } = require('@librechat/data-schemas');
/**
* Converts an image file to the target format. The function first resizes the image based on the specified
@ -99,7 +98,7 @@ async function processFirebaseAvatar({ buffer, userId, manual }) {
const url = `${downloadURL}?manual=${isManual}`;
if (isManual) {
await db.models.User.updateUser(userId, { avatar: url });
await updateUser(userId, { avatar: url });
}
return url;

View file

@ -1,9 +1,9 @@
const fs = require('fs');
const path = require('path');
const sharp = require('sharp');
const { updateUser } = require('@librechat/data-schemas');
const { resizeImageBuffer } = require('../images/resize');
const { updateFile } = require('~/models/File');
const db = require('~/lib/db/connectDb');
/**
* Converts an image file to the target format. The function first resizes the image based on the specified
@ -141,7 +141,7 @@ async function processLocalAvatar({ buffer, userId, manual }) {
let url = `${urlRoute}?manual=${isManual}`;
if (isManual) {
await db.models?.User.updateUser(userId, { avatar: url });
await updateUser(userId, { avatar: url });
}
return url;

View file

@ -1,11 +1,10 @@
const fs = require('fs');
const path = require('path');
const sharp = require('sharp');
const { logger, updateUser } = require('@librechat/data-schemas');
const { resizeImageBuffer } = require('../images/resize');
const { saveBufferToS3 } = require('./crud');
const { updateFile } = require('~/models/File');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const { saveBufferToS3 } = require('./crud');
const defaultBasePath = 'images';
@ -102,7 +101,7 @@ async function processS3Avatar({ buffer, userId, manual, basePath = defaultBaseP
try {
const downloadURL = await saveBufferToS3({ userId, buffer, fileName: 'avatar.png', basePath });
if (manual === 'true') {
await db.models?.User.updateUser(userId, { avatar: downloadURL });
await updateUser(userId, { avatar: downloadURL });
}
return downloadURL;
} catch (error) {

View file

@ -1,7 +1,7 @@
const { ErrorTypes } = require('librechat-data-provider');
const { encrypt, decrypt } = require('~/server/utils');
const { logger } = require('~/config');
const db = require('~/lib/db/connectDb');
const { Key, logger, updateUser } = require('@librechat/data-schemas');
const { encrypt, decrypt } = require('~/server/utils/crypto');
/**
* Updates the plugins for a user based on the action specified (install/uninstall).
* @async
@ -16,11 +16,10 @@ const db = require('~/lib/db/connectDb');
const updateUserPluginsService = async (user, pluginKey, action) => {
try {
const userPlugins = user.plugins || [];
const { User } = db.models;
if (action === 'install') {
return await User.updateUser(user._id, { plugins: [...userPlugins, pluginKey] });
return await updateUser(user._id, { plugins: [...userPlugins, pluginKey] });
} else if (action === 'uninstall') {
return await User.updateUser(user._id, {
return await updateUser(user._id, {
plugins: userPlugins.filter((plugin) => plugin !== pluginKey),
});
}
@ -42,7 +41,7 @@ const updateUserPluginsService = async (user, pluginKey, action) => {
* an error indicating that there is no user key available.
*/
const getUserKey = async ({ userId, name }) => {
const keyValue = await db.models.Key.findOne({ userId, name }).lean();
const keyValue = await Key.findOne({ userId, name }).lean();
if (!keyValue) {
throw new Error(
JSON.stringify({
@ -89,7 +88,7 @@ const getUserKeyValues = async ({ userId, name }) => {
* returns its expiry date. If the key is not found, it returns null for the expiry date.
*/
const getUserKeyExpiry = async ({ userId, name }) => {
const keyValue = await db.models.Key.findOne({ userId, name }).lean();
const keyValue = await Key.findOne({ userId, name }).lean();
if (!keyValue) {
return { expiresAt: null };
}
@ -123,7 +122,7 @@ const updateUserKey = async ({ userId, name, value, expiresAt = null }) => {
// make sure to remove if already present
updateQuery.$unset = { expiresAt };
}
return await db.models.Key.findOneAndUpdate({ userId, name }, updateQuery, {
return await Key.findOneAndUpdate({ userId, name }, updateQuery, {
upsert: true,
new: true,
}).lean();
@ -143,10 +142,10 @@ const updateUserKey = async ({ userId, name, value, expiresAt = null }) => {
*/
const deleteUserKey = async ({ userId, name, all = false }) => {
if (all) {
return await db.models.Key.deleteMany({ userId });
return await Key.deleteMany({ userId });
}
await db.models.Key.findOneAndDelete({ userId, name }).lean();
await Key.findOneAndDelete({ userId, name }).lean();
};
/**

View file

@ -1,7 +1,6 @@
const { webcrypto } = require('node:crypto');
const { decryptV3, decryptV2 } = require('../utils/crypto');
const { hashBackupCode } = require('~/server/utils/crypto');
const db = require('~/lib/db/connectDb');
const { User } = require('@librechat/data-schemas');
const { hashBackupCode, decryptV3, decryptV2 } = require('~/server/utils/crypto');
// Base32 alphabet for TOTP secret encoding.
const BASE32_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
@ -173,7 +172,7 @@ const verifyBackupCode = async ({ user, backupCode }) => {
: codeObj,
);
// Update the user record with the marked backup code.
await db.models.User.updateUser(user._id, { backupCodes: updatedBackupCodes });
await User.updateUser(user._id, { backupCodes: updatedBackupCodes });
return true;
}
return false;