Move tos form to a separate form type, add a request interceptor to redirect to accept TOS when they have not accepted the latest version
parent
d1ea33b0bf
commit
2640823988
@ -0,0 +1,55 @@ |
||||
<?php |
||||
namespace vierbergenlars\AuthserverTosBundle\Controller; |
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
||||
use Symfony\Component\HttpFoundation\Request; |
||||
use FOS\RestBundle\Controller\Annotations\View; |
||||
use vierbergenlars\AuthserverTosBundle\Entity\UserTos; |
||||
use vierbergenlars\AuthserverTosBundle\Form\AcceptTosType; |
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType; |
||||
use Braincrafted\Bundle\BootstrapBundle\Form\Type\FormActionsType; |
||||
|
||||
class TosController extends Controller |
||||
{ |
||||
|
||||
/** |
||||
* @View() |
||||
*/ |
||||
public function acceptAction(Request $request) |
||||
{ |
||||
$user = $this->getUser(); |
||||
$em = $this->getDoctrine()->getManagerForClass(UserTos::class); |
||||
|
||||
$userTos = $em->find(UserTos::class, $user); |
||||
if (!$userTos) { |
||||
$userTos = new UserTos($user); |
||||
$em->persist($userTos); |
||||
} |
||||
|
||||
$tosUrl = $this->container->getParameter('vierbergenlars_tos.tos_url'); |
||||
|
||||
$formBuilder = $this->createFormBuilder(); |
||||
$formBuilder->add('vl_tos', AcceptTosType::class, [ |
||||
'url' => $tosUrl |
||||
]); |
||||
|
||||
$formBuilder->add('submit', SubmitType::class, [ |
||||
'label' => 'Submit' |
||||
]); |
||||
|
||||
$form = $formBuilder->getForm(); |
||||
|
||||
$form->handleRequest($request); |
||||
|
||||
if ($form->isValid()) { |
||||
$userTos->setAcceptedVersion($this->container->getParameter('vierbergenlars_tos.tos_version')); |
||||
$em->flush(); |
||||
return $this->redirectToRoute('user_profile'); |
||||
} |
||||
|
||||
return [ |
||||
'form' => $form, |
||||
'tos_url' => $tosUrl |
||||
]; |
||||
} |
||||
} |
@ -1,75 +0,0 @@ |
||||
<?php |
||||
namespace vierbergenlars\AuthserverTosBundle\EventListener; |
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
||||
use Registration\RegistrationEvents; |
||||
use Registration\Event\RegistrationFormEvent; |
||||
use Registration\Event\RegistrationHandleEvent; |
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; |
||||
use Symfony\Component\Validator\Constraints\IsTrue; |
||||
use vierbergenlars\AuthserverTosBundle\Entity\UserTos; |
||||
use Doctrine\ORM\EntityManagerInterface; |
||||
|
||||
class RegistrationListener implements EventSubscriberInterface |
||||
{ |
||||
|
||||
private $tosUrl; |
||||
|
||||
private $tosVersion; |
||||
|
||||
/** |
||||
* |
||||
* @var EntityManagerInterface |
||||
*/ |
||||
private $em; |
||||
|
||||
public static function getSubscribedEvents() |
||||
{ |
||||
return [ |
||||
RegistrationEvents::BUILD_FORM => [ |
||||
'onBuildForm', |
||||
-200 |
||||
], |
||||
RegistrationEvents::HANDLE_FORM => [ |
||||
'onHandleForm', |
||||
-20 // After persisting user |
||||
] |
||||
]; |
||||
} |
||||
|
||||
public function __construct($tosUrl, $tosVersion, EntityManagerInterface $em) |
||||
{ |
||||
$this->tosUrl = $tosUrl; |
||||
$this->tosVersion = $tosVersion; |
||||
$this->em = $em; |
||||
} |
||||
|
||||
public function onBuildForm(RegistrationFormEvent $event) |
||||
{ |
||||
$event->getFormBuilder()->add('vl_tos_accept', CheckboxType::class, [ |
||||
'label' => 'I accept the <a href="' . htmlentities($this->tosUrl, ENT_HTML5 | ENT_QUOTES) . '">terms of service</a>', |
||||
'mapped' => false, |
||||
'attr' => [ |
||||
'align_with_widget' => true |
||||
], |
||||
'constraints' => [ |
||||
new IsTrue([ |
||||
'message' => 'You must accept the terms of service.' |
||||
]) |
||||
] |
||||
]); |
||||
} |
||||
|
||||
public function onHandleForm(RegistrationHandleEvent $event) |
||||
{ |
||||
if ($event->getForm() |
||||
->get('vl_tos_accept') |
||||
->getData()) { |
||||
$user = $event->getForm()->getData(); |
||||
/* @var $user \App\Entity\User */ |
||||
$tosUser = new UserTos($user); |
||||
$tosUser->setAcceptedVersion($this->tosVersion); |
||||
$this->em->persist($tosUser); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,122 @@ |
||||
<?php |
||||
namespace vierbergenlars\AuthserverTosBundle\EventListener; |
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
||||
use Registration\RegistrationEvents; |
||||
use Registration\Event\RegistrationFormEvent; |
||||
use Registration\Event\RegistrationHandleEvent; |
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; |
||||
use Symfony\Component\Validator\Constraints\IsTrue; |
||||
use vierbergenlars\AuthserverTosBundle\Entity\UserTos; |
||||
use Doctrine\ORM\EntityManagerInterface; |
||||
use App\Entity\User; |
||||
use Symfony\Component\HttpFoundation\RedirectResponse; |
||||
use Symfony\Component\HttpKernel\KernelEvents; |
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent; |
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; |
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; |
||||
use vierbergenlars\AuthserverTosBundle\Form\AcceptTosType; |
||||
|
||||
class TosListener implements EventSubscriberInterface |
||||
{ |
||||
|
||||
private $tosUrl; |
||||
|
||||
private $tosVersion; |
||||
|
||||
/** |
||||
* |
||||
* @var EntityManagerInterface |
||||
*/ |
||||
private $em; |
||||
|
||||
/** |
||||
* |
||||
* @var TokenStorageInterface |
||||
*/ |
||||
private $tokenStorage; |
||||
|
||||
/** |
||||
* |
||||
* @var UrlGeneratorInterface |
||||
*/ |
||||
private $urlGenerator; |
||||
|
||||
public static function getSubscribedEvents() |
||||
{ |
||||
return [ |
||||
RegistrationEvents::BUILD_FORM => [ |
||||
'onBuildForm', |
||||
-200 |
||||
], |
||||
RegistrationEvents::HANDLE_FORM => [ |
||||
'onHandleForm', |
||||
-20 // After persisting user |
||||
], |
||||
KernelEvents::REQUEST => 'onKernelRequest' |
||||
]; |
||||
} |
||||
|
||||
public function __construct($tosUrl, $tosVersion, EntityManagerInterface $em, TokenStorageInterface $tokenStorage, UrlGeneratorInterface $urlGenerator) |
||||
{ |
||||
$this->tosUrl = $tosUrl; |
||||
$this->tosVersion = $tosVersion; |
||||
$this->em = $em; |
||||
$this->tokenStorage = $tokenStorage; |
||||
$this->urlGenerator = $urlGenerator; |
||||
} |
||||
|
||||
public function onBuildForm(RegistrationFormEvent $event) |
||||
{ |
||||
$event->getFormBuilder()->add('vl_tos', AcceptTosType::class, [ |
||||
'url' => $this->tosUrl, |
||||
'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); |
||||
} |
||||
} |
||||
|
||||
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; |
||||
$userTos = $this->em->find(UserTos::class, $user); |
||||
|
||||
if ($userTos && $userTos->getAcceptedVersion() >= $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); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,39 @@ |
||||
<?php |
||||
namespace vierbergenlars\AuthserverTosBundle\Form; |
||||
|
||||
use Symfony\Component\Form\AbstractType; |
||||
use Symfony\Component\Form\FormBuilderInterface; |
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; |
||||
use Symfony\Component\Validator\Constraints\IsTrue; |
||||
|
||||
class AcceptTosType extends AbstractType |
||||
{ |
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options) |
||||
{ |
||||
$builder->add('accept', CheckboxType::class, [ |
||||
'label' => 'I accept the <a href="' . htmlentities($options['url'], ENT_HTML5 | ENT_QUOTES) . '">terms of service</a>', |
||||
'attr' => [ |
||||
'align_with_widget' => true |
||||
], |
||||
'constraints' => [ |
||||
new IsTrue([ |
||||
'message' => 'You must accept the terms of service.' |
||||
]) |
||||
] |
||||
]); |
||||
} |
||||
|
||||
/** |
||||
* |
||||
* {@inheritdoc} |
||||
* @see \Symfony\Component\Form\AbstractType::configureOptions() |
||||
*/ |
||||
public function configureOptions(\Symfony\Component\OptionsResolver\OptionsResolver $resolver) |
||||
{ |
||||
$resolver->setDefined('url') |
||||
->setRequired('url') |
||||
->addAllowedTypes('url', 'string') |
||||
->setDefault('label', false); |
||||
} |
||||
} |
@ -0,0 +1,4 @@ |
||||
vl_tos_accept: |
||||
path: /usr/tos/accept |
||||
defaults: |
||||
_controller: AuthserverTosBundle:Tos:accept |
@ -0,0 +1,16 @@ |
||||
{% extends '::base.html.twig' %} |
||||
{% block body %} |
||||
<div class="container-fluid"> |
||||
<div class="row"> |
||||
<div class="col-xs-12"> |
||||
<div class="alert alert-info">Our terms of service have been updated.<br>You must accept these terms to be able to continue using the application.</div> |
||||
</div> |
||||
<div class="col-xs-12"> |
||||
<iframe src="{{ tos_url }}" style="width: 100%; height: 70vh;"></iframe> |
||||
</div> |
||||
<div class="col-xs-12"> |
||||
{{ form(form, {'style': 'horizontal'}) }} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{% endblock %} |
Reference in new issue