File size: 2,488 Bytes
f0743f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
const rateLimit = require('express-rate-limit');
const { limiterCache } = require('@librechat/api');
const { ViolationTypes } = require('librechat-data-provider');
const logViolation = require('~/cache/logViolation');

const getEnvironmentVariables = () => {
  const FORK_IP_MAX = parseInt(process.env.FORK_IP_MAX) || 30;
  const FORK_IP_WINDOW = parseInt(process.env.FORK_IP_WINDOW) || 1;
  const FORK_USER_MAX = parseInt(process.env.FORK_USER_MAX) || 7;
  const FORK_USER_WINDOW = parseInt(process.env.FORK_USER_WINDOW) || 1;
  const FORK_VIOLATION_SCORE = process.env.FORK_VIOLATION_SCORE;

  const forkIpWindowMs = FORK_IP_WINDOW * 60 * 1000;
  const forkIpMax = FORK_IP_MAX;
  const forkIpWindowInMinutes = forkIpWindowMs / 60000;

  const forkUserWindowMs = FORK_USER_WINDOW * 60 * 1000;
  const forkUserMax = FORK_USER_MAX;
  const forkUserWindowInMinutes = forkUserWindowMs / 60000;

  return {
    forkIpWindowMs,
    forkIpMax,
    forkIpWindowInMinutes,
    forkUserWindowMs,
    forkUserMax,
    forkUserWindowInMinutes,
    forkViolationScore: FORK_VIOLATION_SCORE,
  };
};

const createForkHandler = (ip = true) => {
  const {
    forkIpMax,
    forkUserMax,
    forkViolationScore,
    forkIpWindowInMinutes,
    forkUserWindowInMinutes,
  } = getEnvironmentVariables();

  return async (req, res) => {
    const type = ViolationTypes.FILE_UPLOAD_LIMIT;
    const errorMessage = {
      type,
      max: ip ? forkIpMax : forkUserMax,
      limiter: ip ? 'ip' : 'user',
      windowInMinutes: ip ? forkIpWindowInMinutes : forkUserWindowInMinutes,
    };

    await logViolation(req, res, type, errorMessage, forkViolationScore);
    res.status(429).json({ message: 'Too many conversation fork requests. Try again later' });
  };
};

const createForkLimiters = () => {
  const { forkIpWindowMs, forkIpMax, forkUserWindowMs, forkUserMax } = getEnvironmentVariables();

  const ipLimiterOptions = {
    windowMs: forkIpWindowMs,
    max: forkIpMax,
    handler: createForkHandler(),
    store: limiterCache('fork_ip_limiter'),
  };
  const userLimiterOptions = {
    windowMs: forkUserWindowMs,
    max: forkUserMax,
    handler: createForkHandler(false),
    keyGenerator: function (req) {
      return req.user?.id;
    },
    store: limiterCache('fork_user_limiter'),
  };

  const forkIpLimiter = rateLimit(ipLimiterOptions);
  const forkUserLimiter = rateLimit(userLimiterOptions);
  return { forkIpLimiter, forkUserLimiter };
};

module.exports = { createForkLimiters };