traductions, sentry, form, mariadb, assets
Some checks failed
Cadoles/hydra-sql/pipeline/pr-develop There was a failure building this commit

This commit is contained in:
2022-12-13 15:46:24 +01:00
parent 6fc004a549
commit 9c746638a3
235 changed files with 22613 additions and 179 deletions

View File

@ -0,0 +1,20 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class LocaleController extends AbstractController
{
#[Route(path: 'locale/{locale}', name: 'locale_change')]
public function changeLocal(string $locale, Request $request)
{
// On stocke la langue dans la session
$request->getSession()->set('_locale', $locale);
// redirection
return $this->redirect($request->headers->get('referer'));
}
}

View File

@ -24,17 +24,13 @@ class MainController extends AbstractController
$this->hydra = $hydra;
}
/**
* @Route("/", name="app_home")
*/
#[Route('/', name: 'app_home')]
public function home(Request $request)
{
return $this->hydra->handleLoginRequest($request);
}
/**
* @Route("/connect/login-accept", name="app_login_accept")
*/
#[Route('/connect/login-accept', name: 'app_login_accept')]
public function loginAccept(Request $request)
{
/** @var User */
@ -47,9 +43,7 @@ class MainController extends AbstractController
return new RedirectResponse($loginAcceptRes['redirect_to']);
}
/**
* @Route("/connect/consent", name="app_consent")
*/
#[Route('/connect/consent', name: 'app_consent')]
public function consent(Request $request)
{
return $this->hydra->handleConsentRequest($request);

View File

@ -2,32 +2,52 @@
namespace App\Controller;
use App\Form\LoginType;
use App\Security\PdoUserAuthenticator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormError;
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\Http\Authentication\AuthenticationUtils;
use Symfony\Contracts\Translation\TranslatorInterface;
class SecurityController extends AbstractController
{
/**
* @Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
#[Route('/login', name: 'app_login')]
public function login(ParameterBagInterface $params, AuthenticationUtils $authenticationUtils, Request $request, TranslatorInterface $trans): Response
{
// get the login error if there is one
// Si l'utilisateur est déjà connecté on le renvoie sur la page du site demandeur
if ($this->getUser()) {
return new RedirectResponse($params->get('issuer_url'));
}
// On fournit le form, mais il est traité par un authenticator
$loginForm = $this->createForm(LoginType::class, null);
$error = $authenticationUtils->getLastAuthenticationError();
if ($error) {
if ($request->getSession()->has(PdoUserAuthenticator::ERROR_LOGIN)) {
$loginForm->get('login')->addError(new FormError($trans->trans('error.login', [], 'messages')));
$request->getSession()->remove(PdoUserAuthenticator::ERROR_LOGIN);
}
if ($request->getSession()->has(PdoUserAuthenticator::ERROR_PASSWORD)) {
$loginForm->get('password')->addError(new FormError($trans->trans('error.password', [], 'messages')));
$request->getSession()->remove(PdoUserAuthenticator::ERROR_PASSWORD);
}
if ($request->getSession()->has(PdoUserAuthenticator::ERROR_PDO)) {
$loginForm->addError(new FormError($trans->trans('error.pdo', [], 'messages')));
$request->getSession()->remove(PdoUserAuthenticator::ERROR_PDO);
}
}
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('login.html.twig', ['last_username' => $lastUsername, 'error' => $error]);
return $this->render('login.html.twig', [
'loginForm' => $loginForm->createView(),
]);
}
/**
* @Route("/logout", name="app_logout")
*/
#[Route('/logout', name: 'logout')]
public function logout(Request $request)
{
}

View File

@ -0,0 +1,41 @@
<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class LocaleSubscriber implements EventSubscriberInterface
{
// Langue par défaut
private string $defaultLocale;
public function __construct(string $defaultLocale)
{
$this->defaultLocale = $defaultLocale;
}
public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
if (!$request->hasPreviousSession()) {
return;
}
// On vérifie si la langue est passée en paramètre de l'URL
if ($locale = $request->query->get('_locale')) {
$request->setLocale($locale);
} else {
// Sinon on utilise celle de la session
$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}
}
public static function getSubscribedEvents()
{
return [
KernelEvents::REQUEST => [['onKernelRequest', 20]],
];
}
}

View File

@ -27,10 +27,11 @@ class LogoutSubscriber implements EventSubscriberInterface
$request = $event->getRequest();
// get the current response, if it is already set by another listener
$response = $event->getResponse();
$request->getSession()->clear();
$request->getSession()->invalidate();
// configure a custom logout response to the homepage
$response = $this->hydra->handleLogoutRequest($request);
$event->setResponse($response);
}
}

39
src/Form/LoginType.php Normal file
View File

@ -0,0 +1,39 @@
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class LoginType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('login', TextType::class, [
'translation_domain' => 'form',
'label' => 'form.label.login',
])
->add('password', PasswordType::class, [
'translation_domain' => 'form',
'label' => 'form.label.password',
])
->add('_remember_me', CheckboxType::class, [
'required' => false,
'translation_domain' => 'form',
'label' => 'form.label.remember_me',
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => null,
]);
}
}

View File

@ -78,7 +78,7 @@ class HydraService extends AbstractController
$logoutRequestInfo = $this->client->fetchLogoutRequestInfo($logoutChallenge)->toArray();
$logoutAcceptRes = $this->client->acceptLogoutRequest($logoutRequestInfo['challenge'])->toArray();
$this->session->clear();
$this->tokenStorage->setToken();
$this->tokenStorage->setToken(null);
return new RedirectResponse($logoutAcceptRes['redirect_to']);
}

View File

