mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-20 10:20:15 +01:00
Move usermethods and models to data-schema
This commit is contained in:
parent
4808c5be48
commit
4049b5572c
93 changed files with 2396 additions and 1267 deletions
|
|
@ -8,10 +8,10 @@ const {
|
|||
requestPasswordReset,
|
||||
setOpenIDAuthTokens,
|
||||
} = require('~/server/services/AuthService');
|
||||
const { findSession, getUserById, deleteAllUserSessions, findUser } = require('~/models');
|
||||
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 +48,7 @@ const resetPasswordController = async (req, res) => {
|
|||
if (resetPasswordService instanceof Error) {
|
||||
return res.status(400).json(resetPasswordService);
|
||||
} else {
|
||||
await deleteAllUserSessions({ userId: req.body.userId });
|
||||
await db.models.Session.deleteAllUserSessions({ userId: req.body.userId });
|
||||
return res.status(200).json(resetPasswordService);
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -83,7 +83,7 @@ const refreshController = async (req, res) => {
|
|||
}
|
||||
try {
|
||||
const payload = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET);
|
||||
const user = await getUserById(payload.id, '-password -__v -totpSecret');
|
||||
const user = await db.models.User.getUserById(payload.id, '-password -__v -totpSecret');
|
||||
if (!user) {
|
||||
return res.status(401).redirect('/login');
|
||||
}
|
||||
|
|
@ -96,7 +96,10 @@ const refreshController = async (req, res) => {
|
|||
}
|
||||
|
||||
// Find the session with the hashed refresh token
|
||||
const session = await findSession({ userId: userId, refreshToken: refreshToken });
|
||||
const session = await db.models.Session.findSession({
|
||||
userId: userId,
|
||||
refreshToken: refreshToken,
|
||||
});
|
||||
|
||||
if (session && session.expiration > new Date()) {
|
||||
const token = await setAuthTokens(userId, res, session._id);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
const Balance = require('~/models/Balance');
|
||||
|
||||
const db = require('~/lib/db/connectDb');
|
||||
async function balanceController(req, res) {
|
||||
const balanceData = await Balance.findOne(
|
||||
const balanceData = await db.models.Balance.findOne(
|
||||
{ user: req.user.id },
|
||||
'-_id tokenCredits autoRefillEnabled refillIntervalValue refillIntervalUnit lastRefill refillAmount',
|
||||
).lean();
|
||||
|
|
|
|||
|
|
@ -5,10 +5,9 @@ const {
|
|||
verifyBackupCode,
|
||||
getTOTPSecret,
|
||||
} = require('~/server/services/twoFactorService');
|
||||
const { updateUser, getUserById } = require('~/models');
|
||||
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, '');
|
||||
|
||||
/**
|
||||
|
|
@ -25,7 +24,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 updateUser(userId, {
|
||||
const user = await db.models.User.updateUser(userId, {
|
||||
totpSecret: encryptedSecret,
|
||||
backupCodes: codeObjects,
|
||||
twoFactorEnabled: false,
|
||||
|
|
@ -47,7 +46,7 @@ const verify2FA = async (req, res) => {
|
|||
try {
|
||||
const userId = req.user.id;
|
||||
const { token, backupCode } = req.body;
|
||||
const user = await getUserById(userId);
|
||||
const user = await db.models.User.getUserById(userId);
|
||||
|
||||
if (!user || !user.totpSecret) {
|
||||
return res.status(400).json({ message: '2FA not initiated' });
|
||||
|
|
@ -79,7 +78,8 @@ const confirm2FA = async (req, res) => {
|
|||
try {
|
||||
const userId = req.user.id;
|
||||
const { token } = req.body;
|
||||
const user = await getUserById(userId);
|
||||
const { User } = db.models;
|
||||
const user = await User.getUserById(userId);
|
||||
|
||||
if (!user || !user.totpSecret) {
|
||||
return res.status(400).json({ message: '2FA not initiated' });
|
||||
|
|
@ -87,7 +87,7 @@ const confirm2FA = async (req, res) => {
|
|||
|
||||
const secret = await getTOTPSecret(user.totpSecret);
|
||||
if (await verifyTOTP(secret, token)) {
|
||||
await updateUser(userId, { twoFactorEnabled: true });
|
||||
await User.updateUser(userId, { twoFactorEnabled: true });
|
||||
return res.status(200).json();
|
||||
}
|
||||
return res.status(400).json({ message: 'Invalid token.' });
|
||||
|
|
@ -103,7 +103,7 @@ const confirm2FA = async (req, res) => {
|
|||
const disable2FA = async (req, res) => {
|
||||
try {
|
||||
const userId = req.user.id;
|
||||
await updateUser(userId, { totpSecret: null, backupCodes: [], twoFactorEnabled: false });
|
||||
await db.models.User.updateUser(userId, { totpSecret: null, backupCodes: [], twoFactorEnabled: false });
|
||||
return res.status(200).json();
|
||||
} catch (err) {
|
||||
logger.error('[disable2FA]', err);
|
||||
|
|
@ -118,7 +118,7 @@ const regenerateBackupCodes = async (req, res) => {
|
|||
try {
|
||||
const userId = req.user.id;
|
||||
const { plainCodes, codeObjects } = await generateBackupCodes();
|
||||
await updateUser(userId, { backupCodes: codeObjects });
|
||||
await db.models.User.updateUser(userId, { backupCodes: codeObjects });
|
||||
return res.status(200).json({
|
||||
backupCodes: plainCodes,
|
||||
backupCodesHash: codeObjects,
|
||||
|
|
|
|||
|
|
@ -8,15 +8,11 @@ const {
|
|||
const {
|
||||
Balance,
|
||||
getFiles,
|
||||
updateUser,
|
||||
deleteFiles,
|
||||
deleteConvos,
|
||||
deletePresets,
|
||||
deleteMessages,
|
||||
deleteUserById,
|
||||
deleteAllUserSessions,
|
||||
} = require('~/models');
|
||||
const User = require('~/models/User');
|
||||
const { updateUserPluginAuth, deleteUserPluginAuth } = require('~/server/services/PluginService');
|
||||
const { updateUserPluginsService, deleteUserKey } = require('~/server/services/UserService');
|
||||
const { verifyEmail, resendVerificationEmail } = require('~/server/services/AuthService');
|
||||
|
|
@ -26,6 +22,7 @@ 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} */
|
||||
|
|
@ -39,7 +36,7 @@ const getUserController = async (req, res) => {
|
|||
const originalAvatar = userData.avatar;
|
||||
try {
|
||||
userData.avatar = await getNewS3URL(userData.avatar);
|
||||
await updateUser(userData.id, { avatar: userData.avatar });
|
||||
await db.models.User.updateUser(userData.id, { avatar: userData.avatar });
|
||||
} catch (error) {
|
||||
userData.avatar = originalAvatar;
|
||||
logger.error('Error getting new S3 URL for avatar:', error);
|
||||
|
|
@ -50,7 +47,7 @@ const getUserController = async (req, res) => {
|
|||
|
||||
const getTermsStatusController = async (req, res) => {
|
||||
try {
|
||||
const user = await User.findById(req.user.id);
|
||||
const user = await db.models.User.findById(req.user.id);
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'User not found' });
|
||||
}
|
||||
|
|
@ -63,7 +60,7 @@ const getTermsStatusController = async (req, res) => {
|
|||
|
||||
const acceptTermsController = async (req, res) => {
|
||||
try {
|
||||
const user = await User.findByIdAndUpdate(req.user.id, { termsAccepted: true }, { new: true });
|
||||
const user = await db.models.User.findByIdAndUpdate(req.user.id, { termsAccepted: true }, { new: true });
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'User not found' });
|
||||
}
|
||||
|
|
@ -160,7 +157,7 @@ const deleteUserController = async (req, res) => {
|
|||
|
||||
try {
|
||||
await deleteMessages({ user: user.id }); // delete user messages
|
||||
await deleteAllUserSessions({ userId: user.id }); // delete user sessions
|
||||
await db.models.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
|
||||
|
|
@ -168,7 +165,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 deleteUserById(user.id); // delete user
|
||||
await db.models.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
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ const {
|
|||
getTOTPSecret,
|
||||
} = require('~/server/services/twoFactorService');
|
||||
const { setAuthTokens } = require('~/server/services/AuthService');
|
||||
const { getUserById } = require('~/models/userMethods');
|
||||
const { logger } = require('~/config');
|
||||
const db = require('~/lib/db/connectDb');
|
||||
|
||||
/**
|
||||
* Verifies the 2FA code during login using a temporary token.
|
||||
|
|
@ -25,7 +25,7 @@ const verify2FAWithTempToken = async (req, res) => {
|
|||
return res.status(401).json({ message: 'Invalid or expired temporary token' });
|
||||
}
|
||||
|
||||
const user = await getUserById(payload.userId);
|
||||
const user = await db.models.User.getUserById(payload.userId);
|
||||
if (!user || !user.twoFactorEnabled) {
|
||||
return res.status(400).json({ message: '2FA is not enabled for this user' });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const mongoSanitize = require('express-mongo-sanitize');
|
|||
const fs = require('fs');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const { jwtLogin, passportLogin } = require('~/strategies');
|
||||
const { connectDb, indexSync } = require('~/lib/db');
|
||||
const { connectDb, indexSync, getModels } = require('~/lib/db');
|
||||
const { isEnabled } = require('~/server/utils');
|
||||
const { ldapLogin } = require('~/strategies');
|
||||
const { logger } = require('~/config');
|
||||
|
|
@ -36,6 +36,7 @@ const startServer = async () => {
|
|||
axios.defaults.headers.common['Accept-Encoding'] = 'gzip';
|
||||
}
|
||||
await connectDb();
|
||||
|
||||
logger.info('Connected to MongoDB');
|
||||
await indexSync();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ const { isEnabled, removePorts } = require('~/server/utils');
|
|||
const keyvMongo = require('~/cache/keyvMongo');
|
||||
const denyRequest = require('./denyRequest');
|
||||
const { getLogStores } = require('~/cache');
|
||||
const { findUser } = require('~/models');
|
||||
const { logger } = require('~/config');
|
||||
const db = require('~/lib/db/connectDb');
|
||||
|
||||
|
||||
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.';
|
||||
|
|
@ -57,7 +58,7 @@ const checkBan = async (req, res, next = () => {}) => {
|
|||
let userId = req.user?.id ?? req.user?._id ?? null;
|
||||
|
||||
if (!userId && req?.body?.email) {
|
||||
const user = await findUser({ email: req.body.email }, '_id');
|
||||
const user = await db.models.User.findUser({ email: req.body.email }, '_id');
|
||||
userId = user?._id ? user._id.toString() : userId;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
const { getInvite } = require('~/models/inviteUser');
|
||||
const { deleteTokens } = require('~/models/Token');
|
||||
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 deleteTokens({ token: invite.token });
|
||||
await db.models.Token.deleteTokens({ token: invite.token });
|
||||
req.invite = invite;
|
||||
next();
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
const { getBalanceConfig } = require('~/server/services/Config');
|
||||
const Balance = require('~/models/Balance');
|
||||
const { logger } = require('~/config');
|
||||
const db = require('~/lib/db/connectDb');
|
||||
|
||||
/**
|
||||
* Middleware to synchronize user balance settings with current balance configuration.
|
||||
|
|
@ -20,14 +20,14 @@ const setBalanceConfig = async (req, res, next) => {
|
|||
}
|
||||
|
||||
const userId = req.user._id;
|
||||
const userBalanceRecord = await Balance.findOne({ user: userId }).lean();
|
||||
const userBalanceRecord = await db.models.Balance.findOne({ user: userId }).lean();
|
||||
const updateFields = buildUpdateFields(balanceConfig, userBalanceRecord);
|
||||
|
||||
if (Object.keys(updateFields).length === 0) {
|
||||
return next();
|
||||
}
|
||||
|
||||
await Balance.findOneAndUpdate(
|
||||
await db.models.Balance.findOneAndUpdate(
|
||||
{ user: userId },
|
||||
{ $set: updateFields },
|
||||
{ upsert: true, new: true },
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ const { requireJwtAuth, validateMessageReq } = require('~/server/middleware');
|
|||
const { cleanUpPrimaryKeyValue } = require('~/lib/utils/misc');
|
||||
const { getConvosQueried } = require('~/models/Conversation');
|
||||
const { countTokens } = require('~/server/utils');
|
||||
const { Message } = require('~/models/Message');
|
||||
const { logger } = require('~/config');
|
||||
const db = require('~/lib/db/connectDb');
|
||||
|
||||
const router = express.Router();
|
||||
router.use(requireJwtAuth);
|
||||
|
|
@ -40,21 +40,25 @@ router.get('/', async (req, res) => {
|
|||
const sortOrder = sortDirection === 'asc' ? 1 : -1;
|
||||
|
||||
if (conversationId && messageId) {
|
||||
const message = await Message.findOne({ conversationId, messageId, user: user }).lean();
|
||||
const message = await db.models.Message.findOne({
|
||||
conversationId,
|
||||
messageId,
|
||||
user: user,
|
||||
}).lean();
|
||||
response = { messages: message ? [message] : [], nextCursor: null };
|
||||
} else if (conversationId) {
|
||||
const filter = { conversationId, user: user };
|
||||
if (cursor) {
|
||||
filter[sortField] = sortOrder === 1 ? { $gt: cursor } : { $lt: cursor };
|
||||
}
|
||||
const messages = await Message.find(filter)
|
||||
const messages = await db.models.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 Message.meiliSearch(search, undefined, true);
|
||||
const searchResults = await db.models.Message.meiliSearch(search, undefined, true);
|
||||
|
||||
const messages = searchResults.hits || [];
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ const { logger, getFlowStateManager, sendEvent } = require('~/config');
|
|||
const { encryptV2, decryptV2 } = require('~/server/utils/crypto');
|
||||
const { getActions, deleteActions } = require('~/models/Action');
|
||||
const { deleteAssistant } = require('~/models/Assistant');
|
||||
const { findToken } = require('~/models/Token');
|
||||
const { logAxiosError } = require('~/utils');
|
||||
const { getLogStores } = require('~/cache');
|
||||
const db = require('~/lib/db/connectDb');
|
||||
|
||||
const JWT_SECRET = process.env.JWT_SECRET;
|
||||
const toolNameRegex = /^[a-zA-Z0-9_-]+$/;
|
||||
|
|
@ -231,9 +231,10 @@ async function createActionTool({
|
|||
};
|
||||
|
||||
const tokenPromises = [];
|
||||
tokenPromises.push(findToken({ userId, type: 'oauth', identifier }));
|
||||
const { Token } = db.models;
|
||||
tokenPromises.push(Token.findToken({ userId, type: 'oauth', identifier }));
|
||||
tokenPromises.push(
|
||||
findToken({
|
||||
Token.findToken({
|
||||
userId,
|
||||
type: 'oauth_refresh',
|
||||
identifier: `${identifier}:refresh`,
|
||||
|
|
|
|||
|
|
@ -1,28 +1,12 @@
|
|||
const bcrypt = require('bcryptjs');
|
||||
const { webcrypto } = require('node:crypto');
|
||||
const { SystemRoles, errorsToString } = require('librechat-data-provider');
|
||||
const {
|
||||
findUser,
|
||||
countUsers,
|
||||
createUser,
|
||||
updateUser,
|
||||
getUserById,
|
||||
generateToken,
|
||||
deleteUserById,
|
||||
} = require('~/models/userMethods');
|
||||
const {
|
||||
createToken,
|
||||
findToken,
|
||||
deleteTokens,
|
||||
findSession,
|
||||
deleteSession,
|
||||
createSession,
|
||||
generateRefreshToken,
|
||||
} = require('~/models');
|
||||
const { isEnabled, checkEmailConfig, sendEmail } = require('~/server/utils');
|
||||
const { isEmailDomainAllowed } = require('~/server/services/domains');
|
||||
const { registerSchema } = require('~/strategies/validators');
|
||||
const { logger } = require('~/config');
|
||||
const db = require('~/lib/db/connectDb');
|
||||
const { getBalanceConfig } = require('~/server/services/Config');
|
||||
|
||||
const domains = {
|
||||
client: process.env.DOMAIN_CLIENT,
|
||||
|
|
@ -40,13 +24,14 @@ const genericVerificationMessage = 'Please check your email to verify your email
|
|||
* @returns
|
||||
*/
|
||||
const logoutUser = async (req, refreshToken) => {
|
||||
const { Session } = db.models;
|
||||
try {
|
||||
const userId = req.user._id;
|
||||
const session = await findSession({ userId: userId, refreshToken });
|
||||
const session = await Session.findSession({ userId: userId, refreshToken });
|
||||
|
||||
if (session) {
|
||||
try {
|
||||
await deleteSession({ sessionId: session._id });
|
||||
await Session.deleteSession({ sessionId: session._id });
|
||||
} catch (deleteErr) {
|
||||
logger.error('[logoutUser] Failed to delete session.', deleteErr);
|
||||
return { status: 500, message: 'Failed to delete session.' };
|
||||
|
|
@ -98,7 +83,7 @@ const sendVerificationEmail = async (user) => {
|
|||
template: 'verifyEmail.handlebars',
|
||||
});
|
||||
|
||||
await createToken({
|
||||
await db.models.Token.createToken({
|
||||
userId: user._id,
|
||||
email: user.email,
|
||||
token: hash,
|
||||
|
|
@ -117,7 +102,8 @@ const verifyEmail = async (req) => {
|
|||
const { email, token } = req.body;
|
||||
const decodedEmail = decodeURIComponent(email);
|
||||
|
||||
const user = await findUser({ email: decodedEmail }, 'email _id emailVerified');
|
||||
const { User, Token } = db.models;
|
||||
const user = await User.findUser({ email: decodedEmail }, 'email _id emailVerified');
|
||||
|
||||
if (!user) {
|
||||
logger.warn(`[verifyEmail] [User not found] [Email: ${decodedEmail}]`);
|
||||
|
|
@ -129,7 +115,7 @@ const verifyEmail = async (req) => {
|
|||
return { message: 'Email already verified', status: 'success' };
|
||||
}
|
||||
|
||||
let emailVerificationData = await findToken({ email: decodedEmail });
|
||||
let emailVerificationData = await Token.findToken({ email: decodedEmail });
|
||||
|
||||
if (!emailVerificationData) {
|
||||
logger.warn(`[verifyEmail] [No email verification data found] [Email: ${decodedEmail}]`);
|
||||
|
|
@ -145,13 +131,13 @@ const verifyEmail = async (req) => {
|
|||
return new Error('Invalid or expired email verification token');
|
||||
}
|
||||
|
||||
const updatedUser = await updateUser(emailVerificationData.userId, { emailVerified: true });
|
||||
const updatedUser = await User.updateUser(emailVerificationData.userId, { emailVerified: true });
|
||||
if (!updatedUser) {
|
||||
logger.warn(`[verifyEmail] [User update failed] [Email: ${decodedEmail}]`);
|
||||
return new Error('Failed to update user verification status');
|
||||
}
|
||||
|
||||
await deleteTokens({ token: emailVerificationData.token });
|
||||
await Token.deleteTokens({ token: emailVerificationData.token });
|
||||
logger.info(`[verifyEmail] Email verification successful [Email: ${decodedEmail}]`);
|
||||
return { message: 'Email verification was successful', status: 'success' };
|
||||
};
|
||||
|
|
@ -162,6 +148,7 @@ const verifyEmail = async (req) => {
|
|||
* @returns {Promise<{status: number, message: string, user?: MongoUser}>}
|
||||
*/
|
||||
const registerUser = async (user, additionalData = {}) => {
|
||||
const { User } = db.models;
|
||||
const { error } = registerSchema.safeParse(user);
|
||||
if (error) {
|
||||
const errorMessage = errorsToString(error.errors);
|
||||
|
|
@ -178,7 +165,7 @@ const registerUser = async (user, additionalData = {}) => {
|
|||
|
||||
let newUserId;
|
||||
try {
|
||||
const existingUser = await findUser({ email }, 'email _id');
|
||||
const existingUser = await User.findUser({ email }, 'email _id');
|
||||
|
||||
if (existingUser) {
|
||||
logger.info(
|
||||
|
|
@ -200,7 +187,7 @@ const registerUser = async (user, additionalData = {}) => {
|
|||
}
|
||||
|
||||
//determine if this is the first registered user (not counting anonymous_user)
|
||||
const isFirstRegisteredUser = (await countUsers()) === 0;
|
||||
const isFirstRegisteredUser = (await User.countUsers()) === 0;
|
||||
|
||||
const salt = bcrypt.genSaltSync(10);
|
||||
const newUserData = {
|
||||
|
|
@ -216,7 +203,9 @@ const registerUser = async (user, additionalData = {}) => {
|
|||
|
||||
const emailEnabled = checkEmailConfig();
|
||||
const disableTTL = isEnabled(process.env.ALLOW_UNVERIFIED_EMAIL_LOGIN);
|
||||
const newUser = await createUser(newUserData, disableTTL, true);
|
||||
const balanceConfig = await getBalanceConfig();
|
||||
|
||||
const newUser = await User.createUser(newUserData, balanceConfig, disableTTL, true);
|
||||
newUserId = newUser._id;
|
||||
if (emailEnabled && !newUser.emailVerified) {
|
||||
await sendVerificationEmail({
|
||||
|
|
@ -225,14 +214,14 @@ const registerUser = async (user, additionalData = {}) => {
|
|||
name,
|
||||
});
|
||||
} else {
|
||||
await updateUser(newUserId, { emailVerified: true });
|
||||
await User.updateUser(newUserId, { emailVerified: true });
|
||||
}
|
||||
|
||||
return { status: 200, message: genericVerificationMessage };
|
||||
} catch (err) {
|
||||
logger.error('[registerUser] Error in registering user:', err);
|
||||
if (newUserId) {
|
||||
const result = await deleteUserById(newUserId);
|
||||
const result = await User.deleteUserById(newUserId);
|
||||
logger.warn(
|
||||
`[registerUser] [Email: ${email}] [Temporary User deleted: ${JSON.stringify(result)}]`,
|
||||
);
|
||||
|
|
@ -247,7 +236,8 @@ const registerUser = async (user, additionalData = {}) => {
|
|||
*/
|
||||
const requestPasswordReset = async (req) => {
|
||||
const { email } = req.body;
|
||||
const user = await findUser({ email }, 'email _id');
|
||||
const { User, Token } = db.models;
|
||||
const user = await User.findUser({ email }, 'email _id');
|
||||
const emailEnabled = checkEmailConfig();
|
||||
|
||||
logger.warn(`[requestPasswordReset] [Password reset request initiated] [Email: ${email}]`);
|
||||
|
|
@ -259,11 +249,11 @@ const requestPasswordReset = async (req) => {
|
|||
};
|
||||
}
|
||||
|
||||
await deleteTokens({ userId: user._id });
|
||||
await Token.deleteTokens({ userId: user._id });
|
||||
|
||||
const [resetToken, hash] = createTokenHash();
|
||||
|
||||
await createToken({
|
||||
await Token.createToken({
|
||||
userId: user._id,
|
||||
token: hash,
|
||||
createdAt: Date.now(),
|
||||
|
|
@ -308,7 +298,8 @@ const requestPasswordReset = async (req) => {
|
|||
* @returns
|
||||
*/
|
||||
const resetPassword = async (userId, token, password) => {
|
||||
let passwordResetToken = await findToken({
|
||||
const { User, Token } = db.models;
|
||||
let passwordResetToken = await Token.findToken({
|
||||
userId,
|
||||
});
|
||||
|
||||
|
|
@ -323,7 +314,7 @@ const resetPassword = async (userId, token, password) => {
|
|||
}
|
||||
|
||||
const hash = bcrypt.hashSync(password, 10);
|
||||
const user = await updateUser(userId, { password: hash });
|
||||
const user = await User.updateUser(userId, { password: hash });
|
||||
|
||||
if (checkEmailConfig()) {
|
||||
await sendEmail({
|
||||
|
|
@ -338,7 +329,7 @@ const resetPassword = async (userId, token, password) => {
|
|||
});
|
||||
}
|
||||
|
||||
await deleteTokens({ token: passwordResetToken.token });
|
||||
await Token.deleteTokens({ token: passwordResetToken.token });
|
||||
logger.info(`[resetPassword] Password reset successful. [Email: ${user.email}]`);
|
||||
return { message: 'Password reset was successful' };
|
||||
};
|
||||
|
|
@ -353,19 +344,20 @@ const resetPassword = async (userId, token, password) => {
|
|||
*/
|
||||
const setAuthTokens = async (userId, res, sessionId = null) => {
|
||||
try {
|
||||
const user = await getUserById(userId);
|
||||
const token = await generateToken(user);
|
||||
const { User, Session } = db.models;
|
||||
const user = await User.getUserById(userId);
|
||||
const token = await User.generateToken(user);
|
||||
|
||||
let session;
|
||||
let refreshToken;
|
||||
let refreshTokenExpires;
|
||||
|
||||
if (sessionId) {
|
||||
session = await findSession({ sessionId: sessionId }, { lean: false });
|
||||
session = await Session.findSession({ sessionId: sessionId }, { lean: false });
|
||||
refreshTokenExpires = session.expiration.getTime();
|
||||
refreshToken = await generateRefreshToken(session);
|
||||
refreshToken = await Session.generateRefreshToken(session);
|
||||
} else {
|
||||
const result = await createSession(userId);
|
||||
const result = await Session.createSession(userId);
|
||||
session = result.session;
|
||||
refreshToken = result.refreshToken;
|
||||
refreshTokenExpires = session.expiration.getTime();
|
||||
|
|
@ -444,8 +436,9 @@ const setOpenIDAuthTokens = (tokenset, res) => {
|
|||
const resendVerificationEmail = async (req) => {
|
||||
try {
|
||||
const { email } = req.body;
|
||||
await deleteTokens(email);
|
||||
const user = await findUser({ email }, 'email _id name');
|
||||
const { User, Token } = db.models;
|
||||
await Token.deleteTokens(email);
|
||||
const user = await User.findUser({ email }, 'email _id name');
|
||||
|
||||
if (!user) {
|
||||
logger.warn(`[resendVerificationEmail] [No user found] [Email: ${email}]`);
|
||||
|
|
@ -470,7 +463,7 @@ const resendVerificationEmail = async (req) => {
|
|||
template: 'verifyEmail.handlebars',
|
||||
});
|
||||
|
||||
await createToken({
|
||||
await Token.createToken({
|
||||
userId: user._id,
|
||||
email: user.email,
|
||||
token: hash,
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@ const fs = require('fs');
|
|||
const path = require('path');
|
||||
const sharp = require('sharp');
|
||||
const { resizeImageBuffer } = require('../images/resize');
|
||||
const { updateUser } = require('~/models/userMethods');
|
||||
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.
|
||||
|
|
@ -108,7 +107,7 @@ async function processAzureAvatar({ buffer, userId, manual, basePath = 'images',
|
|||
const isManual = manual === 'true';
|
||||
const url = `${downloadURL}?manual=${isManual}`;
|
||||
if (isManual) {
|
||||
await updateUser(userId, { avatar: url });
|
||||
await db.models?.User.updateUser(userId, { avatar: url });
|
||||
}
|
||||
return url;
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ const fs = require('fs');
|
|||
const path = require('path');
|
||||
const sharp = require('sharp');
|
||||
const { resizeImageBuffer } = require('../images/resize');
|
||||
const { updateUser } = require('~/models/userMethods');
|
||||
const { saveBufferToFirebase } = require('./crud');
|
||||
const { updateFile } = require('~/models/File');
|
||||
const { logger } = require('~/config');
|
||||
const db = require('~/lib/db/connectDb');
|
||||
|
||||
/**
|
||||
* Converts an image file to the target format. The function first resizes the image based on the specified
|
||||
|
|
@ -99,7 +99,7 @@ async function processFirebaseAvatar({ buffer, userId, manual }) {
|
|||
const url = `${downloadURL}?manual=${isManual}`;
|
||||
|
||||
if (isManual) {
|
||||
await updateUser(userId, { avatar: url });
|
||||
await db.models.User.updateUser(userId, { avatar: url });
|
||||
}
|
||||
|
||||
return url;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ const fs = require('fs');
|
|||
const path = require('path');
|
||||
const sharp = require('sharp');
|
||||
const { resizeImageBuffer } = require('../images/resize');
|
||||
const { updateUser } = require('~/models/userMethods');
|
||||
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 updateUser(userId, { avatar: url });
|
||||
await db.models?.User.updateUser(userId, { avatar: url });
|
||||
}
|
||||
|
||||
return url;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ const fs = require('fs');
|
|||
const path = require('path');
|
||||
const sharp = require('sharp');
|
||||
const { resizeImageBuffer } = require('../images/resize');
|
||||
const { updateUser } = require('~/models/userMethods');
|
||||
const { saveBufferToS3 } = require('./crud');
|
||||
const { updateFile } = require('~/models/File');
|
||||
const { logger } = require('~/config');
|
||||
const db = require('~/lib/db/connectDb');
|
||||
|
||||
const defaultBasePath = 'images';
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ async function processS3Avatar({ buffer, userId, manual, basePath = defaultBaseP
|
|||
try {
|
||||
const downloadURL = await saveBufferToS3({ userId, buffer, fileName: 'avatar.png', basePath });
|
||||
if (manual === 'true') {
|
||||
await updateUser(userId, { avatar: downloadURL });
|
||||
await db.models?.User.updateUser(userId, { avatar: downloadURL });
|
||||
}
|
||||
return downloadURL;
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
const { ErrorTypes } = require('librechat-data-provider');
|
||||
const { encrypt, decrypt } = require('~/server/utils');
|
||||
const { updateUser, Key } = require('~/models');
|
||||
const { logger } = require('~/config');
|
||||
|
||||
const db = require('~/lib/db/connectDb');
|
||||
/**
|
||||
* Updates the plugins for a user based on the action specified (install/uninstall).
|
||||
* @async
|
||||
|
|
@ -17,10 +16,11 @@ const { logger } = require('~/config');
|
|||
const updateUserPluginsService = async (user, pluginKey, action) => {
|
||||
try {
|
||||
const userPlugins = user.plugins || [];
|
||||
const { User } = db.models;
|
||||
if (action === 'install') {
|
||||
return await updateUser(user._id, { plugins: [...userPlugins, pluginKey] });
|
||||
return await User.updateUser(user._id, { plugins: [...userPlugins, pluginKey] });
|
||||
} else if (action === 'uninstall') {
|
||||
return await updateUser(user._id, {
|
||||
return await User.updateUser(user._id, {
|
||||
plugins: userPlugins.filter((plugin) => plugin !== pluginKey),
|
||||
});
|
||||
}
|
||||
|
|
@ -42,7 +42,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 Key.findOne({ userId, name }).lean();
|
||||
const keyValue = await db.models.Key.findOne({ userId, name }).lean();
|
||||
if (!keyValue) {
|
||||
throw new Error(
|
||||
JSON.stringify({
|
||||
|
|
@ -89,7 +89,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 Key.findOne({ userId, name }).lean();
|
||||
const keyValue = await db.models.Key.findOne({ userId, name }).lean();
|
||||
if (!keyValue) {
|
||||
return { expiresAt: null };
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ const updateUserKey = async ({ userId, name, value, expiresAt = null }) => {
|
|||
// make sure to remove if already present
|
||||
updateQuery.$unset = { expiresAt };
|
||||
}
|
||||
return await Key.findOneAndUpdate({ userId, name }, updateQuery, {
|
||||
return await db.models.Key.findOneAndUpdate({ userId, name }, updateQuery, {
|
||||
upsert: true,
|
||||
new: true,
|
||||
}).lean();
|
||||
|
|
@ -143,10 +143,10 @@ const updateUserKey = async ({ userId, name, value, expiresAt = null }) => {
|
|||
*/
|
||||
const deleteUserKey = async ({ userId, name, all = false }) => {
|
||||
if (all) {
|
||||
return await Key.deleteMany({ userId });
|
||||
return await db.models.Key.deleteMany({ userId });
|
||||
}
|
||||
|
||||
await Key.findOneAndDelete({ userId, name }).lean();
|
||||
await db.models.Key.findOneAndDelete({ userId, name }).lean();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const { webcrypto } = require('node:crypto');
|
||||
const { decryptV3, decryptV2 } = require('../utils/crypto');
|
||||
const { hashBackupCode } = require('~/server/utils/crypto');
|
||||
const db = require('~/lib/db/connectDb');
|
||||
|
||||
// Base32 alphabet for TOTP secret encoding.
|
||||
const BASE32_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
|
||||
|
|
@ -172,8 +173,7 @@ const verifyBackupCode = async ({ user, backupCode }) => {
|
|||
: codeObj,
|
||||
);
|
||||
// Update the user record with the marked backup code.
|
||||
const { updateUser } = require('~/models');
|
||||
await updateUser(user._id, { backupCodes: updatedBackupCodes });
|
||||
await db.models.User.updateUser(user._id, { backupCodes: updatedBackupCodes });
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ const crypto = require('node:crypto');
|
|||
const { webcrypto } = crypto;
|
||||
|
||||
// Use hex decoding for both key and IV for legacy methods.
|
||||
const key = Buffer.from(process.env.CREDS_KEY, 'hex');
|
||||
const iv = Buffer.from(process.env.CREDS_IV, 'hex');
|
||||
const key = Buffer.from('f34be427ebb29de8d88c107a71546019685ed8b241d8f2ed00c3df97ad2566f0', 'hex');
|
||||
const iv = Buffer.from('e2341419ec3dd3d19b13a1a87fafcbfb', 'hex');
|
||||
const algorithm = 'AES-CBC';
|
||||
|
||||
// --- Legacy v1/v2 Setup: AES-CBC with fixed key and IV ---
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
jest.mock('~/models/Message', () => ({
|
||||
Message: jest.fn(),
|
||||
}));
|
||||
jest.mock('~/models/Conversation', () => ({
|
||||
Conversation: jest.fn(),
|
||||
}));
|
||||
const { isEnabled, sanitizeFilename } = require('./handleText');
|
||||
|
||||
describe('isEnabled', () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue