|
|
|
<?php
|
|
|
|
namespace vierbergenlars\AuthserverTosBundle\EventListener;
|
|
|
|
|
|
|
|
use Admin\AdminEvents;
|
|
|
|
use Admin\Event\FilterListEvent;
|
|
|
|
use App\Entity\User;
|
|
|
|
use Doctrine\Common\Collections\Criteria;
|
|
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
|
|
use Registration\RegistrationEvents;
|
|
|
|
use Registration\Event\RegistrationFormEvent;
|
|
|
|
use Registration\Event\RegistrationHandleEvent;
|
|
|
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
|
|
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
|
|
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
|
|
|
use Symfony\Component\HttpKernel\KernelEvents;
|
|
|
|
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
|
|
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
|
|
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
|
|
|
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
|
|
|
use vierbergenlars\AuthserverTosBundle\Entity\UserTos;
|
|
|
|
use vierbergenlars\AuthserverTosBundle\Form\AcceptTosType;
|
|
|
|
use Psr\Cache\CacheItemPoolInterface;
|
|
|
|
|
|
|
|
class TosListener implements EventSubscriberInterface
|
|
|
|
{
|
|
|
|
|
|
|
|
private $terms;
|
|
|
|
|
|
|
|
private $tosVersion;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @var EntityManagerInterface
|
|
|
|
*/
|
|
|
|
private $em;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var CacheItemPoolInterface
|
|
|
|
*/
|
|
|
|
private $cache;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @var TokenStorageInterface
|
|
|
|
*/
|
|
|
|
private $tokenStorage;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @var UrlGeneratorInterface
|
|
|
|
*/
|
|
|
|
private $urlGenerator;
|
|
|
|
|
|
|
|
public static function getSubscribedEvents()
|
|
|
|
{
|
|
|
|
$handlers = [
|
|
|
|
RegistrationEvents::BUILD_FORM => [
|
|
|
|
'onBuildForm',
|
|
|
|
-200
|
|
|
|
],
|
|
|
|
RegistrationEvents::HANDLE_FORM => [
|
|
|
|
'onHandleForm',
|
|
|
|
-20 // After persisting user
|
|
|
|
],
|
|
|
|
KernelEvents::REQUEST => 'onKernelRequest'
|
|
|
|
];
|
|
|
|
|
|
|
|
if (class_exists(AdminEvents::class) && defined(AdminEvents::class . '::FILTER_LIST')) {
|
|
|
|
$handlers[AdminEvents::FILTER_LIST] = [
|
|
|
|
[
|
|
|
|
'onFilterListCreateForm',
|
|
|
|
10
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'onFilterListFilter',
|
|
|
|
-10
|
|
|
|
]
|
|
|
|
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $handlers;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __construct($terms, $tosVersion, CacheItemPoolInterface $cache, EntityManagerInterface $em, TokenStorageInterface $tokenStorage, UrlGeneratorInterface $urlGenerator)
|
|
|
|
{
|
|
|
|
$this->terms = $terms;
|
|
|
|
$this->tosVersion = $tosVersion;
|
|
|
|
$this->cache = $cache;
|
|
|
|
$this->em = $em;
|
|
|
|
$this->tokenStorage = $tokenStorage;
|
|
|
|
$this->urlGenerator = $urlGenerator;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function onBuildForm(RegistrationFormEvent $event)
|
|
|
|
{
|
|
|
|
$event->getFormBuilder()->add('vl_tos', AcceptTosType::class, [
|
|
|
|
'terms' => $this->terms,
|
|
|
|
'mapped' => false
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function onHandleForm(RegistrationHandleEvent $event)
|
|
|
|
{
|
|
|
|
if ($event->getForm()
|
|
|
|
->get('vl_tos')
|
|
|
|
->getData()['accept']) {
|
|
|
|
$user = $event->getForm()->getData();
|
|
|
|
/* @var $user \App\Entity\User */
|
|
|
|
$tosUser = new UserTos($user);
|
|
|
|
$tosUser->setAcceptedVersion($this->tosVersion);
|
|
|
|
$this->em->persist($tosUser);
|
|
|
|
$this->cache->deleteItem('version_u_'.$user->getId());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private function getAcceptedTosVersion(User $user, $force = false) {
|
|
|
|
$cacheItem = $this->cache->getItem('version_u_'.$user->getId());
|
|
|
|
if(!$cacheItem->isHit() || $force) {
|
|
|
|
$userTos = $this->em->find(UserTos::class, $user);
|
|
|
|
|
|
|
|
if($userTos) {
|
|
|
|
$cacheItem->set($userTos->getAcceptedVersion());
|
|
|
|
} else {
|
|
|
|
$cacheItem->set(null);
|
|
|
|
}
|
|
|
|
|
|
|
|
$cacheItem->expiresAfter(24*60*60); // One day
|
|
|
|
$this->cache->saveDeferred($cacheItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $cacheItem->get();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function onKernelRequest(GetResponseEvent $event)
|
|
|
|
{
|
|
|
|
if (!$event->isMasterRequest())
|
|
|
|
return;
|
|
|
|
if (!($token = $this->tokenStorage->getToken()))
|
|
|
|
return;
|
|
|
|
if (!($user = $token->getUser()))
|
|
|
|
return;
|
|
|
|
if (!($user instanceof User))
|
|
|
|
return;
|
|
|
|
if ($token->hasAttribute('vl_tos_accept_ok'))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ($this->getAcceptedTosVersion($user) >= $this->tosVersion) {
|
|
|
|
$token->setAttribute('vl_tos_accept_ok', true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($event->getRequest()->getRequestFormat() !== 'html') {
|
|
|
|
throw new AccessDeniedHttpException('You need to accept the latest version of the terms of service.');
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ($event->getRequest()->attributes->get('_route')) {
|
|
|
|
case 'vl_tos_accept':
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
$response = RedirectResponse::create($this->urlGenerator->generate('vl_tos_accept'));
|
|
|
|
$event->setResponse($response);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function onFilterListCreateForm(FilterListEvent $event)
|
|
|
|
{
|
|
|
|
$event->getSearchFormBuilder()->add('tos_accepted', ChoiceType::class, [
|
|
|
|
'choices' => [
|
|
|
|
'Yes' => '1',
|
|
|
|
'No' => '0'
|
|
|
|
],
|
|
|
|
'expanded' => true,
|
|
|
|
'required' => false
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function onFilterListFilter(FilterListEvent $event)
|
|
|
|
{
|
|
|
|
$field = $event->getSearchForm()->get('tos_accepted');
|
|
|
|
if ($field->isEmpty() || $field->getData() === null)
|
|
|
|
return;
|
|
|
|
$toses = $this->em->createQueryBuilder()
|
|
|
|
->select('t')
|
|
|
|
->from(UserTos::class, 't')
|
|
|
|
->where('t.acceptedVersion >= :currentVersion')
|
|
|
|
->setParameter('currentVersion', $this->tosVersion)
|
|
|
|
->groupBy('t.user')
|
|
|
|
->getQuery()
|
|
|
|
->getArrayResult();
|
|
|
|
|
|
|
|
$userIds = array_map(function ($tos) {
|
|
|
|
return $tos['user_id'];
|
|
|
|
}, $toses);
|
|
|
|
|
|
|
|
$expr = $field->getData() === "1" ? Criteria::expr()->in('id', $userIds) : Criteria::expr()->notIn('id', $userIds);
|
|
|
|
|
|
|
|
$event->addFilter('tos_accepted', $expr);
|
|
|
|
}
|
|
|
|
}
|