<?php
namespace App\EventSubscriber\AuthenticationToken;
use App\Entity\Referral;
use App\Service\AuthenticationTokenService;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
class AuthenticationTokenSubscriber
{
protected $doctrine;
protected $router;
/** @var AuthenticationTokenService $tokenService **/
protected $tokenService;
protected $authenticationKey;
protected $authenticationSecret;
private $logger;
public function __construct(ManagerRegistry $doctrine, UrlGeneratorInterface $router, AuthenticationTokenService $tokenService, $authenticationKey, $authenticationSecret, LoggerInterface $logger)
{
$this->doctrine = $doctrine;
$this->router = $router;
$this->tokenService = $tokenService;
$this->authenticationKey = $authenticationKey;
$this->authenticationSecret = $authenticationSecret;
$this->logger = $logger;
}
protected function checkTokenReview(RequestEvent $event)
{
$request = $event->getRequest();
$checkPath = '/api/authentication_tokens/review';
if ($request->getRequestUri() !== $checkPath || $request->getMethod() !== 'POST') {
return false;
}
$headers = $request->headers;
$authenticationTokenUid = $headers->get('authorization', null);
if (! $authenticationTokenUid) {
return false;
}
$token = $this->tokenService->getTokenByUid($authenticationTokenUid);
if (! $token) {
return false;
}
if ($token->getAccessTimestamp()) {
return false;
}
$uid = $token->getUid();
$url = $this->router->generate('views_external_referral_review', [
'token' => $uid
], UrlGeneratorInterface::ABSOLUTE_URL);
$response = new JsonResponse([
'url' => $url
]);
$event->setResponse($response);
return true;
}
protected function checkTokenRequest(RequestEvent $event)
{
$request = $event->getRequest();
$checkPath = '/api/authentication_tokens/request';
if ($request->getRequestUri() !== $checkPath || $request->getMethod() !== 'POST') {
return false;
}
$content = json_decode($request->getContent(), true);
try {
$key = $content['key'];
$secret = $content['secret'];
$referralId = $content['referral'];
$userData = $content['user'];
} catch (\Exception $ex) {
throw new BadRequestException("Invalid request data");
}
$systemKey = $this->authenticationKey;
$systemSecret = $this->authenticationSecret;
if (! $key) {
throw new BadRequestException("Authentication key must be submitted");
}
if (! $secret) {
throw new BadRequestException("Authentication secret must be submitted");
}
if (! $referralId) {
throw new BadRequestException("Authentication referral must be submitted");
}
if (! $userData) {
throw new BadRequestException("Authentication user must be submitted");
}
if ($key !== $systemKey || $secret !== $systemSecret) {
throw new BadRequestException("Could not authenticate");
}
$referralRepository = $this->doctrine->getRepository(Referral::class);
$referral = null;
try {
$referral = $referralRepository->findOneBy([
'submissionId' => $referralId
]);
} catch (\Exception $ex) {}
if (! $referral) {
throw new BadRequestException("Invalid referral submitted");
}
$clientIps = $request->headers->get('x-forwarded-for') ?: json_encode($request->getClientIps());
$requestorInformation = $clientIps;
$token = $this->tokenService->generateToken($referral, $requestorInformation, $userData);
$response = new JsonResponse([
'uid' => $token->getUid()
]);
$event->setResponse($response);
return true;
}
protected function checkTokenStatusUpdate(RequestEvent $event)
{
$request = $event->getRequest();
$checkPaths = [
'/api/authentication_tokens/received',
'/api/authentication_tokens/processed',
'/api/authentication_tokens/eligible',
'/api/authentication_tokens/not_eligible',
'/api/authentication_tokens/rejected',
'/api/authentication_tokens/unable_to_contact'
];
if (! in_array($request->getRequestUri(), $checkPaths) || $request->getMethod() !== 'POST') {
return false;
}
$content = json_decode($request->getContent(), true);
$comments = null;
$serviceCoordinator = null;
$serviceCoordinatorEs = null;
$eligibilityDetermination = null;
$eligibilityDeterminationEs = null;
$statusDetails = null;
$statusDetailsEs = null;
$status = null;
switch ($request->getRequestUri()) {
case '/api/authentication_tokens/received':
$status = Referral::STATUS_RECEIVED;
break;
case '/api/authentication_tokens/processed':
$status = Referral::STATUS_PROCESSED;
break;
case '/api/authentication_tokens/eligible':
$status = Referral::STATUS_ELIGIBLE;
$serviceCoordinator = $content['service_coordinator'] ?? null;
$serviceCoordinatorEs = $content['service_coordinator_es'] ?? null;
$eligibilityDetermination = $content['eligibility_determination'] ?? null;
$eligibilityDeterminationEs = $content['eligibility_determination_es'] ?? null;
$statusDetails = $content['status_details'] ?? null;
$statusDetailsEs = $content['status_details_es'] ?? null;
break;
case '/api/authentication_tokens/not_eligible':
$status = Referral::STATUS_NOT_ELIGIBLE;
$serviceCoordinator = $content['service_coordinator'] ?? null;
$serviceCoordinatorEs = $content['service_coordinator_es'] ?? null;
break;
case '/api/authentication_tokens/rejected':
$status = Referral::STATUS_REJECTED;
$comments = $content['comments'] ?? null;
break;
case '/api/authentication_tokens/unable_to_contact':
$status = Referral::STATUS_UNABLE_TO_CONTACT;
$serviceCoordinator = $content['service_coordinator'] ?? null;
$serviceCoordinatorEs = $content['service_coordinator_es'] ?? null;
$statusDetails = $content['status_details'] ?? null;
$statusDetailsEs = $content['status_details_es'] ?? null;
break;
}
$headers = $request->headers;
$authenticationTokenUid = $headers->get('authorization', null);
if (! $authenticationTokenUid) {
return false;
}
$token = $this->tokenService->getTokenByUid($authenticationTokenUid);
if (! $token) {
return false;
}
if ($token->getExpirationTimestamp()) {
return false;
}
$clientIps = $request->headers->get('x-forwarded-for') ?: json_encode($request->getClientIps());
$accessorInformation = $clientIps;
$accessTimestamp = new \DateTime("now");
$referral = $token->getReferral();
$token->setAccessorInformation($accessorInformation);
$token->setAccessTimestamp($accessTimestamp);
$token->setExpirationTimestamp($accessTimestamp);
$referral->setStatus($status);
$referral->setComments($comments);
$referral->setServiceCoordinator($serviceCoordinator);
$referral->setServiceCoordinatorEs($serviceCoordinatorEs);
$referral->setEligibilityDetermination($eligibilityDetermination);
$referral->setEligibilityDeterminationEs($eligibilityDeterminationEs);
$referral->setStatusDetails($statusDetails);
$referral->setStatusDetailsEs($statusDetailsEs);
$this->doctrine->getManager()->persist($token);
$this->doctrine->getManager()->persist($referral);
$this->doctrine->getManager()->flush();
$response = new JsonResponse([
'status' => $referral->getStatus()
]);
$event->setResponse($response);
return true;
}
public function onKernelRequest(RequestEvent $event)
{
if ($this->checkTokenRequest($event)) {
return;
}
if ($this->checkTokenReview($event)) {
return;
}
if ($this->checkTokenStatusUpdate($event)) {
return;
}
return;
}
}