<?php
namespace App\EventListener;
use App\Manager\System\CustomerApiManager;
use App\Service\EnvironmentService;
use Noxlogic\RateLimitBundle\Annotation\RateLimit;
use Noxlogic\RateLimitBundle\Events\CheckedRateLimitEvent;
use Noxlogic\RateLimitBundle\Events\GenerateKeyEvent;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
class ApiRateLimitGenerateKeyListener
{
private CustomerApiManager $customerApiManager;
private bool $apiSandbox;
private EnvironmentService $environmentService;
public function __construct(
CustomerApiManager $customerApiManager,
ParameterBagInterface $parameterBag,
EnvironmentService $environmentService
) {
$this->customerApiManager = $customerApiManager;
$this->apiSandbox = $parameterBag->get('api_sandbox');
$this->environmentService = $environmentService;
}
public function onGenerateKey(GenerateKeyEvent $event): void
{
$event->addToKey($this->getBearerToken());
}
public function setRateLimit(CheckedRateLimitEvent $checkedRateLimitEvent): void
{
if (!$this->environmentService->isApi()) {
return;
}
if (!empty($checkedRateLimitEvent->getRequest()->query->get('parentTaxonomy'))) {
$checkedRateLimitEvent->setRateLimit(
new RateLimit([
'limit' => 30,
'period' => 60,
'methods' => ['*'],
])
);
return;
}
if (!$this->getBearerToken()) {
return;
}
$customerApi = $this->customerApiManager->findCustomerApi($this->getBearerToken(), $this->apiSandbox);
$roles = $customerApi ? $customerApi->getCustomer()->getRoles() : [];
if ($roles && in_array('ROLE_API_SYS', $roles, true)) {
$checkedRateLimitEvent->setRateLimit(
new RateLimit([
'limit' => 1000,
'period' => 60,
'methods' => ['*'],
])
);
}
}
public function getBearerToken(): ?string
{
$headers = $this->getAuthorizationHeader();
// HEADER: Get the access token from the header
if (!empty($headers) && preg_match('/Bearer\s(\S+)/', $headers, $matches)) {
return $matches[1];
}
return null;
}
public function getAuthorizationHeader(): ?string
{
$headers = null;
if (isset($_SERVER['Authorization'])) {
$headers = trim($_SERVER['Authorization']);
} elseif (isset($_SERVER['HTTP_AUTHORIZATION'])) { // Nginx or fast CGI
$headers = trim($_SERVER['HTTP_AUTHORIZATION']);
} elseif (function_exists('apache_request_headers')) {
$requestHeaders = getallheaders();
// 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)
$requestHeaders = array_combine(
array_map('ucwords', array_keys($requestHeaders)),
array_values($requestHeaders)
);
if (isset($requestHeaders['Authorization'])) {
$headers = trim($requestHeaders['Authorization']);
}
}
return $headers;
}
}