src/Voter/AccessTokenVoter.php line 30

Open in your IDE?
  1. <?php
  2. namespace App\Voter;
  3. use App\Controller\Front\AccessTokenController;
  4. use App\Entity\Trace;
  5. use DateInterval;
  6. use DateTime;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use Symfony\Component\HttpFoundation\RequestStack;
  9. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  10. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  11. class AccessTokenVoter extends Voter
  12. {
  13.     public const TRY_ACCESS_TOKEN 'try_access_token';
  14.     public const MAX_TRY_PER_TIMESPAN 5;
  15.     public const TIMESPAN_SECONDS 3600;
  16.     private $traceRepo;
  17.     private $requestStack;
  18.     public function __construct(
  19.         EntityManagerInterface $em,
  20.         RequestStack $requestStack
  21.     ) {
  22.         $this->traceRepo    $em->getRepository(Trace::class);
  23.         $this->requestStack $requestStack;
  24.     }
  25.     protected function supports($attribute$entity): bool
  26.     {
  27.         // if the attribute isn't one we support, return false
  28.         if ($attribute === self::TRY_ACCESS_TOKEN) {
  29.             return true;
  30.         }
  31.         return false;
  32.     }
  33.     protected function voteOnAttribute($attribute$entityTokenInterface $token): bool
  34.     {
  35.         if ($attribute === self::TRY_ACCESS_TOKEN) {
  36.             return $this->canTry();
  37.         }
  38.         return false;
  39.     }
  40.     private function canTry(): bool
  41.     {
  42.         /*
  43.          * Count all trace with same ip and same type in the timespan
  44.          */
  45.         $request $this->requestStack->getCurrentRequest();
  46.         $ip $request->getClientIp();
  47.         $after $this->buildTryAfterDT();
  48.         $similarTriesCount $this->traceRepo->searchCount([
  49.             'type'  => AccessTokenController::ACCESS_ROUTE_HIT,
  50.             'ip'    => $ip,
  51.             'after' => $after
  52.         ]);
  53.         return ($similarTriesCount <= self::MAX_TRY_PER_TIMESPAN);
  54.     }
  55.     private function buildTryInterval(): DateInterval
  56.     {
  57.         return new DateInterval('PT' self::TIMESPAN_SECONDS 'S');
  58.     }
  59.     private function buildTryAfterDT(): DateTime
  60.     {
  61.         $interval $this->buildTryInterval();
  62.         $after = new DateTime();
  63.         $after->sub($interval);
  64.         return $after;
  65.     }
  66. }