Author: nathanaelhoun
Date: 2026-02-27 19:23:43 +0100 (Fri, 27 Feb 2026)
New Revision: 5498
Added:
openmairie_exemple/branches/POC_migration_mots_de_passe/tests/testAuthentification.php
Modified:
openmairie_exemple/branches/POC_migration_mots_de_passe/tests/011_utilisateur.robot
openmairie_exemple/branches/POC_migration_mots_de_passe/tests/config.xml
openmairie_exemple/branches/POC_migration_mots_de_passe/tests/resources/resources.robot
Log:
tests: verifier le changement de mot de passe et la migration de mot de passe
Modified: openmairie_exemple/branches/POC_migration_mots_de_passe/tests/011_utilisateur.robot
===================================================================
--- openmairie_exemple/branches/POC_migration_mots_de_passe/tests/011_utilisateur.robot 2026-02-27 18:03:43 UTC (rev 5497)
+++ openmairie_exemple/branches/POC_migration_mots_de_passe/tests/011_utilisateur.robot 2026-02-27 18:23:43 UTC (rev 5498)
@@ -1,11 +1,16 @@
*** Settings ***
+
Resource resources/resources.robot
-Suite Setup For Suite Setup
-Suite Teardown For Suite Teardown
-Documentation TestSuite "Utilisateur"...
+Suite Setup Run Keywords No Operation
+ ... AND For Suite Setup
+ ... AND Composition du jeu de connées
+Suite Teardown Run Keywords No Operation
+ ... AND For Suite Teardown
+
*** Test Cases ***
+
Synchronisation des utilisateurs avec un annuaire LDAP
[Documentation] On teste la synchronisation des utilisateurs avec le ldap
@@ -62,13 +67,79 @@
Valid Message Should Be La synchronisation des utilisateurs est terminée.
-Changement du mot de passe
+Changement du mot de passe - un mauvais mot de passe actuel est rejeté.
- [Documentation]
+ Depuis la page d'accueil test_011_mdp test_011_mdp
+ Accéder au formulaire de changement de mot de passe
+ Soumettre le changement de mot de passe mauvais_mdp nouveau_mdp_test nouveau_mdp_test
+ Error Message Should Be Mot de passe actuel incorrect
- Comment @todo Écrire le 'Test Case'
+Changement du mot de passe - un nouveau mot de passe vide est rejeté.
+ Depuis la page d'accueil test_011_mdp test_011_mdp
+ Accéder au formulaire de changement de mot de passe
+ Soumettre le changement de mot de passe test_011_mdp ${EMPTY} ${EMPTY}
+ Error Message Should Be Nouveau mot de passe incorrect
+
+
+Changement du mot de passe - deux nouveaux mots de passe différents sont rejetés.
+
+ Depuis la page d'accueil test_011_mdp test_011_mdp
+ Accéder au formulaire de changement de mot de passe
+ Soumettre le changement de mot de passe test_011_mdp nouveau_mdp_test nouveau_mdp_test_different
+ Error Message Should Be Nouveau mot de passe incorrect
+
+
+Changement du mot de passe - le nouveau mot de passe a bien remplacé l'ancien
+ ${NOUVEAU_MDP} Set Variable nouveau_mdp_test
+
+ Depuis la page d'accueil test_011_mdp test_011_mdp
+ Accéder au formulaire de changement de mot de passe
+ Soumettre le changement de mot de passe test_011_mdp ${NOUVEAU_MDP} ${NOUVEAU_MDP}
+ Valid Message Should Be Votre mot de passe a été changé correctement
+
+ # Vérifier que l'ancien mot de passe est refusé
+ Go To ${PROJECT_URL}
+ Se déconnecter
+ Depuis la page de login
+ Saisir les informations de connexion et valider test_011_mdp test_011_mdp
+ Error Message Should Be Votre identifiant ou votre mot de passe est incorrect.
+
+ # Vérifier que le nouveau mot de passe est accepté à la connexion
+ Depuis la page de login
+ Saisir les informations de connexion et valider test_011_mdp ${NOUVEAU_MDP}
+ Valid Message Should Be Votre session est maintenant ouverte.
+
+ # Restaurer le mot de passe initial
+ Accéder au formulaire de changement de mot de passe
+ Soumettre le changement de mot de passe ${NOUVEAU_MDP} test_011_mdp test_011_mdp
+ Valid Message Should Be Votre mot de passe a été changé correctement
+
+
+Changement du mot de passe - mot de passe très long accepté
+ [Documentation] Les mots de passe sont hachés avec PASSWORD_ARGON2ID, il ne devrait pas y avoir de limite de longueur.
+
+ ${MDP_LONG} Set Variable mdp_tres_long_sans_limite_de_longueur_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+
+ Depuis la page d'accueil test_011_mdp test_011_mdp
+ Accéder au formulaire de changement de mot de passe
+ Soumettre le changement de mot de passe test_011_mdp ${MDP_LONG} ${MDP_LONG}
+ Valid Message Should Be Votre mot de passe a été changé correctement
+
+ # Vérifier que la connexion avec le mot de passe long fonctionne
+ Go To ${PROJECT_URL}
+ Se déconnecter
+ Depuis la page de login
+ Saisir les informations de connexion et valider test_011_mdp ${MDP_LONG}
+ Valid Message Should Be Votre session est maintenant ouverte.
+
+ # Restaurer le mot de passe initial
+ Accéder au formulaire de changement de mot de passe
+ Soumettre le changement de mot de passe ${MDP_LONG} test_011_mdp test_011_mdp
+ Valid Message Should Be Votre mot de passe a été changé correctement
+
+
Suppression de son propre utilisateur interdite
[Documentation]
@@ -113,10 +184,10 @@
Wait Until Keyword Succeeds ${TIMEOUT} ${RETRY_INTERVAL} Le titre de la page doit être Redéfinition Du Mot De Passe
Input Text css=#login plop
Click Element css=input[type='submit']
- Wait Until Keyword Succeeds ${TIMEOUT} ${RETRY_INTERVAL} Error Message Should Be Votre identifiant est incorrect, ou ne vous permet pas de redefinir votre mot de passe de cette manière. Contactez votre administrateur.
+ Error Message Should Be Votre identifiant est incorrect, ou ne vous permet pas de redefinir votre mot de passe de cette manière. Contactez votre administrateur.
Input Text css=#login admin
Click Element css=input[type='submit']
- Wait Until Keyword Succeeds ${TIMEOUT} ${RETRY_INTERVAL} Valid Message Should Be Un message de demande de ré-initialisation de mot de passe vous a été envoyé sur votre messagerie.
+ Valid Message Should Be Un message de demande de ré-initialisation de mot de passe vous a été envoyé sur votre messagerie.
# Accéder à maildump pour vérifier que le mail est bien présent et contient bien les accents
Go To
http://127.0.0.1:1080/
@@ -131,3 +202,32 @@
Depuis la page de login
Element Should Not Be Visible css=p.link-password-reset
+
+*** Keywords ***
+
+Composition du jeu de connées
+ Depuis la page d'accueil admin admin
+
+ Ajouter l'utilisateur test_011_mdp
test_0...@example.net test_011_mdp test_011_mdp ADMINISTRATEUR
+
+
+Accéder au formulaire de changement de mot de passe
+ Wait Until Element Is Visible css=a.actions-password
+ Click Element css=a.actions-password
+ Wait Until Element Is Visible css=#form-change-password
+
+
+Soumettre le changement de mot de passe
+ [Arguments] ${current} ${new} ${confirm}
+
+ Selenium2Library.Input Password css=#current-password ${current}
+ Selenium2Library.Input Password css=#new-password ${new}
+ Selenium2Library.Input Password css=#new-password-confirmation ${confirm}
+ Click Element css=input[name="submit-change-password"]
+
+
+Saisir les informations de connexion et valider
+ [Arguments] ${login} ${password}
+ Input Text login ${login}
+ Selenium2Library.Input Password password ${password}
+ Click Button login.action.connect
Modified: openmairie_exemple/branches/POC_migration_mots_de_passe/tests/config.xml
===================================================================
--- openmairie_exemple/branches/POC_migration_mots_de_passe/tests/config.xml 2026-02-27 18:03:43 UTC (rev 5497)
+++ openmairie_exemple/branches/POC_migration_mots_de_passe/tests/config.xml 2026-02-27 18:23:43 UTC (rev 5498)
@@ -6,6 +6,7 @@
<file>testOmDbForm.php</file>
<file>testREST.php</file>
<file>testCleanBreak.php</file>
+ <file>testAuthentification.php</file>
</testsuite>
</testsuites>
</phpunit>
Modified: openmairie_exemple/branches/POC_migration_mots_de_passe/tests/resources/resources.robot
===================================================================
--- openmairie_exemple/branches/POC_migration_mots_de_passe/tests/resources/resources.robot 2026-02-27 18:03:43 UTC (rev 5497)
+++ openmairie_exemple/branches/POC_migration_mots_de_passe/tests/resources/resources.robot 2026-02-27 18:23:43 UTC (rev 5498)
@@ -25,3 +25,22 @@
For Suite Teardown
Fermer le navigateur
+
+
+# TODO retirer avant de merger, il faut faire cette modification dans openmairie.robotframework
+Saisir l'utilisateur
+ [Documentation] Surchage pour le nouveau champ password_hash, à modifier dans la librairie
+ [Arguments] ${nom}=null ${email}=null ${login}=null ${password}=null ${profil}=null ${collectivite}=null
+
+ # On saisit le nom
+ Run Keyword If '${nom}' != 'null' Input Text nom ${nom}
+ # On saisit l'email
+ Run Keyword If '${email}' != 'null' Input Text email ${email}
+ # On saisit le login
+ Run Keyword If '${login}' != 'null' Input Text login ${login}
+ # On saisit le mot de passe
+ Run Keyword If '${password}' != 'null' Input Text password_hash ${password}
+ # On sélectionne la collectivité
+ Run Keyword If '${collectivite}' != 'null' Select From List By Label om_collectivite ${collectivite}
+ # On sélectionne le profil
+ Run Keyword If '${profil}' != 'null' Select From List By Label om_profil ${profil}
\ No newline at end of file
Added: openmairie_exemple/branches/POC_migration_mots_de_passe/tests/testAuthentification.php
===================================================================
--- openmairie_exemple/branches/POC_migration_mots_de_passe/tests/testAuthentification.php (rev 0)
+++ openmairie_exemple/branches/POC_migration_mots_de_passe/tests/testAuthentification.php 2026-02-27 18:23:43 UTC (rev 5498)
@@ -0,0 +1,263 @@
+<?php
+/**
+ * Ce script contient la définition de la classe 'AuthentificationTest'.
+ *
+ * @package framework_openmairie
+ * @version SVN : $Id$
+ */
+
+require_once "../tests/resources/omtestcase.class.php";
+
+/**
+ * Cette classe permet de tester unitairement la méthode processDatabaseAuthentication
+ * qui gère la migration transparente des mots de passe MD5 vers argon2id.
+ */
+final class AuthentificationTest extends OMTestCase {
+
+ /**
+ * Instance de l'application framework.
+ *
+ * @var framework_openmairie
+ */
+ protected \framework_openmairie $f;
+
+ /**
+ * Liste des IDs d'utilisateurs de test à supprimer dans tearDown.
+ *
+ * @var array
+ */
+ protected array $utilisateurs_a_nettoyer = array();
+
+ /**
+ * ID de profil valide récupéré en base.
+ *
+ * @var int|null
+ */
+ protected $om_profil_id = null;
+
+ /**
+ * ID de collectivité valide récupéré en base.
+ *
+ * @var int|null
+ */
+ protected $om_collectivite_id = null;
+
+ // -------------------------------------------------------------------------
+
+ public function setUp(): void {
+ parent::setUp();
+ parent::common_setUp();
+
+ $this->f = $this->get_inst_om_application();
+ $this->f->disableLog();
+
+ // Récupération d'un profil valide
+ $qres = $this->f->get_all_results_from_db_query(
+ "SELECT om_profil FROM ".DB_PREFIXE."om_profil LIMIT 1",
+ array('origin' => __METHOD__)
+ );
+ $this->om_profil_id = $qres['result'][0]['om_profil'];
+
+ // Récupération d'une collectivité valide
+ $qres = $this->f->get_all_results_from_db_query(
+ "SELECT om_collectivite FROM ".DB_PREFIXE."om_collectivite LIMIT 1",
+ array('origin' => __METHOD__)
+ );
+ $this->om_collectivite_id = $qres['result'][0]['om_collectivite'];
+ }
+
+ public function tearDown(): void {
+ // Nettoyage de tous les utilisateurs de test créés
+ foreach ($this->utilisateurs_a_nettoyer as $id) {
+ $this->f->execute_auto_db_query(
+ 'delete',
+ DB_PREFIXE."om_utilisateur",
+ array(),
+ "om_utilisateur=".$id,
+ array("origin" => __METHOD__, "force_return" => true)
+ );
+ }
+ $this->utilisateurs_a_nettoyer = array();
+
+ $this->f->__destruct();
+
+ parent::common_tearDown();
+ parent::tearDown();
+ }
+
+ public function onNotSuccessfulTest(Throwable $e): void {
+ parent::common_onNotSuccessfulTest($e);
+ parent::onNotSuccessfulTest($e);
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Insère un utilisateur de test en base et retourne son ID.
+ *
+ * @param string $login Login de l'utilisateur.
+ * @param string|null $pwd Hash MD5 (champ legacy), ou NULL.
+ * @param string|null $password_hash Hash argon2id, ou NULL.
+ *
+ * @return int L'ID de l'utilisateur inséré.
+ */
+ private function insererUtilisateurTest(string $login, $pwd, $password_hash): int {
+ $qres = $this->f->get_next_id_from_db_sequence(
+ DB_PREFIXE."om_utilisateur",
+ array("origin" => __METHOD__)
+ );
+ $id = $qres['result'];
+
+ $valF = array(
+ "om_utilisateur" => $id,
+ "nom" => "Utilisateur Test Auth",
+ "email" => "
test...@example.com",
+ "login" => $login,
+ "pwd" => $pwd,
+ "password_hash" => $password_hash,
+ "om_profil" => $this->om_profil_id,
+ "om_collectivite" => $this->om_collectivite_id,
+ );
+
+ $this->f->execute_auto_db_query(
+ 'insert',
+ DB_PREFIXE."om_utilisateur",
+ $valF,
+ null,
+ array("origin" => __METHOD__, "force_return" => true)
+ );
+
+ $this->utilisateurs_a_nettoyer[] = $id;
+
+ return $id;
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Test 1 : Un login inexistant doit retourner false.
+ */
+ public function test_processDatabaseAuthentication__login_inconnu() {
+ $result = $this->f->processDatabaseAuthentication(
+ 'login_qui_nexiste_pas_test_auth',
+ 'n_importe_quoi'
+ );
+
+ $this->assertFalse($result);
+ }
+
+ /**
+ * Test 2 : Compte avec mot de passe MD5, bon mot de passe.
+ *
+ * Vérifie que :
+ * - l'authentification retourne true
+ * - la migration a eu lieu (pwd = NULL, password_hash commence par $argon2id$)
+ */
+ public function test_processDatabaseAuthentication__compte_md5_bon_mot_de_passe() {
+ $login = 'test_auth_01';
+ $password = 'secret_test';
+
+ $this->insererUtilisateurTest($login, md5($password), null);
+
+ $result = $this->f->processDatabaseAuthentication($login, $password);
+
+ $this->assertTrue($result);
+
+ // Vérification que la migration a bien eu lieu
+ $qres = $this->f->get_all_results_from_db_query(
+ "SELECT pwd, password_hash FROM ".DB_PREFIXE."om_utilisateur WHERE login='".$login."'",
+ array('origin' => __METHOD__)
+ );
+ $row = $qres['result'][0];
+
+ // La couche PEAR DB convertit le null PHP en '' lors du UPDATE (comportement normal).
+ // La logique d'auth utilise !empty($pwd), donc '' est traité comme migré — identique à NULL.
+ $this->assertEmpty($row['pwd'], "Le champ 'pwd' doit être vidé (NULL ou chaîne vide) après migration.");
+ $this->assertStringStartsWith(
+ '$argon2id$',
+ $row['password_hash'],
+ "Le champ 'password_hash' doit commencer par '\$argon2id\$' après migration."
+ );
+ }
+
+ /**
+ * Test 3 : Compte avec mot de passe MD5, mauvais mot de passe.
+ *
+ * Vérifie que :
+ * - l'authentification retourne false
+ * - la migration n'a PAS eu lieu (pwd reste non null et inchangé)
+ */
+ public function test_processDatabaseAuthentication__compte_md5_mauvais_mot_de_passe() {
+ $login = 'test_auth_02';
+ $password = 'secret_test';
+
+ $this->insererUtilisateurTest($login, md5($password), null);
+
+ $result = $this->f->processDatabaseAuthentication($login, 'mauvais_mot_de_passe');
+
+ $this->assertFalse($result);
+
+ // Vérification que la migration n'a PAS eu lieu
+ $qres = $this->f->get_all_results_from_db_query(
+ "SELECT pwd, password_hash FROM ".DB_PREFIXE."om_utilisateur WHERE login='".$login."'",
+ array('origin' => __METHOD__)
+ );
+ $row = $qres['result'][0];
+
+ $this->assertNotNull($row['pwd'], "Le champ 'pwd' doit rester non null (pas de migration).");
+ $this->assertEquals(md5($password), $row['pwd'], "Le hash MD5 ne doit pas avoir changé.");
+ }
+
+ /**
+ * Test 4 : Compte avec mot de passe argon2id, bon mot de passe.
+ *
+ * Vérifie que l'authentification retourne true.
+ */
+ public function test_processDatabaseAuthentication__compte_argon2id_bon_mot_de_passe() {
+ $login = 'test_auth_03';
+ $password = 'secret_test';
+
+ $this->insererUtilisateurTest($login, null, password_hash($password, PASSWORD_ARGON2ID));
+
+ $result = $this->f->processDatabaseAuthentication($login, $password);
+
+ $this->assertTrue($result);
+ }
+
+ /**
+ * Test 5 : Compte avec mot de passe argon2id, mauvais mot de passe.
+ *
+ * Vérifie que l'authentification retourne false.
+ */
+ public function test_processDatabaseAuthentication__compte_argon2id_mauvais_mot_de_passe() {
+ $login = 'test_auth_04';
+ $password = 'secret_test';
+
+ $this->insererUtilisateurTest($login, null, password_hash($password, PASSWORD_ARGON2ID));
+
+ $result = $this->f->processDatabaseAuthentication($login, 'mauvais_mot_de_passe');
+
+ $this->assertFalse($result);
+ }
+
+ /**
+ * Test 6 : Authentification avec un mot de passe très long (500 caractères).
+ *
+ * Argon2id n'a pas de limite de longueur contrairement à bcrypt (72 octets).
+ * Vérifie que l'authentification retourne true.
+ */
+ public function test_processDatabaseAuthentication__mot_de_passe_tres_long() {
+ $login = 'test_auth_05';
+ $long_password = str_repeat('A', 500);
+
+ $this->insererUtilisateurTest(
+ $login,
+ null,
+ password_hash($long_password, PASSWORD_ARGON2ID)
+ );
+
+ $result = $this->f->processDatabaseAuthentication($login, $long_password);
+
+ $this->assertTrue($result);
+ }
+}
Property changes on: openmairie_exemple/branches/POC_migration_mots_de_passe/tests/testAuthentification.php
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property