Skip to content

Instantly share code, notes, and snippets.

@teohhanhui
Created April 8, 2019 16:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save teohhanhui/994ab0d0bab439302ef96ac080568a8f to your computer and use it in GitHub Desktop.
Save teohhanhui/994ab0d0bab439302ef96ac080568a8f to your computer and use it in GitHub Desktop.
<?php
declare(strict_types=1);
namespace App\EventListener;
use App\Entity\Order;
use App\Enum\OrderStatus;
use Ds\Map;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
class OrderStatusAuthorizationListener
{
/**
* @var AuthorizationCheckerInterface
*/
private $authorizationChecker;
/**
* @var Map<Order, OrderStatus>
*/
private $initialOrderStatuses;
/**
* @param AuthorizationCheckerInterface $authorizationChecker
*/
public function __construct(AuthorizationCheckerInterface $authorizationChecker)
{
$this->authorizationChecker = $authorizationChecker;
$this->initialOrderStatuses = new Map();
}
/**
* @param GetResponseEvent $event
*/
public function onKernelRequestPostRead(GetResponseEvent $event): void
{
$request = $event->getRequest();
$data = $request->attributes->get('data');
if (!$data instanceof Order) {
return;
}
/** @var Order $order */
$order = $data;
if (!\in_array($request->getMethod(), [
Request::METHOD_POST,
Request::METHOD_PUT,
], true)) {
return;
}
$orderStatus = $order->getOrderStatus();
// Deny changing the order if order status is not draft
if (OrderStatus::ORDER_DRAFT !== $orderStatus->getValue()) {
// Allow for admin
if (!$this->authorizationChecker->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
}
}
$this->initialOrderStatuses->put($order, $orderStatus);
}
/**
* @param GetResponseEvent $event
*/
public function onKernelRequestPostDeserialize(GetResponseEvent $event): void
{
$request = $event->getRequest();
$data = $request->attributes->get('data');
if (!$data instanceof Order) {
return;
}
/** @var Order $order */
$order = $data;
if (!\in_array($request->getMethod(), [
Request::METHOD_POST,
Request::METHOD_PUT,
], true)) {
return;
}
$initialOrderStatus = $this->initialOrderStatuses->get($order, null);
$orderStatus = $order->getOrderStatus();
// Abstain if there is no change in the order status
if (null !== $initialOrderStatus && $initialOrderStatus->getValue() === $orderStatus->getValue()) {
return;
}
// Allow creating a draft order
if (null === $initialOrderStatus && OrderStatus::ORDER_DRAFT === $orderStatus->getValue()) {
return;
}
// Allow transitioning the order from draft status to payment due status
if (null !== $initialOrderStatus && OrderStatus::ORDER_DRAFT === $initialOrderStatus->getValue() && OrderStatus::ORDER_PAYMENT_DUE === $orderStatus->getValue()) {
return;
}
// Allow for admin
if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
return;
}
throw new AccessDeniedException();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment