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.auth@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); } }