Merge pull request #14 from tips-of-mine/fix/password-edit-view-paths

fix: Corriger les chemins d'inclusion dans la vue edit_password
This commit is contained in:
tips-of-mine
2025-06-15 21:14:57 +02:00
committed by GitHub
6 changed files with 181 additions and 4 deletions

View File

@ -216,6 +216,8 @@ $router->addRoute('GET', '/users/create', 'UserController@showCreateForm', true)
$router->addRoute('POST', '/users/create', 'UserController@create', true); $router->addRoute('POST', '/users/create', 'UserController@create', true);
$router->addRoute('POST', '/users/delete', 'UserController@delete', true); $router->addRoute('POST', '/users/delete', 'UserController@delete', true);
$router->addRoute('POST', '/users/toggle-admin', 'UserController@toggleAdminRole', true); $router->addRoute('POST', '/users/toggle-admin', 'UserController@toggleAdminRole', true);
$router->addRoute('GET', '/users/edit-password/{id}', 'UserController@showEditPasswordForm', true); // Nouvelle route GET
$router->addRoute('POST', '/users/update-password', 'UserController@updatePassword', true); // Nouvelle route POST
$router->addRoute('GET', '/logout', 'AuthController@logout', true); $router->addRoute('GET', '/logout', 'AuthController@logout', true);
// Exécuter le routage // Exécuter le routage

View File

@ -142,6 +142,109 @@ class UserController
exit(); exit();
} }
/**
* Affiche le formulaire de modification du mot de passe pour un utilisateur.
*
* @param int $userId L'ID de l'utilisateur.
*/
public function showEditPasswordForm(int $userId)
{
$this->requireAdmin();
global $translations; // Utilisé par la vue
$currentLang = $this->langService->getLanguage(); // Utilisé par la vue
$darkModeClass = DarkMode::getBodyClass(); // Utilisé par la vue
$stmt = $this->db->prepare("SELECT id, username FROM users WHERE id = ?");
$stmt->execute([$userId]);
$user = $stmt->fetch();
if (!$user) {
$_SESSION['error'] = $this->langService->__('user_not_found');
header('Location: /users');
exit();
}
$errorMessage = $_SESSION['error'] ?? null;
unset($_SESSION['error']); // Effacer le message d'erreur après l'avoir récupéré
require_once APP_ROOT_DIR . '/src/Views/users/edit_password.php';
}
/**
* Traite la soumission du formulaire de mise à jour du mot de passe.
*/
public function updatePassword()
{
$this->requireAdmin();
$ipAddress = $_SERVER['REMOTE_ADDR'];
$adminUserId = $this->authService->getUserId(); // Pour les logs
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('Location: /users');
exit();
}
$userId = $_POST['user_id'] ?? null;
$newPassword = $_POST['new_password'] ?? '';
$confirmPassword = $_POST['confirm_password'] ?? '';
if (empty($userId) || empty($newPassword) || empty($confirmPassword)) {
$_SESSION['error'] = $this->langService->__('password_update_error_empty_fields');
// Rediriger vers le formulaire d'édition du mot de passe de l'utilisateur concerné
header('Location: /users/edit-password/' . $userId);
exit();
}
if ($newPassword !== $confirmPassword) {
$_SESSION['error'] = $this->langService->__('password_update_error_mismatch');
header('Location: /users/edit-password/' . $userId);
exit();
}
// Récupérer les informations de l'utilisateur à modifier
$stmtUser = $this->db->prepare("SELECT username FROM users WHERE id = ?");
$stmtUser->execute([$userId]);
$userToUpdate = $stmtUser->fetch();
if (!$userToUpdate) {
$_SESSION['error'] = $this->langService->__('user_not_found');
header('Location: /users'); // Ou une page d'erreur générique
exit();
}
// Empêcher la modification du mot de passe de l'utilisateur "admin" (ou un nom spécifique)
// Vous pouvez rendre le nom "admin" configurable si nécessaire
if ($userToUpdate['username'] === 'admin') {
$_SESSION['error'] = $this->langService->__('cannot_change_admin_password');
$this->logService->log('warning', "Tentative de modification du mot de passe de l'administrateur principal '{$userToUpdate['username']}' par l'admin ID: {$adminUserId}.", $adminUserId, $ipAddress);
header('Location: /users/edit-password/' . $userId);
exit();
}
$hashedPassword = password_hash($newPassword, PASSWORD_DEFAULT);
try {
$stmt = $this->db->prepare("UPDATE users SET password = ? WHERE id = ?");
$stmt->execute([$hashedPassword, $userId]);
if ($stmt->rowCount() > 0) {
$this->logService->log('info', "Mot de passe de l'utilisateur '{$userToUpdate['username']}' (ID: {$userId}) modifié par l'administrateur ID: {$adminUserId}.", $adminUserId, $ipAddress);
$_SESSION['success'] = $this->langService->__('password_update_success', ['username' => htmlspecialchars($userToUpdate['username'])]);
} else {
// Ce cas peut arriver si le mot de passe est identique ou si l'utilisateur n'existe pas (déjà vérifié mais par sécurité)
$_SESSION['error'] = $this->langService->__('password_update_error_db'); // Ou un message plus spécifique
}
} catch (PDOException $e) {
error_log("Erreur lors de la mise à jour du mot de passe: " . $e->getMessage());
$_SESSION['error'] = $this->langService->__('password_update_error_db');
$this->logService->log('error', "Échec de la mise à jour du mot de passe pour '{$userToUpdate['username']}' (ID: {$userId}): " . $e->getMessage(), $adminUserId, $ipAddress);
}
header('Location: /users');
exit();
}
/** /**
* Supprime un utilisateur. * Supprime un utilisateur.
*/ */

