src/EventListener/ApiRateLimitGenerateKeyListener.php line 35

Open in your IDE?
  1. <?php
  2. namespace App\EventListener;
  3. use App\Manager\System\CustomerApiManager;
  4. use App\Service\EnvironmentService;
  5. use Noxlogic\RateLimitBundle\Annotation\RateLimit;
  6. use Noxlogic\RateLimitBundle\Events\CheckedRateLimitEvent;
  7. use Noxlogic\RateLimitBundle\Events\GenerateKeyEvent;
  8. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  9. class ApiRateLimitGenerateKeyListener
  10. {
  11. private CustomerApiManager $customerApiManager;
  12. private bool $apiSandbox;
  13. private EnvironmentService $environmentService;
  14. public function __construct(
  15. CustomerApiManager $customerApiManager,
  16. ParameterBagInterface $parameterBag,
  17. EnvironmentService $environmentService,
  18. ) {
  19. $this->customerApiManager = $customerApiManager;
  20. $this->apiSandbox = $parameterBag->get('api_sandbox');
  21. $this->environmentService = $environmentService;
  22. }
  23. public function onGenerateKey(GenerateKeyEvent $event): void
  24. {
  25. $event->addToKey($this->getBearerToken());
  26. }
  27. public function setRateLimit(CheckedRateLimitEvent $checkedRateLimitEvent): void
  28. {
  29. if (!$this->environmentService->isApi()) {
  30. return;
  31. }
  32. if (!empty($checkedRateLimitEvent->getRequest()->query->get('parentTaxonomy'))) {
  33. $checkedRateLimitEvent->setRateLimit(
  34. new RateLimit([
  35. 'limit' => 30,
  36. 'period' => 60,
  37. 'methods' => ['*'],
  38. ])
  39. );
  40. return;
  41. }
  42. if (!$this->getBearerToken()) {
  43. return;
  44. }
  45. $customerApi = $this->customerApiManager->findCustomerApi($this->getBearerToken(), $this->apiSandbox);
  46. $roles = $customerApi ? $customerApi->getCustomer()->getRoles() : [];
  47. if ($roles && in_array('ROLE_API_SYS', $roles, true)) {
  48. $checkedRateLimitEvent->setRateLimit(
  49. new RateLimit([
  50. 'limit' => 100000,
  51. 'period' => 60,
  52. 'methods' => ['*'],
  53. ])
  54. );
  55. }
  56. }
  57. public function getBearerToken(): ?string
  58. {
  59. $headers = $this->getAuthorizationHeader();
  60. // HEADER: Get the access token from the header
  61. if (!empty($headers) && preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
  62. return $matches[1];
  63. }
  64. return null;
  65. }
  66. public function getAuthorizationHeader(): ?string
  67. {
  68. $headers = null;
  69. if (isset($_SERVER['Authorization'])) {
  70. $headers = trim($_SERVER['Authorization']);
  71. } elseif (isset($_SERVER['HTTP_AUTHORIZATION'])) { // Nginx or fast CGI
  72. $headers = trim($_SERVER['HTTP_AUTHORIZATION']);
  73. } elseif (function_exists('apache_request_headers')) {
  74. $requestHeaders = getallheaders();
  75. // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization)
  76. $requestHeaders = array_combine(
  77. array_map('ucwords', array_keys($requestHeaders)),
  78. array_values($requestHeaders)
  79. );
  80. if (isset($requestHeaders['Authorization'])) {
  81. $headers = trim($requestHeaders['Authorization']);
  82. }
  83. }
  84. return $headers;
  85. }
  86. }