<?php
namespace App\Controller;
use App\Form\ResetPasswordForm;
use App\Form\ResetPasswordRequestForm;
use App\Security\LoginAPIAuthenticator;
use App\Security\UserProvider;
use App\Services\UlteamApiService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
class SecurityController extends AbstractController
{
/**
* @Route("/login/{slug}", name="app_login")
* @param AuthenticationUtils $authenticationUtils
* @return Response
*/
public function login(AuthenticationUtils $authenticationUtils, $slug = ''): Response
{
$token = [];
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user hydra:member
$lastUsername = $authenticationUtils->getLastUsername();
$form = $this->createForm(ResetPasswordRequestForm::class, null, ['action' => $this->generateUrl('app_reset_pwd_request')]);
if (isset($_GET['token'])) {
$token['token'] = $_GET['token'];
}elseif ($this->getUser()!= null){
$token['token'] = $this->getUser()->getToken();
}
$passwordResetForm = $this->createForm(ResetPasswordForm::class, $token, ['action' => $this->generateUrl('app_reset_pwd', ['token'=>$token])]);
return $this->render('security/login.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
'reset_request_form' => $form->createView(),
'reset_pwd_form' => $passwordResetForm->createView(),
'token' => $token,
'slug' => $slug
]);
}
/**
* @param Request $request
* @param UlteamApiService $apiService
* @return RedirectResponse
* @Route("/reset-pwd-request", name="app_reset_pwd_request")
*/
public function resetPasswordRequest(Request $request, UlteamApiService $apiService): RedirectResponse
{
$form = $this->createForm(ResetPasswordRequestForm::class, null, ['action' => $this->generateUrl('app_reset_pwd_request')]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()){
try {
$message = $apiService->resetPwdRequest($form->get('email')->getData())->message;
$this->addFlash('warning', $message);
} catch (ClientExceptionInterface | TransportExceptionInterface | ServerExceptionInterface | RedirectionExceptionInterface $e) {
$this->addFlash('error', "Une erreur est survenue, nous ne pouvons pas traiter votre demande");
}
}
return $this->redirectToRoute('app_login');
}
/**
* @param Request $request
* @param UlteamApiService $apiService
* @return RedirectResponse
* @Route("/reset-pwd", name="app_reset_pwd")
*/
public function resetPassword(Request $request, UlteamApiService $apiService, TokenStorageInterface $storage, UserProvider $provider, EventDispatcherInterface $dispatcher, LoginAPIAuthenticator $authenticator):Response
{
$error= [];
$errorsFiltered = [];
if ($_GET != []) {
$token['token'] = $_GET['token'];
}else{
$token['token'] = $this->getUser()->getToken();
}
$passwordResetForm = $this->createForm(ResetPasswordForm::class, $token);
if ($this->getUser() != null && $this->getUser()->getIsFirstLogin() == true) {
$passwordResetForm->add('username', TextType::class,["label" => 'Identifiant']);
}
$passwordResetForm->handleRequest($request);
if ($passwordResetForm->isSubmitted() && $passwordResetForm->isValid()){
try {
$data = $passwordResetForm ->getData();
if ($this->getUser() != null && $this->getUser()->getIsFirstLogin() == true) {
$user = $apiService->getUser($this->getUser()->getId());
if (isset($user->department)) {
$user->department = $user->department->{"@id"};
}
unset($data['token']);
$user->firstLogin = false;
$user->{'username'} = $data['username'];
$user->{'plainPassword'} = $data['password'];
$user->{'passwordConfirm'} = $data['passwordConfirmation'];
$updatedUser = $apiService->updateUser($user);
// Login after password change
$storage->setToken();
$user = $provider->loadUserByUsername($updatedUser->username, $passwordResetForm->get('password')->getData());
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$storage->setToken($token);
$event = new InteractiveLoginEvent($request, $token);
$dispatcher->dispatch($event, SecurityEvents::INTERACTIVE_LOGIN);
$response = $authenticator->onAuthenticationSuccess($request, $token, 'main');
$this->addFlash('success', 'Informations modifiées avec succès');
return $response;
}
$apiService->resetPwd($data);
$this->addFlash('success', 'Mot de passe modifié avec succès');
return $this->redirectToRoute("app_login");
} catch (ClientExceptionInterface | TransportExceptionInterface | ServerExceptionInterface | RedirectionExceptionInterface $e) {
$error = json_decode($e->getResponse()->getContent(false))->violations;
foreach ($error as $value) {
$errorsFiltered['message'] = $value->{'message'};
}
$error = json_decode(json_encode($errorsFiltered));
$this->addFlash('danger', $error->message);
$referer = $request->headers->get('referer');
return $this->redirect($referer);
}
}
return $this->render('security/reset_pwd.html.twig', [
'error' => $error,
'reset_pwd_form' => $passwordResetForm->createView(),
'token' => $token,
]);
}
/**
* @Route("/logout", name="app_logout")
*/
public function logout()
{
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
}
}