@ -4,10 +4,8 @@ namespace App;
use App\DependencyInjection\PdoExtension;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
@ -25,6 +23,7 @@ class Kernel extends BaseKernel
$loader->load(function (ContainerBuilder $container) use ($loader) {
$envLanguage = \getenv('APP_LOCALES');
$container->setParameter('app.supported_locales', explode(',', $envLanguage));
$container->registerExtension(new PdoExtension());
$loader->load($this->getConfigDir().'/pdo_configuration/*.{yml,yaml}', 'glob');
});

View File

@ -0,0 +1,9 @@
<?php
namespace App\Pdo\Exception;
use Exception;
class InvalidLoginException extends Exception
{
}

View File

@ -2,6 +2,8 @@
namespace App\Pdo\Exception;
class InvalidPasswordException
use Exception;
class InvalidPasswordException extends Exception
{
}

View File

@ -3,16 +3,16 @@
namespace App\Security;
use App\Entity\User;
use App\Hydra\Client;
use App\Pdo\Exception\InvalidPasswordException;
use App\Services\PdoService;
use PDOException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
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\Security;
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
@ -22,18 +22,19 @@ use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPasspor
class PdoUserAuthenticator extends AbstractAuthenticator
{
public const LOGIN_ROUTE = 'app_login';
public const ERROR_LOGIN = 'error_login';
public const ERROR_PASSWORD = 'error_password';
public const ERROR_PDO = 'error_pdo';
private PdoService $pdoService;
protected string $baseUrl;
private Client $client;
private SessionInterface $session;
private PdoService $pdoService;
private UrlGeneratorInterface $router;
public function __construct(string $baseUrl, PdoService $pdoService, Client $client, SessionInterface $session)
public function __construct(string $baseUrl, PdoService $pdoService, UrlGeneratorInterface $router)
{
$this->baseUrl = $baseUrl;
$this->pdoService = $pdoService;
$this->client = $client;
$this->session = $session;
$this->router = $router;
}
/**
@ -53,38 +54,50 @@ class PdoUserAuthenticator extends AbstractAuthenticator
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
$message = strtr($exception->getMessageKey(), $exception->getMessageData());
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
return new Response($message, Response::HTTP_FORBIDDEN);
return new RedirectResponse(
$this->router->generate('app_login')
);
}
public function authenticate(Request $request): Passport
{
$login = $request->request->get('login');
$password = $request->request->get('password');
$rememberMe = $request->request->get('_remember_me') ? true : false;
$form = $request->request->get('login');
$login = $form['login'];
$password = $form['password'];
$rememberMe = isset($form['_remember_me']) ? true : false;
try {
// requête préparée
$remoteHashedPassword = $this->pdoService->fetchPassword($login);
} catch (PDOException $e) {
dd($e);
}
try {
$this->pdoService->verifyPassword($password, $remoteHashedPassword);
$attributes = $this->pdoService->fetchDatas($login);
$user = new User($login, $password, $attributes, $rememberMe);
$loader = function (string $userIdentifier) use ($user) {
return $user->getLogin() == $userIdentifier ? $user : null;
};
$passport = new SelfValidatingPassport(new UserBadge($login, $loader));
// if ($rememberMe) {
// $passport->addBadge(new RememberMeBadge());
// }
$passport->setAttribute('attributes', $user->getAttributes());
return $passport;
} catch (InvalidPasswordException $e) {
$request->getSession()->set(self::ERROR_PDO, true);
throw new AuthenticationException();
}
if ($remoteHashedPassword) {
try {
$this->pdoService->verifyPassword($password, $remoteHashedPassword);
$attributes = $this->pdoService->fetchDatas($login);
$user = new User($login, $password, $attributes, $rememberMe);
$loader = function (string $userIdentifier) use ($user) {
return $user->getLogin() == $userIdentifier ? $user : null;
};
$passport = new SelfValidatingPassport(new UserBadge($login, $loader));
if ($rememberMe) {
$passport->addBadge(new RememberMeBadge());
}
$passport->setAttribute('attributes', $user->getAttributes());
return $passport;
} catch (InvalidPasswordException $e) {
$request->getSession()->set(self::ERROR_PASSWORD, true);
throw new AuthenticationException();
} catch (PDOException $e) {
$request->getSession()->set(self::ERROR_PDO, true);
throw new AuthenticationException();
}
}
$request->getSession()->set(self::ERROR_LOGIN, true);
throw new AuthenticationException();
}
}

View File

@ -2,11 +2,12 @@
namespace App\Services;
use App\Pdo\Exception\InvalidPasswordException;
use App\Pdo\PdoConnect;
use App\Pdo\PdoRequest;
use PDO;
use PDOException;
use App\Pdo\PdoConnect;
use App\Pdo\PdoRequest;
use Sentry\captureException;
use App\Pdo\Exception\InvalidPasswordException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
@ -34,8 +35,9 @@ class PdoService extends AbstractController
$query->execute([$this->pdoRequest->getNameLogin() => $login]);
$datas = $query->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo 'Erreur fetch Datas !: '.$e->getMessage().'<br/>';
exit();
\Sentry\captureException($e);
throw new PDOException();
}
return $datas;
@ -55,11 +57,15 @@ class PdoService extends AbstractController
$query->execute([$this->pdoRequest->getNameLogin() => $login]);
$password = $query->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo 'Erreur fetch Password!: '.$e->getMessage().'<br/>';
exit();
\Sentry\captureException($e);
dd($e);
throw new PDOException();
}
if ($password) {
return $password[$this->pdoRequest->getNamePassword()];
}
return $password[$this->pdoRequest->getNamePassword()];
return false;
}
public function getConnection()