Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ vendor
.php_cs.cache
ezplatform
.web-server-pid
.idea
54 changes: 52 additions & 2 deletions bundle/Listener/EmailProvided.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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']);
Expand All @@ -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);
}
}
}
Comment on lines +114 to +149
Copy link
Contributor Author

@RemyNovactive RemyNovactive Dec 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La récupération du lien présent dans le mail avec le token et le mail se fait maintenant ici et on créer un cookie


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);
}

/**
Expand Down
48 changes: 19 additions & 29 deletions bundle/Listener/PreContentView.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

La récupération du lien présent dans le mail avec le token et le mail ne se fait plus ici !
Voir : bundle/Listener/EmailProvided.php

} 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;
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,10 @@
"name": "ezsystems/ezplatform",
"url": "https://github.com/ezsystems/ezplatform"
}
},
"config": {
"allow-plugins": {
"symfony/thanks": false
}
}
}