Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(config/scripts): Enhance User Creation and Ban Handling, Standardize Imports #1144

Merged
merged 3 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions api/cache/banViolation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
64 changes: 52 additions & 12 deletions api/server/middleware/checkBan.js
Original file line number Diff line number Diff line change
@@ -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 })
Expand Down Expand Up @@ -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) {
Expand All @@ -72,24 +94,42 @@ 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();
}

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);
};
Expand Down
4 changes: 2 additions & 2 deletions api/server/services/AuthService.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion api/server/services/PluginService.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const updateUserPluginAuth = async (userId, authField, pluginKey, value) => {
value: encryptedValue,
pluginKey,
});
newPluginAuth.save();
await newPluginAuth.save();
return newPluginAuth;
}
} catch (err) {
Expand Down
6 changes: 3 additions & 3 deletions config/add-balance.js
Original file line number Diff line number Diff line change
@@ -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 () => {
/**
Expand Down
17 changes: 15 additions & 2 deletions config/ban-user.js
Original file line number Diff line number Diff line change
@@ -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 () => {
/**
Expand Down Expand Up @@ -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);
}
});
26 changes: 21 additions & 5 deletions config/create-user.js
Original file line number Diff line number Diff line change
@@ -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 () => {
/**
Expand Down Expand Up @@ -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);
}
});
Loading