diff --git a/api/cache/banViolation.js b/api/cache/banViolation.js index f683f82afb4..e0ae26319e3 100644 --- a/api/cache/banViolation.js +++ b/api/cache/banViolation.js @@ -54,11 +54,17 @@ const banViolation = async (req, res, errorMessage) => { } req.ip = removePorts(req); - console.log(`[BAN] Banning user ${user_id} @ ${req.ip} for ${duration / 1000 / 60} minutes`); + console.log( + `[BAN] Banning user ${user_id} ${req.ip ? `@ ${req.ip} ` : ''}for ${ + duration / 1000 / 60 + } minutes`, + ); const expiresAt = Date.now() + duration; await banLogs.set(user_id, { type, violation_count, duration, expiresAt }); - await banLogs.set(req.ip, { type, user_id, violation_count, duration, expiresAt }); + if (req.ip) { + await banLogs.set(req.ip, { type, user_id, violation_count, duration, expiresAt }); + } errorMessage.ban = true; errorMessage.ban_duration = duration; diff --git a/api/server/middleware/checkBan.js b/api/server/middleware/checkBan.js index c744dda07d5..a7eab87bdfc 100644 --- a/api/server/middleware/checkBan.js +++ b/api/server/middleware/checkBan.js @@ -1,9 +1,10 @@ const Keyv = require('keyv'); const uap = require('ua-parser-js'); -const { getLogStores } = require('../../cache'); const denyRequest = require('./denyRequest'); +const { getLogStores } = require('../../cache'); const { isEnabled, removePorts } = require('../utils'); const keyvRedis = require('../../cache/keyvRedis'); +const User = require('../../models/User'); const banCache = isEnabled(process.env.USE_REDIS) ? new Keyv({ store: keyvRedis }) @@ -52,12 +53,33 @@ const checkBan = async (req, res, next = () => {}) => { } req.ip = removePorts(req); - const userId = req.user?.id ?? req.user?._id ?? null; - const ipKey = isEnabled(process.env.USE_REDIS) ? `ban_cache:ip:${req.ip}` : req.ip; - const userKey = isEnabled(process.env.USE_REDIS) ? `ban_cache:user:${userId}` : userId; + let userId = req.user?.id ?? req.user?._id ?? null; + + if (!userId && req?.body?.email) { + const user = await User.findOne({ email: req.body.email }, '_id').lean(); + userId = user?._id ? user._id.toString() : userId; + } + + if (!userId && !req.ip) { + return next(); + } + + let cachedIPBan; + let cachedUserBan; + + let ipKey = ''; + let userKey = ''; + + if (req.ip) { + ipKey = isEnabled(process.env.USE_REDIS) ? `ban_cache:ip:${req.ip}` : req.ip; + cachedIPBan = await banCache.get(ipKey); + } + + if (userId) { + userKey = isEnabled(process.env.USE_REDIS) ? `ban_cache:user:${userId}` : userId; + cachedUserBan = await banCache.get(userKey); + } - const cachedIPBan = await banCache.get(ipKey); - const cachedUserBan = await banCache.get(userKey); const cachedBan = cachedIPBan || cachedUserBan; if (cachedBan) { @@ -72,9 +94,18 @@ const checkBan = async (req, res, next = () => {}) => { return next(); } - const ipBan = await banLogs.get(req.ip); - const userBan = await banLogs.get(userId); - const isBanned = ipBan || userBan; + let ipBan; + let userBan; + + if (req.ip) { + ipBan = await banLogs.get(req.ip); + } + + if (userId) { + userBan = await banLogs.get(userId); + } + + const isBanned = !!(ipBan || userBan); if (!isBanned) { return next(); @@ -82,14 +113,23 @@ const checkBan = async (req, res, next = () => {}) => { const timeLeft = Number(isBanned.expiresAt) - Date.now(); - if (timeLeft <= 0) { + if (timeLeft <= 0 && ipKey) { await banLogs.delete(ipKey); + } + + if (timeLeft <= 0 && userKey) { await banLogs.delete(userKey); return next(); } - banCache.set(ipKey, isBanned, timeLeft); - banCache.set(userKey, isBanned, timeLeft); + if (ipKey) { + banCache.set(ipKey, isBanned, timeLeft); + } + + if (userKey) { + banCache.set(userKey, isBanned, timeLeft); + } + req.banned = true; return await banResponse(req, res); }; diff --git a/api/server/services/AuthService.js b/api/server/services/AuthService.js index fc792eceaa8..5be5529c964 100644 --- a/api/server/services/AuthService.js +++ b/api/server/services/AuthService.js @@ -91,7 +91,7 @@ const registerUser = async (user) => { const salt = bcrypt.genSaltSync(10); const hash = bcrypt.hashSync(newUser.password, salt); newUser.password = hash; - newUser.save(); + await newUser.save(); return { status: 200, user: newUser }; } catch (err) { @@ -117,7 +117,7 @@ const requestPasswordReset = async (email) => { } let resetToken = crypto.randomBytes(32).toString('hex'); - const hash = await bcrypt.hashSync(resetToken, 10); + const hash = bcrypt.hashSync(resetToken, 10); await new Token({ userId: user._id, diff --git a/api/server/services/PluginService.js b/api/server/services/PluginService.js index e96de6be938..8e8643cbfeb 100644 --- a/api/server/services/PluginService.js +++ b/api/server/services/PluginService.js @@ -58,7 +58,7 @@ const updateUserPluginAuth = async (userId, authField, pluginKey, value) => { value: encryptedValue, pluginKey, }); - newPluginAuth.save(); + await newPluginAuth.save(); return newPluginAuth; } } catch (err) { diff --git a/config/add-balance.js b/config/add-balance.js index cec03dd9f55..a6069733c67 100644 --- a/config/add-balance.js +++ b/config/add-balance.js @@ -1,7 +1,7 @@ -const connectDb = require('@librechat/backend/lib/db/connectDb'); +const connectDb = require('../api/lib/db/connectDb'); const { askQuestion, silentExit } = require('./helpers'); -const User = require('@librechat/backend/models/User'); -const Transaction = require('@librechat/backend/models/Transaction'); +const User = require('../api/models/User'); +const Transaction = require('../api/models/Transaction'); (async () => { /** diff --git a/config/ban-user.js b/config/ban-user.js index c73d662cf46..45e628aeca4 100644 --- a/config/ban-user.js +++ b/config/ban-user.js @@ -1,7 +1,7 @@ -const connectDb = require('@librechat/backend/lib/db/connectDb'); +const connectDb = require('../api/lib/db/connectDb'); const { askQuestion, silentExit } = require('./helpers'); const banViolation = require('../api/cache/banViolation'); -const User = require('@librechat/backend/models/User'); +const User = require('../api/models/User'); (async () => { /** @@ -97,3 +97,16 @@ const User = require('@librechat/backend/models/User'); silentExit(0); })(); + +process.on('uncaughtException', (err) => { + if (!err.message.includes('fetch failed')) { + console.error('There was an uncaught error:'); + console.error(err); + } + + if (err.message.includes('fetch failed')) { + return; + } else { + process.exit(1); + } +}); diff --git a/config/create-user.js b/config/create-user.js index a900bd54c04..c854b137a96 100644 --- a/config/create-user.js +++ b/config/create-user.js @@ -1,7 +1,7 @@ -const connectDb = require('@librechat/backend/lib/db/connectDb'); -const { registerUser } = require('@librechat/backend/server/services/AuthService'); +const connectDb = require('../api/lib/db/connectDb'); +const { registerUser } = require('../api/server/services/AuthService'); const { askQuestion, silentExit } = require('./helpers'); -const User = require('@librechat/backend/models/User'); +const User = require('../api/models/User'); (async () => { /** @@ -127,6 +127,22 @@ const User = require('@librechat/backend/models/User'); } // Done! - console.green('User created successfully!'); - silentExit(0); + const userCreated = await User.findOne({ $or: [{ email }, { username }] }); + if (userCreated) { + console.green('User created successfully!'); + silentExit(0); + } })(); + +process.on('uncaughtException', (err) => { + if (!err.message.includes('fetch failed')) { + console.error('There was an uncaught error:'); + console.error(err); + } + + if (err.message.includes('fetch failed')) { + return; + } else { + process.exit(1); + } +});