View File

@ -90,8 +90,19 @@
"confirm_toggle_admin_role": "Are you sure you want to modify this user's role?", "confirm_toggle_admin_role": "Are you sure you want to modify this user's role?",
"remove_admin_status": "Remove Admin", "remove_admin_status": "Remove Admin",
"pass_to_admin": "Make Admin", "pass_to_admin": "Make Admin",
"cannot_change_main_admin_role": "Role not modifiable" "cannot_change_main_admin_role": "Role not modifiable",
"cert_revoke_success_intermediate": "Intermediate certificate '{name}' has been successfully revoked and the Root CA CRL has been updated.", "cert_revoke_success_intermediate": "Intermediate certificate '{name}' has been successfully revoked and the Root CA CRL has been updated.",
"cert_revoke_warn_crl_update_failed_intermediate": "Intermediate certificate '{name}' has been revoked, but updating the Root CA CRL encountered an issue. Please contact an administrator.", "cert_revoke_warn_crl_update_failed_intermediate": "Intermediate certificate '{name}' has been revoked, but updating the Root CA CRL encountered an issue. Please contact an administrator.",
"cert_revoke_error_intermediate": "Error revoking intermediate certificate '{name}': {output}" "cert_revoke_error_intermediate": "Error revoking intermediate certificate '{name}': {output}",
"edit_password_title": "Edit Password",
"new_password": "New Password",
"confirm_new_password": "Confirm New Password",
"update_password_button": "Update Password",
"editing_password_for_user": "Editing password for user: %username%",
"password_update_error_empty_fields": "Please fill in all password fields.",
"password_update_error_mismatch": "Passwords do not match.",
"cannot_change_admin_password": "The main administrator's password cannot be changed through this interface.",
"password_update_error_db": "Error updating password. Please try again.",
"password_update_success": "User %username%'s password has been successfully updated.",
"edit_password_button": "Edit Pwd"
} }

View File

@ -90,8 +90,19 @@
"confirm_toggle_admin_role": "Êtes-vous sûr de vouloir modifier le rôle de cet utilisateur ?", "confirm_toggle_admin_role": "Êtes-vous sûr de vouloir modifier le rôle de cet utilisateur ?",
"remove_admin_status": "Retirer Admin", "remove_admin_status": "Retirer Admin",
"pass_to_admin": "Passer Admin", "pass_to_admin": "Passer Admin",
"cannot_change_main_admin_role": "Rôle non modifiable" "cannot_change_main_admin_role": "Rôle non modifiable",
"cert_revoke_success_intermediate": "Le certificat intermédiaire '{name}' a été révoqué avec succès et la CRL du CA Racine a été mise à jour.", "cert_revoke_success_intermediate": "Le certificat intermédiaire '{name}' a été révoqué avec succès et la CRL du CA Racine a été mise à jour.",
"cert_revoke_warn_crl_update_failed_intermediate": "Le certificat intermédiaire '{name}' a été révoqué, mais la mise à jour de la CRL du CA Racine a rencontré un problème. Veuillez contacter un administrateur.", "cert_revoke_warn_crl_update_failed_intermediate": "Le certificat intermédiaire '{name}' a été révoqué, mais la mise à jour de la CRL du CA Racine a rencontré un problème. Veuillez contacter un administrateur.",
"cert_revoke_error_intermediate": "Erreur lors de la révocation du certificat intermédiaire '{name}': {output}" "cert_revoke_error_intermediate": "Erreur lors de la révocation du certificat intermédiaire '{name}': {output}",
"edit_password_title": "Modifier le mot de passe",
"new_password": "Nouveau mot de passe",
"confirm_new_password": "Confirmer le nouveau mot de passe",
"update_password_button": "Mettre à jour le mot de passe",
"editing_password_for_user": "Modification du mot de passe pour l'utilisateur : %username%",
"password_update_error_empty_fields": "Veuillez remplir tous les champs de mot de passe.",
"password_update_error_mismatch": "Les mots de passe ne correspondent pas.",
"cannot_change_admin_password": "Le mot de passe de l'administrateur principal ne peut pas être modifié via cette interface.",
"password_update_error_db": "Erreur lors de la mise à jour du mot de passe. Veuillez réessayer.",
"password_update_success": "Le mot de passe de l'utilisateur %username% a été mis à jour avec succès.",
"edit_password_button": "Modifier Mdp"
} }

