diff --git a/.gitignore b/.gitignore index e8925cd..a4e17f3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ vendor .php_cs.cache ezplatform .web-server-pid +.idea \ No newline at end of file diff --git a/bundle/Listener/EmailProvided.php b/bundle/Listener/EmailProvided.php index a03b0db..ddf0521 100644 --- a/bundle/Listener/EmailProvided.php +++ b/bundle/Listener/EmailProvided.php @@ -18,10 +18,12 @@ use Novactive\Bundle\eZProtectedContentBundle\Entity\ProtectedAccess; use Novactive\Bundle\eZProtectedContentBundle\Entity\ProtectedTokenStorage; use Novactive\Bundle\eZProtectedContentBundle\Form\RequestEmailProtectedAccessType; +use Novactive\Bundle\eZProtectedContentBundle\Repository\ProtectedTokenStorageRepository; use Ramsey\Uuid\Uuid; use Swift_Message; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\Form\FormFactoryInterface; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Swift_Mailer; @@ -80,11 +82,14 @@ public function onKernelRequest(GetResponseEvent $event): void if (!$event->isMasterRequest()) { return; } - $form = $this->formFactory->create(RequestEmailProtectedAccessType::class); $request = $event->getRequest(); - $form->handleRequest($request); + // ÉTAPE 2 - On reçoit le formulaire avec l'adresse email de l'internaute (+ le contentID). + // On va créer un token (ProtectedTokenStorage) et générer un email avec un lien qui sera utilisé dans l'étape 3. + // On affiche à internaute un message pour lui demander de vérifier ses mails. + $form = $this->formFactory->create(RequestEmailProtectedAccessType::class); + $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $data = $form->getData(); $contentId = intval($data['content_id']); @@ -106,6 +111,51 @@ public function onKernelRequest(GetResponseEvent $event): void $response->setPrivate(); $event->setResponse($response); } + + // ÉTAPE 3 - L'internaute a cliqué sur le lien dans le mail généré à l'étape 2 + // On retrouve le token et on crée un cookie + // On redirige l'internaute vers la page demandée. + if ($request->query->has('mail') + && $request->query->has('token') + && !$request->query->has('waiting_validation') + ) { + $token = $request->get('token'); + $mail = $request->get('mail'); + + /** @var ProtectedTokenStorageRepository $protectedTokenStorageRepository */ + $protectedTokenStorageRepository = $this->entityManager->getRepository(ProtectedTokenStorage::class); + $unexpiredTokenList = $protectedTokenStorageRepository->findUnexpiredBy([ + //'content_id' => $content->id, // TODO, On a pas le contentID ... est ce que on le met dans le line du mail ? On en a pas forcément besoin ... ? + 'token' => $token, + 'mail' => $mail + ]); + + if (count($unexpiredTokenList) > 0 ) { + $uri = $request->getRequestUri(); + $path = parse_url($uri, PHP_URL_PATH); + $response = new RedirectResponse($path); + $response->setPrivate(); + + foreach ($unexpiredTokenList as $unexpiredToken) { + $hash = self::hash($unexpiredToken->getContentId()); + $cookie = new Cookie(PasswordProvided::COOKIE_PREFIX.$hash, $hash, strtotime('now + 24 hours')); // TODO réflexion sur la durées + $response->headers->setCookie($cookie); + // TODO Supprimer/invalider le token ? + } + + $event->setResponse($response); + } + } + } + + public static function hash(int $contentId): string + { + return md5((string) $contentId); + } + + public static function isValidHash(string $hash, int $contentId): bool + { + return $hash === self::hash($contentId); } /** diff --git a/bundle/Listener/PreContentView.php b/bundle/Listener/PreContentView.php index 4b6d5c8..70f0291 100644 --- a/bundle/Listener/PreContentView.php +++ b/bundle/Listener/PreContentView.php @@ -17,10 +17,8 @@ use eZ\Publish\Core\MVC\Symfony\Event\PreContentViewEvent; use eZ\Publish\Core\MVC\Symfony\View\ContentView; use Novactive\Bundle\eZProtectedContentBundle\Entity\ProtectedAccess; -use Novactive\Bundle\eZProtectedContentBundle\Entity\ProtectedTokenStorage; use Novactive\Bundle\eZProtectedContentBundle\Form\RequestEmailProtectedAccessType; use Novactive\Bundle\eZProtectedContentBundle\Form\RequestProtectedAccessType; -use Novactive\Bundle\eZProtectedContentBundle\Repository\ProtectedTokenStorageRepository; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\RequestStack; @@ -83,35 +81,27 @@ public function onPreContentView(PreContentViewEvent $event) if (!$canRead) { $request = $this->requestStack->getCurrentRequest(); - if ($request->query->has('mail') - && $request->query->has('token') - && !$request->query->has('waiting_validation') - ) { - /** @var ProtectedTokenStorageRepository $protectedTokenStorageRepository */ - $protectedTokenStorageRepository = $this->entityManager->getRepository(ProtectedTokenStorage::class); - $unexpiredToken = $protectedTokenStorageRepository->findUnexpiredBy([ - 'content_id' => $content->id, - 'token' => $request->get('token'), - 'mail' => $request->get('mail') - ]); - - if (count($unexpiredToken) > 0 ) { - $canRead = true; + $cookies = $request->cookies; + foreach ($cookies as $name => $value) { + // TODO On a 2 fournisseur de cookies. PasswordProvided et EmailProvided. + // J'ai fait en sorte que EmailProvided respecte le format du PasswordProvided. + // C'est donc le même COOKIE_PREFIX + // Règle 1 = Le nom du cookie doit commencer par COOKIE_PREFIX + if (PasswordProvided::COOKIE_PREFIX !== substr($name, 0, \strlen(PasswordProvided::COOKIE_PREFIX))) { + continue; } - } else { - $cookies = $request->cookies; - foreach ($cookies as $name => $value) { - if (PasswordProvided::COOKIE_PREFIX !== substr($name, 0, \strlen(PasswordProvided::COOKIE_PREFIX))) { - continue; - } - if (str_replace(PasswordProvided::COOKIE_PREFIX, '', $name) !== $value) { - continue; + // Règle 2 = Le nom du cookie doit contenir la valeur ... TODO .. Pourquoi ? C'est bizarre comme règle .. + if (str_replace(PasswordProvided::COOKIE_PREFIX, '', $name) !== $value) { + continue; + } + foreach ($protections as $protection) { + // Protection par mot de passe. + if ($protection->getPassword() && md5($protection->getPassword()) === $value) { + $canRead = true; } - foreach ($protections as $protection) { - /** @var ProtectedAccess $protection */ - if (md5($protection->getPassword()) === $value) { - $canRead = true; - } + // Protection par email. + if ($protection->getAsEmail() && EmailProvided::isValidHash($value, $protection->getContentId())) { + $canRead = true; } } } diff --git a/composer.json b/composer.json index 2f00b8f..f233423 100644 --- a/composer.json +++ b/composer.json @@ -53,5 +53,10 @@ "name": "ezsystems/ezplatform", "url": "https://github.com/ezsystems/ezplatform" } + }, + "config": { + "allow-plugins": { + "symfony/thanks": false + } } }