From d056b1feac4e98868b79543ad16ffe49a7de3d5d Mon Sep 17 00:00:00 2001 From: rudy Date: Mon, 19 Jun 2023 15:56:55 +0200 Subject: [PATCH] =?UTF-8?q?issue-19:=20s=C3=A9paration=20des=20exceptions?= =?UTF-8?q?=20pour=20=C3=A9viter=20les=20erreurs=20g=C3=A9n=C3=A9riques,?= =?UTF-8?q?=20message=20personalis=C3=A9=20par=20type=20d'erreur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Controller/SecurityController.php | 18 +++++++++-- ... => DataToFetchConfigurationException.php} | 2 +- .../Exception/DatabaseConnectionException.php | 9 ++++++ .../LoginElementsConfigurationException.php | 9 ++++++ ...ption.php => NullDataToFetchException.php} | 2 +- .../NullPasswordColumnNameException.php | 9 ++++++ .../SecurityPatternConfigurationException.php | 9 ++++++ src/SQLLogin/SQLLoginRequest.php | 19 ++++++++---- src/Security/Hasher/PasswordEncoder.php | 8 +++-- src/Security/SQLLoginUserAuthenticator.php | 29 ++++++++++++++---- src/Service/SQLLoginService.php | 30 ++++++++++++++++--- translations/messages.en.xlf | 12 ++++++++ translations/messages.en.yaml | 5 +++- translations/messages.fr.xlf | 14 ++++++++- translations/messages.fr.yaml | 5 +++- translations/validators.en.xlf | 4 +++ 16 files changed, 157 insertions(+), 27 deletions(-) rename src/SQLLogin/Exception/{InvalidSQLLoginConfigurationException.php => DataToFetchConfigurationException.php} (50%) create mode 100644 src/SQLLogin/Exception/DatabaseConnectionException.php create mode 100644 src/SQLLogin/Exception/LoginElementsConfigurationException.php rename src/SQLLogin/Exception/{InvalidSQLLoginException.php => NullDataToFetchException.php} (55%) create mode 100644 src/SQLLogin/Exception/NullPasswordColumnNameException.php create mode 100644 src/SQLLogin/Exception/SecurityPatternConfigurationException.php diff --git a/src/Controller/SecurityController.php b/src/Controller/SecurityController.php index 08a0c76..cb525c5 100644 --- a/src/Controller/SecurityController.php +++ b/src/Controller/SecurityController.php @@ -36,9 +36,21 @@ class SecurityController extends AbstractController $loginForm->get('password')->addError(new FormError($trans->trans('error.password', [], 'messages'))); $request->getSession()->remove(SQLLoginUserAuthenticator::ERROR_PASSWORD); } - if ($request->getSession()->has(SQLLoginUserAuthenticator::ERROR_SQL_LOGIN)) { - $loginForm->addError(new FormError($trans->trans('error.sql_login', [], 'messages'))); - $request->getSession()->remove(SQLLoginUserAuthenticator::ERROR_SQL_LOGIN); + if ($request->getSession()->has(SQLLoginUserAuthenticator::ERROR_PDO)) { + $loginForm->addError(new FormError($trans->trans('error.pdo', [], 'messages'))); + $request->getSession()->remove(SQLLoginUserAuthenticator::ERROR_PDO); + } + if ($request->getSession()->has(SQLLoginUserAuthenticator::ERROR_CONFIGURATION)) { + $loginForm->addError(new FormError($trans->trans('error.configuration', [], 'messages'))); + $request->getSession()->remove(SQLLoginUserAuthenticator::ERROR_CONFIGURATION); + } + if ($request->getSession()->has(SQLLoginUserAuthenticator::ERROR_DATA_TO_FETCH_CONFIGURATION)) { + $loginForm->addError(new FormError($trans->trans('error.data_to_fetch_configuration', [], 'messages'))); + $request->getSession()->remove(SQLLoginUserAuthenticator::ERROR_DATA_TO_FETCH_CONFIGURATION); + } + if ($request->getSession()->has(SQLLoginUserAuthenticator::ERROR_SECURITY_PATTERN_CONFIGURATION)) { + $loginForm->addError(new FormError($trans->trans('error.security_pattern_configuration', [], 'messages'))); + $request->getSession()->remove(SQLLoginUserAuthenticator::ERROR_SECURITY_PATTERN_CONFIGURATION); } } diff --git a/src/SQLLogin/Exception/InvalidSQLLoginConfigurationException.php b/src/SQLLogin/Exception/DataToFetchConfigurationException.php similarity index 50% rename from src/SQLLogin/Exception/InvalidSQLLoginConfigurationException.php rename to src/SQLLogin/Exception/DataToFetchConfigurationException.php index 156abf7..7b09626 100644 --- a/src/SQLLogin/Exception/InvalidSQLLoginConfigurationException.php +++ b/src/SQLLogin/Exception/DataToFetchConfigurationException.php @@ -4,6 +4,6 @@ namespace App\SQLLogin\Exception; use Exception; -class InvalidSQLLoginConfigurationException extends Exception +class DataToFetchConfigurationException extends Exception { } diff --git a/src/SQLLogin/Exception/DatabaseConnectionException.php b/src/SQLLogin/Exception/DatabaseConnectionException.php new file mode 100644 index 0000000..770ea6b --- /dev/null +++ b/src/SQLLogin/Exception/DatabaseConnectionException.php @@ -0,0 +1,9 @@ +config[self::DATA_TO_FETCH] as $data) { - $scope .= $data.','; - } - $scope = substr($scope, 0, -1); + if ($this->config[self::DATA_TO_FETCH]) { + foreach ($this->config[self::DATA_TO_FETCH] as $data) { + $scope .= $data.','; + } + // On enlève la dernière virgule + $scope = substr($scope, 0, -1); - return 'SELECT '.$scope.' FROM '.$this->getTableName().' WHERE '.$this->getLoginColumnName().' = :'.$this->getLoginColumnName().';'; + return 'SELECT '.$scope.' FROM '.$this->getTableName().' WHERE '.$this->getLoginColumnName().' = :'.$this->getLoginColumnName().';'; + } + throw new NullDataToFetchException(); } /** * Construction de la string pour la requête préparée selon la configuration yaml * intègre la récupération du mot de passe hashé, du salt et de besoin d'upgrade de la méthode de hashage */ - public function getRequestPassword() + public function getRequestPassword(): string { $fields = $this->getPasswordColumnName(); if (!empty($this->getSaltColumnName())) { diff --git a/src/Security/Hasher/PasswordEncoder.php b/src/Security/Hasher/PasswordEncoder.php index 5edaf71..3259f81 100644 --- a/src/Security/Hasher/PasswordEncoder.php +++ b/src/Security/Hasher/PasswordEncoder.php @@ -2,8 +2,9 @@ namespace App\Security\Hasher; -use App\SQLLogin\Exception\InvalidSQLLoginConfigurationException; use App\SQLLogin\Exception\InvalidSQLPasswordException; +use App\SQLLogin\Exception\SecurityPatternConfigurationException; +use Psr\Log\LoggerInterface; use Symfony\Component\PasswordHasher\Exception\InvalidPasswordException; use Symfony\Component\PasswordHasher\Hasher\CheckPasswordLengthTrait; use Symfony\Component\PasswordHasher\LegacyPasswordHasherInterface; @@ -19,7 +20,7 @@ class PasswordEncoder implements LegacyPasswordHasherInterface protected array $hashAlgoLegacy; protected array $securityPattern; - public function __construct(?string $pepper, string $hashAlgoLegacy, string $securityPattern) + public function __construct(?string $pepper, string $hashAlgoLegacy, string $securityPattern, private LoggerInterface $loggerInterface) { $this->pepper = $pepper; $this->hashAlgoLegacy = explode(',', $hashAlgoLegacy); @@ -91,7 +92,8 @@ class PasswordEncoder implements LegacyPasswordHasherInterface foreach ($this->securityPattern as $term) { if (self::PEPPER_PATTERN !== $term && self::PASSWORD_PATTERN !== $term && self::SALT_PATTERN !== $term) { - throw new InvalidSQLLoginConfigurationException(); + $this->loggerInterface->critical('La configuration du security pattern est invalide, les termes autorisés sont : '.self::PASSWORD_PATTERN.', '.self::SALT_PATTERN.' et '.self::PEPPER_PATTERN); + throw new SecurityPatternConfigurationException(); } } $completedPlainPassword = ''; diff --git a/src/Security/SQLLoginUserAuthenticator.php b/src/Security/SQLLoginUserAuthenticator.php index 1d3394e..842ad16 100644 --- a/src/Security/SQLLoginUserAuthenticator.php +++ b/src/Security/SQLLoginUserAuthenticator.php @@ -5,8 +5,11 @@ namespace App\Security; use App\Entity\User; use App\Security\Hasher\PasswordEncoder; use App\Service\SQLLoginService; +use App\SQLLogin\Exception\DatabaseConnectionException; +use App\SQLLogin\Exception\DataToFetchConfigurationException; use App\SQLLogin\Exception\InvalidSQLPasswordException; -use PDOException; +use App\SQLLogin\Exception\LoginElementsConfigurationException; +use App\SQLLogin\Exception\SecurityPatternConfigurationException; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -24,7 +27,11 @@ class SQLLoginUserAuthenticator extends AbstractLoginFormAuthenticator public const LOGIN_ROUTE = 'app_login'; public const ERROR_LOGIN = 'error_login'; public const ERROR_PASSWORD = 'error_password'; + public const ERROR_PDO = 'error_pdo'; public const ERROR_SQL_LOGIN = 'error_sql_login'; + public const ERROR_CONFIGURATION = 'error_configuration'; + public const ERROR_DATA_TO_FETCH_CONFIGURATION = 'error_data_to_fetch_configuration'; + public const ERROR_SECURITY_PATTERN_CONFIGURATION = 'error_security_pattern_configuration'; protected string $baseUrl; private SQLLoginService $sqlLoginService; @@ -65,11 +72,15 @@ class SQLLoginUserAuthenticator extends AbstractLoginFormAuthenticator $login = $form['login']; $plaintextPassword = $form['password']; $rememberMe = isset($form['_remember_me']) ? true : false; + $session = $request->getSession(); try { // requête préparée list($remoteHashedPassword, $remoteSalt) = $this->sqlLoginService->fetchPassword($login); - } catch (PDOException $e) { - $request->getSession()->set(self::ERROR_SQL_LOGIN, true); + } catch (DatabaseConnectionException $e) { + $session->set(self::ERROR_PDO, true); + throw new AuthenticationException(); + } catch (LoginElementsConfigurationException $e) { + $session->set(self::ERROR_CONFIGURATION, true); throw new AuthenticationException(); } if ($remoteHashedPassword) { @@ -90,10 +101,16 @@ class SQLLoginUserAuthenticator extends AbstractLoginFormAuthenticator return $passport; } catch (InvalidSQLPasswordException $e) { - $request->getSession()->set(self::ERROR_PASSWORD, true); + $session->set(self::ERROR_PASSWORD, true); throw new AuthenticationException(); - } catch (PDOException $e) { - $request->getSession()->set(self::ERROR_SQL_LOGIN, true); + } catch (DataToFetchConfigurationException $e) { + $session->set(self::ERROR_DATA_TO_FETCH_CONFIGURATION, true); + throw new AuthenticationException(); + } catch (DatabaseConnectionException $e) { + $session->set(self::ERROR_PDO, true); + throw new AuthenticationException(); + } catch (SecurityPatternConfigurationException $e) { + $session->set(self::ERROR_SECURITY_PATTERN_CONFIGURATION, true); throw new AuthenticationException(); } } diff --git a/src/Service/SQLLoginService.php b/src/Service/SQLLoginService.php index 5a98e4a..835a989 100644 --- a/src/Service/SQLLoginService.php +++ b/src/Service/SQLLoginService.php @@ -2,6 +2,10 @@ namespace App\Service; +use App\SQLLogin\Exception\DatabaseConnectionException; +use App\SQLLogin\Exception\DataToFetchConfigurationException; +use App\SQLLogin\Exception\LoginElementsConfigurationException; +use App\SQLLogin\Exception\NullDataToFetchException; use App\SQLLogin\SQLLoginConnect; use App\SQLLogin\SQLLoginRequest; use PDO; @@ -23,16 +27,26 @@ class SQLLoginService extends AbstractController { try { $dbh = $this->getConnection(); + } catch (PDOException $e) { + \Sentry\captureException($e); + $this->loggerInterface->critical($e->getMessage()); + throw new DatabaseConnectionException($e->getMessage()); + } + try { // forge de la requête $request = $this->sqlLoginRequest->getRequestScope(); + } catch (NullDataToFetchException $e) { + throw new DataToFetchConfigurationException($e->getMessage()); + } + + try { // Préparation de la requête $query = $dbh->prepare($request); $query->execute([$this->sqlLoginRequest->getLoginColumnName() => $login]); $datas = $query->fetch(PDO::FETCH_ASSOC); } catch (PDOException $e) { - \Sentry\captureException($e); $this->loggerInterface->critical($e->getMessage()); - throw new PDOException(); + throw new DataToFetchConfigurationException($e->getMessage()); } return $datas; @@ -42,13 +56,21 @@ class SQLLoginService extends AbstractController { try { $dbh = $this->getConnection(); - $request = $this->sqlLoginRequest->getRequestPassword(); + } catch (PDOException $e) { + $this->loggerInterface->critical($e->getMessage()); + throw new DatabaseConnectionException($e->getMessage()); + } + + // forge de la requête + $request = $this->sqlLoginRequest->getRequestPassword(); + + try { $query = $dbh->prepare($request); $query->execute([$this->sqlLoginRequest->getLoginColumnName() => $login]); $password = $query->fetch(PDO::FETCH_ASSOC); } catch (PDOException $e) { $this->loggerInterface->critical($e->getMessage()); - throw new PDOException(); + throw new LoginElementsConfigurationException($e->getMessage()); } if ($password) { return [ diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index c448121..1c1aef3 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -17,6 +17,18 @@ error.pdo Connection to database encountered a problem + + error.configuration + Identification data references do not exist in the database + + + error.data_to_fetch_configuration + Data references to be transmitted do not exist + + + error.security_pattern_configuration + The security pattern is not allowed + diff --git a/translations/messages.en.yaml b/translations/messages.en.yaml index cfcf961..47dc0f7 100644 --- a/translations/messages.en.yaml +++ b/translations/messages.en.yaml @@ -1,4 +1,7 @@ error: login: 'Incorrect login' password: 'Incorrect password' - sql_login: 'Connection to database encountered a problem' \ No newline at end of file + pdo: 'The connexion to the database has failed' + configuration: "Identification data references do not exist in the database" + data_to_fetch_configuration: "Data references to be transmitted do not exist" + security_pattern_configuration: "The security pattern is not allowed" \ No newline at end of file diff --git a/translations/messages.fr.xlf b/translations/messages.fr.xlf index 6a2884d..f7c1387 100644 --- a/translations/messages.fr.xlf +++ b/translations/messages.fr.xlf @@ -15,7 +15,19 @@ error.pdo - La connexion à la base de déonnées à rencontré un problème + La connexion à la base de données a rencontré un problème + + + error.configuration + Les références de données d'identification n'existent pas dans la base de données + + + error.data_to_fetch_configuration + Les références de données à transmettre n'existent pas + + + error.security_pattern_configuration + Le patron de sécurité n'est pas autorisé diff --git a/translations/messages.fr.yaml b/translations/messages.fr.yaml index d9410e2..5eadad1 100644 --- a/translations/messages.fr.yaml +++ b/translations/messages.fr.yaml @@ -1,4 +1,7 @@ error: login: 'Login incorrect ou inconnu' password: 'Mot de passe incorrect' - sql_login: 'La connexion à la base de données a rencontré un problème' \ No newline at end of file + pdo: 'La connexion à la base de données a rencontré un problème' + configuration: "Les références de données d'identification n'existent pas dans la base de données" + data_to_fetch_configuration: "Les références de données à transmettre n'existent pas" + security_pattern_configuration: "Le patron de sécurité n'est pas autorisé" \ No newline at end of file diff --git a/translations/validators.en.xlf b/translations/validators.en.xlf index c384636..2a8c4ec 100644 --- a/translations/validators.en.xlf +++ b/translations/validators.en.xlf @@ -405,6 +405,10 @@ The value of the netmask should be between {{ min }} and {{ max }}. The value of the netmask should be between {{ min }} and {{ max }}. + + The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. + The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. + This form should not contain extra fields. This form should not contain extra fields.