View File

@ -0,0 +1,36 @@
<?php
// Variables attendues du contrôleur: $user, $translations, $currentLang, $darkModeClass, $errorMessage (optionnel)
require_once APP_ROOT_DIR . '/src/Views/shared/header.php';
?>
<div class="container mt-5">
<h2><?= htmlspecialchars($translations['edit_password_title'] ?? 'Edit Password Title') ?></h2>
<?php if (isset($errorMessage)): ?>
<div class="alert alert-danger" role="alert">
<?= htmlspecialchars($errorMessage) ?>
</div>
<?php endif; ?>
<p><?= htmlspecialchars($translations['editing_password_for_user'] ?? 'Editing password for user: %username%') ?>: <strong><?= htmlspecialchars($user['username'] ?? '') ?></strong></p>
<form action="/users/update-password" method="POST">
<input type="hidden" name="user_id" value="<?= htmlspecialchars($user['id'] ?? '') ?>">
<div class="mb-3">
<label for="new_password" class="form-label"><?= htmlspecialchars($translations['new_password'] ?? 'New Password') ?></label>
<input type="password" class="form-control" id="new_password" name="new_password" required>
</div>
<div class="mb-3">
<label for="confirm_password" class="form-label"><?= htmlspecialchars($translations['confirm_new_password'] ?? 'Confirm New Password') ?></label>
<input type="password" class="form-control" id="confirm_password" name="confirm_password" required>
</div>
<button type="submit" class="btn btn-primary"><?= htmlspecialchars($translations['update_password_button'] ?? 'Update Password') ?></button>
</form>
</div>
<?php
require_once APP_ROOT_DIR . '/src/Views/shared/footer.php';
?>

View File

@ -50,6 +50,20 @@ require_once APP_ROOT_DIR . '/src/Views/shared/header.php';
<em><?= htmlspecialchars($translations['cannot_change_main_admin_role'] ?? 'Rôle non modifiable') ?></em> <em><?= htmlspecialchars($translations['cannot_change_main_admin_role'] ?? 'Rôle non modifiable') ?></em>
<?php endif; ?> <?php endif; ?>
<?php // Bouton Modifier le mot de passe
// Ne pas afficher pour l'utilisateur 'admin' ni pour l'admin connecté (pour son propre compte)
if ($user['username'] !== 'admin' && $user['id'] !== $authService->getUserId()): ?>
<a href="/users/edit-password/<?= htmlspecialchars($user['id']) ?>" class="button secondary-button"><?= htmlspecialchars($translations['edit_password_button'] ?? 'Modifier Mdp') ?></a>
<?php elseif ($user['username'] === 'admin'): ?>
<?php // Optionnel: Mettre un placeholder ou rien pour l'utilisateur 'admin' pour ce bouton
// echo '<em>N/A</em>'; // Par exemple
?>
<?php elseif ($user['id'] === $authService->getUserId()): ?>
<?php // Optionnel: Mettre un placeholder ou rien pour l'admin connecté pour son propre compte
// echo '<em>N/A</em>'; // Par exemple
?>
<?php endif; ?>
<?php if ($user['id'] !== $authService->getUserId() && $user['username'] !== 'admin'): // Condition existante pour la suppression, légèrement ajustée pour être sûr que 'admin' n'est pas supprimable non plus via cette interface ?> <?php if ($user['id'] !== $authService->getUserId() && $user['username'] !== 'admin'): // Condition existante pour la suppression, légèrement ajustée pour être sûr que 'admin' n'est pas supprimable non plus via cette interface ?>
<form action="/users/delete" method="post" class="inline-form" onsubmit="return confirm('<?= htmlspecialchars($translations['confirm_delete_user']) ?>');"> <form action="/users/delete" method="post" class="inline-form" onsubmit="return confirm('<?= htmlspecialchars($translations['confirm_delete_user']) ?>');">
<input type="hidden" name="user_id" value="<?= htmlspecialchars($user['id']) ?>"> <input type="hidden" name="user_id" value="<?= htmlspecialchars($user['id']) ?>">