Blame view

app/Support/SearchGuard.php 1.81 KB
e77200db5   nologostudio.ru   Initial commit
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
  <?php
  
  namespace FootyRoom\Support;
  
  use Illuminate\Http\Request;
  use FootyRoom\User\BanCreator;
  use FootyRoom\Repositories\BanRepository;
  use Illuminate\Cache\RateLimiter;
  use Illuminate\Support\Str;
  use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
  
  class SearchGuard
  {
      /** @var int */
      protected const LIMIT = 200;
  
      protected const LIMIT_AWS = 1;
  
      /** @var int */
      protected const RESET_INTERVAL_MINUTES = 1440;
  
      /** @var int */
      protected const BAN_SECONDS = 43200;
  
      /** @var string */
      protected const KEY_PREFIX = 'search_';
  
      /** @var \FootyRoom\Repositories\BanRepository */
      protected $banRepo;
  
      /** @var \FootyRoom\User\BanCreator */
      protected $banCreator;
  
      /** @var \Illuminate\Cache\RateLimiter */
      protected $rateLimiter;
  
      public function __construct(
          BanRepository $banRepo,
          BanCreator $banCreator,
          RateLimiter $rateLimiter
      ) {
          $this->banRepo = $banRepo;
          $this->banCreator = $banCreator;
          $this->rateLimiter = $rateLimiter;
      }
  
      public function check(Request $request): void
      {
          $ip = $request->ip();
          $key = self::KEY_PREFIX.$ip;
  
          $this->rateLimiter->hit($key, self::RESET_INTERVAL_MINUTES);
  
          $ban = $this->banRepo->findActive('ip', $ip, 'search');
  
          if ($ban) {
              throw new TooManyRequestsHttpException();
          }
  
          if ($this->rateLimiter->tooManyAttempts($key, $this->getLimit($ip))) {
              $this->banCreator->create('ip', $ip, 'search', self::BAN_SECONDS, 0);
  
              throw new TooManyRequestsHttpException();
          }
      }
  
      protected function getLimit(string $ip): int
      {
          if (Str::endsWith(gethostbyaddr($ip), 'amazonaws.com')) {
              return self::LIMIT_AWS;
          }
  
          return self::LIMIT;
      }
  }