<?php
namespace App\Controller;
use App\Entity\User;
use Psr\Log\LoggerInterface;
use App\Service\EmailService;
use App\Repository\UserRepository;
use App\Service\UserWordpressService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
class MailPasswordResetController extends AbstractController
{
private $logger;
private $httpClient;
private $emailService;
private $wordpressService;
public function __construct(UserWordpressService $wordpressService, EmailService $emailService,LoggerInterface $logger, HttpClientInterface $httpClient)
{
$this->logger = $logger;
$this->httpClient = $httpClient;
$this->emailService = $emailService;
$this->wordpressService = $wordpressService;
}
#[Route('/forgot-password', name: 'app_forgot_password')]
public function index(UserRepository $userRepository, Request $request, EntityManagerInterface $entityManager, JWTTokenManagerInterface $JWTTokenManager): Response
{
// Je teste si le champ email a été envoyé
if($request->get('email')) {
$email = $request->get('email');
$user = $userRepository->findOneByEmail($email);
// Si ne trouve pas d'utilisateur avec cette email
if(empty($user)) {
$this->addFlash('danger', 'Pas de compte lié à cette adresse mail');
}
// Si j'en trouve
else {
// Je génère un token unique qui me permettra de l'identifier une fois qu'il cliquera sur lien envoyé par mail
$token = uniqid(md5($email), true) . bin2hex(random_bytes(5));
$user->setTempToken($token);
//dump($user);
$entityManager->persist($user);
$entityManager->flush();
// J'envoie le mail de changement de mot de passe
$to = $user->getEmail();
// Sujet de l'e-mail
$subject = "Changement de mot de passe";
// Je génère le lien pour qu'il puisse changer son mot de passe
$signedUrl = $this->generateUrl('new_password',['token' => $token], UrlGeneratorInterface::ABSOLUTE_URL, [
'scheme' => 'https'
]);
//dump($signedUrl);
//dump($token);
// Message
$message = "<h4>Bonjour! Votre lien de modification de votre mot de passe!</h4>
<p>
Appuyer sur le lien ci dessous pour changer votre mot de passe: <br><br>
<a href=".$signedUrl.">Changer mon mot de passe</a>
</p>
<p>
Bien à vous!
</p>";
if($this->emailService->sendMail($to, $subject, $message) == 'succeed') {
$this->addFlash('success', 'Un lien vous a été envoyé dans votre boite mail pour cette modification '.$user->getEmail().', veuillez l\'utiliser pour la modification du mot de passe');
}
else {
throw new \Exception("Erreur d'envoie de mail");
}
}
}
return $this->render('forgot_password/index.html.twig', [
'controller_name' => 'MailPasswordResetController',
]);
}
// Route appelée lorsque l'utilisateur clique sur le lien que l'on lui a envoyé par mail
#[Route('/password/new', name: 'new_password')]
public function newPassword(UserPasswordHasherInterface $userPasswordHasher, UserRepository $userRepository, Request $request, EntityManagerInterface $entityManager, JWTTokenManagerInterface $JWTTokenManager): Response
{
// Je vérifie la présence du token dans l'url
if($request->get('token')) {
// Je cherche la correspondance avec un User par token
$user = $userRepository->findOneByTempToken($request->get('token'));
// Si je ne trouve pas de correspondance
if(empty($user)) {
return new JsonResponse('Lien expiré', Response::HTTP_BAD_REQUEST);
}
// Si j'en trouve
else {
return $this->render('security/newpassword.html.twig', [
'email' => $user->getEmail(),
]);
}
}
// Etant aussi la route de changement de mot de passe à proprement parlé lors d'un oublie je capte aussi si l'utilisateur a rempli le formulaire de nouveau mot de passe
else if ($request->getMethod() === 'POST' && $request->get('newpassword')) {
//dump($request->get('newpassword'));
//dump($request->get('confirmNewpassword'));
// Je cherche la correspondance avec un User par email
$user = $userRepository->findOneByEmail($request->get('email'));
//dump($user);
// Si je ne trouve pas de correspondance
if(empty($user)) {
$this->addFlash('danger', 'Pas de compte lié à cette adresse mail');
}
// Si j'en trouve
else {
// Je vérifie que le mot de passe et sa confirmation sont les mêmes
// Si c'est le cas
if($request->get('newpassword') === $request->get('confirmNewpassword')) {
$user->setPassword(
$userPasswordHasher->hashPassword(
$user,
$request->get('newpassword')
)
);
$user->setTempToken(null);
//dump($user);
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('success', 'Votre mot de passe a été changé avec succès, vous pouvez vous connecter');
return $this->redirectToRoute('app_login');
}
// Si ça ne l'est pas
else {
$this->addFlash('danger', 'Le mot de passe et sa confirmation doivent être identiques');
}
}
return $this->render('security/newpassword.html.twig', [
'email' => $user->getEmail(),
]);
}
return new JsonResponse('Lien expiré', Response::HTTP_BAD_REQUEST);
}
// Route appelée lorsque l'utilisateur clique sur le lien que l'on lui a envoyé par mail
#[Route('/mail/new', name: 'new_mail')]
public function newMail(UserPasswordHasherInterface $userPasswordHasher, UserRepository $userRepository, Request $request, EntityManagerInterface $entityManager, JWTTokenManagerInterface $JWTTokenManager): Response
{
// Je vérifie la présence du token dans l'url
if($request->get('token')) {
// Je cherche la correspondance avec un User par token
$user = $userRepository->findOneByTempToken($request->get('token'));
// Si je ne trouve pas de correspondance
if(empty($user)) {
return new JsonResponse('Lien expiré', Response::HTTP_BAD_REQUEST);
}
// Si j'en trouve
else {
$user->setEmail($request->get('newEmail'));
$user->setTempToken(null);
//dump($user);
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('success', 'Votre Email a été mis à jour avec succès, vous pouvez vous connecter');
// Je contacte le backoffice pour le notifier du changement
$this->updateUserBackoffice($entityManager, $user);
return $this->redirectToRoute('app_login');
}
}
return new JsonResponse('Lien expiré', Response::HTTP_BAD_REQUEST);
}
// Fonction pour *signaler des changements du profil d'un user au backoffice
public function updateUserBackoffice(EntityManagerInterface $entityManager, User $user) {
$autoPublish = 0;
// Si auto publish à true je passe 1 sinon je passe 0
if($user->isAutoPublish()) {
$autoPublish = 1;
}
// A faire après la vérification d'email dans la prod
$jsonData = [
'authentication_key' => $_ENV['AUTHENTICATION_KEY'],
'idcustomer' => $user->getId(),
'customerkey' => $user->getCustomerKey(),
'customerlastname' => $user->getLastname(),
'customerfirstname' => $user->getFirstname(),
'customeremail' => $user->getEMail(),
'customerphonenumber' => $user->getPhoneNumber(),
'customersubjects' => $user->getCustomerSubjects(),
'companyname' => $user->getCompanyName(),
'siteurl' => $user->getWordpressUrl(),
'publishinguser' => $user->getWordpressUsername(),
'publishinguserkey' => $this->wordpressService->decryptPassword($user->getWordpressPassword()),
'seoplugin' => $user->getSeoPlugin(),
'autopublish' => $user->isAutoPublish() == true ? 1 : 0
];
//dump($jsonData);
try {
// Envoyer les données à l'API externe
$response = $this->httpClient->request('POST', 'https://www.groupe-saven.fr/api.cpe/newcustomer.php',
[
'json' => $jsonData
]);
$statusCode = $response->getStatusCode();
$content = $response->getContent(false);
$data = json_decode($content, true);
////dump($statusCode);
//dump($data);
//dump($response);
if ($statusCode !== 200) {
// Lancer une exception avec le contenu de la réponse si le code de statut n'est pas 200
throw new \Exception("Erreur HTTP $statusCode: " . $content);
}
if ($data['status'] === 'success') {
//dump($data['id']);
if(!$user->getPbnId() == (int) $data['id']) {
$this->logger->error("danger" . " Mauvais Utilisateur modifier côté backoffice");
}
else {
//dump("Tout est Ok côté front et backoffice");
}
}
} catch (Exception $e) {
//dump($response);
$this->logger->error("danger" . $e->getMessage());
}
return true;
}
}