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