<?php
namespace App\Security;
use App\Entity\User;
use App\Services\ConfigService;
use App\Services\DTV\YamlConfig\YamlReader;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginAuthenticator extends AbstractLoginFormAuthenticator
{
use TargetPathTrait;
public const LOGIN_ROUTE = 'app_login';
private EntityManagerInterface $em;
private UrlGeneratorInterface $urlGenerator;
private YamlReader $yamlReader;
private ConfigService $configService;
private KernelInterface $kernel;
private ServiceLocator $workflowUserServiceLocator;
public function __construct(
EntityManagerInterface $em,
UrlGeneratorInterface $urlGenerator,
YamlReader $yamlReader,
ConfigService $configService,
KernelInterface $kernel,
ServiceLocator $workflowUserServiceLocator
) {
$this->em = $em;
$this->urlGenerator = $urlGenerator;
$this->yamlReader = $yamlReader;
$this->configService = $configService;
$this->kernel = $kernel;
$this->workflowUserServiceLocator = $workflowUserServiceLocator;
}
/**
* @param Request $request
*
* @return Passport
*
* @throws Exception
*/
public function authenticate( Request $request ): Passport
{
$credentials = $request->request->get( 'login' );
$email = $credentials[ 'email' ] ?? '';
$password = $credentials[ 'password' ] ?? '';
$request->getSession()->set( Security::LAST_USERNAME, $email );
// Code commenté suite demande daikin
// Récupère l'utilisateur en fonction de l'e-mail
// $userRepo = $this->em->getRepository( User::class );
// $user = $userRepo->findOneBy( [ 'email' => $email ] );
// $loginSecurity = $this->yamlReader->getGlobal()['login_security' ] ?? [];
// $failedAttempts = $loginSecurity['failed_attempts'] ?? 3;
// $delayBeforeNewAttempt = $loginSecurity['delay_before_new_attempt'] ?? 24;
// $passwordValidationDays = $loginSecurity['password_validation_days'] ?? 365;
// $env = $this->kernel->getEnvironment();
/*
if ($env !== 'test' || ($user instanceof User && !$user->isDeveloper())) {
// Vérifie si l'utilisateur échoue à la connexion plus de 3 fois
if ( $user && $user->getFailedAttempts() >= $failedAttempts ) {
$lastFailed = $user->getLastFailedAttempt();
$interval = ( new DateTime() )->diff( $lastFailed );
if ( $interval->days == 0 && $interval->h < $delayBeforeNewAttempt ) {
throw new CustomUserMessageAuthenticationException(
'Vous avez été bloqué pendant 24 heures en raison de trop nombreuses tentatives ' .
'de connexion échouées.',
);
}
else {
// Réinitialiser les tentatives après 24 heures
$user->setFailedAttempts( 0 );
$this->em->flush();
}
}
// Vérification de la durée de validité du mot de passe
if ( $user ) {
$passwordUpdated = $user->getPasswordUpdatedAt();
if ( is_null( $passwordUpdated ) ) {
$passwordUpdated = ( new DateTime() )->modify( '-370 days' );
$user->setPasswordUpdatedAt( $passwordUpdated );
$this->em->flush();
}
$interval = ( new DateTime() )->diff( $passwordUpdated );
if ( $interval->days >= $passwordValidationDays ) {
// On injecte le service de workflowUser (pour éviter une dépendance circulaire dans le constructor)
// On envoie un mail à l'utilisateur pour qu'il puisse changer son mot de passe et revalider les CGU
try {
$workflowUser = $this->workflowUserServiceLocator->get('workflowUser');
$workflowUser->resendCGU( $user );
}
catch ( NotFoundExceptionInterface|ContainerExceptionInterface $e ) {
throw new Exception( $e->getMessage() );
}
throw new CustomUserMessageAuthenticationException(
'Votre mot de passe a été créé il y a plus de 12 mois, pour des raisons de sécurités, ' .
'un email vous a été envoyé afin que vous puissiez en changer. <br>' .
'Veuillez vérifier votre boite mail et suivre les instructions.',
);
}
}
}
*/
// fin de code commenté suite demande daikin
return new Passport(
new UserBadge( $email ),
new PasswordCredentials( $password ),
[
new CsrfTokenBadge( 'authenticate', $request->request->get( '_csrf_token' ) ),
],
);
}
/**
* @param Request $request
* @param TokenInterface $token
* @param string $firewallName
*
* @return Response|null
*/
public
function onAuthenticationSuccess(
Request $request,
TokenInterface $token,
string $firewallName
): ?Response {
if ( $this->yamlReader->getType() === 'api' ) {
return new RedirectResponse( $this->urlGenerator->generate( 'back_dashboard' ) );
}
if ( $targetPath = $this->getTargetPath( $request->getSession(), $firewallName ) ) {
return new RedirectResponse( $targetPath );
}
return new RedirectResponse( $this->urlGenerator->generate( 'front_homepage' ) );
}
/**
* @param Request $request
* @param AuthenticationException $exception
*
* @return Response
*/
public
function onAuthenticationFailure(
Request $request, AuthenticationException $exception
): Response {
$credentials = $request->request->get( 'login' );
$email = $credentials[ 'email' ] ?? '';
$userRepo = $this->em->getRepository( User::class );
$user = $userRepo->findOneBy( [ 'email' => $email ] );
if ( $user ) {
$user->setFailedAttempts( $user->getFailedAttempts() + 1 );
$user->setLastFailedAttempt( new DateTime() );
$this->em->flush();
}
$request->getSession()->set( Security::AUTHENTICATION_ERROR, $exception );
return new RedirectResponse( $this->urlGenerator->generate( self::LOGIN_ROUTE ) );
}
/**
* @param Request $request
*
* @return string
*/
protected
function getLoginUrl(
Request $request
): string {
return $this->urlGenerator->generate( self::LOGIN_ROUTE );
}
}