525 lines
20 KiB
PHP

<?php
require_once '../includes/config.php';
require_once '../includes/auth.php';
// Vérification de l'authentification
if (!Auth::check()) {
header('Location: login.php');
exit;
}
// Vérification des privilèges administrateur (premier utilisateur uniquement)
if (!Auth::isAdmin()) {
header('Location: index.php');
exit;
}
$success = '';
$error = '';
// Traitement de l'ajout ou modification d'un utilisateur
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
try {
$config = Config::load();
// Traitement selon l'action
switch ($_POST['action']) {
case 'add':
// Validation
$userId = trim($_POST['user_id'] ?? '');
$password = $_POST['password'] ?? '';
$confirmPassword = $_POST['confirm_password'] ?? '';
$comment = trim($_POST['comment'] ?? '');
$role = $_POST['role'] ?? 'editor';
if (strlen($userId) < 3) {
throw new Exception('L\'identifiant doit faire au moins 3 caractères');
}
if (strlen($password) < 8) {
throw new Exception('Le mot de passe doit faire au moins 8 caractères');
}
if ($password !== $confirmPassword) {
throw new Exception('Les mots de passe ne correspondent pas');
}
// Vérification de l'unicité de l'identifiant
foreach ($config['users'] as $user) {
if ($user['id'] === $userId) {
throw new Exception('Cet identifiant est déjà utilisé');
}
}
// Ajout de l'utilisateur
$config['users'][] = [
'id' => $userId,
'password' => password_hash($password, PASSWORD_DEFAULT),
'role' => $role,
'comment' => $comment
];
$success = 'Utilisateur ajouté avec succès';
break;
case 'edit':
// Validation
$userId = trim($_POST['user_id'] ?? '');
$newUserId = trim($_POST['new_user_id'] ?? '');
$password = $_POST['password'] ?? '';
$comment = trim($_POST['comment'] ?? '');
$role = $_POST['role'] ?? 'editor';
if ($newUserId && strlen($newUserId) < 3) {
throw new Exception('Le nouvel identifiant doit faire au moins 3 caractères');
}
if ($password && strlen($password) < 8) {
throw new Exception('Le mot de passe doit faire au moins 8 caractères');
}
// Recherche de l'utilisateur à modifier
$userFound = false;
foreach ($config['users'] as &$user) {
if ($user['id'] === $userId) {
// Vérification que le premier compte ne perde pas ses privilèges admin
if ($user === reset($config['users']) && $role !== 'admin') {
throw new Exception('Le premier compte doit conserver le rôle d\'administrateur');
}
// Mise à jour des informations
if ($newUserId && $newUserId !== $userId) {
// Vérification de l'unicité du nouvel identifiant
foreach ($config['users'] as $existingUser) {
if ($existingUser['id'] === $newUserId) {
throw new Exception('Ce nouvel identifiant est déjà utilisé');
}
}
$user['id'] = $newUserId;
}
if ($password) {
$user['password'] = password_hash($password, PASSWORD_DEFAULT);
}
$user['comment'] = $comment;
$user['role'] = $role;
$userFound = true;
break;
}
}
if (!$userFound) {
throw new Exception('Utilisateur non trouvé');
}
$success = 'Utilisateur modifié avec succès';
break;
case 'delete':
// Validation
$userId = trim($_POST['user_id'] ?? '');
// Empêcher la suppression du premier utilisateur
if ($userId === reset($config['users'])['id']) {
throw new Exception('Le compte administrateur principal ne peut pas être supprimé');
}
// Recherche et suppression de l'utilisateur
$userIndex = -1;
foreach ($config['users'] as $index => $user) {
if ($user['id'] === $userId) {
$userIndex = $index;
break;
}
}
if ($userIndex === -1) {
throw new Exception('Utilisateur non trouvé');
}
array_splice($config['users'], $userIndex, 1);
$success = 'Utilisateur supprimé avec succès';
break;
}
// Sauvegarde de la configuration
Config::save($config);
} catch (Exception $e) {
$error = $e->getMessage();
}
}
// Chargement de la configuration
$config = Config::load();
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gestion des utilisateurs - Administration</title>
<?php if (file_exists(__DIR__ . '/../assets/images/site/favicon.png')): ?>
<link rel="icon" type="image/png" href="../assets/images/site/favicon.png">
<?php endif; ?>
<link rel="stylesheet" href="../assets/css/main.css">
</head>
<body>
<nav class="admin-nav">
<div class="nav-brand">
<?php if (!empty($config['site']['logo'])): ?>
<img src="<?= htmlspecialchars('../' . $config['site']['logo']) ?>"
alt="<?= htmlspecialchars($config['site']['name']) ?>">
<?php endif; ?>
<span>Administration</span>
</div>
<div class="nav-menu">
<a href="index.php" class="button tooltip" data-tooltip="Retour">
<i class="fas fa-arrow-left"></i>
</a>
</div>
</nav>
<main class="admin-main">
<h1>Gestion des utilisateurs</h1>
<?php if ($success): ?>
<div class="success-message"><?= htmlspecialchars($success) ?></div>
<?php endif; ?>
<?php if ($error): ?>
<div class="error-message"><?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<!-- Liste des utilisateurs existants -->
<section class="users-section">
<h2>Utilisateurs existants</h2>
<div class="users-list">
<?php foreach ($config['users'] as $index => $user): ?>
<div class="user-item <?= $index === 0 ? 'admin-user' : '' ?>">
<div class="user-info">
<h3><?= htmlspecialchars($user['id']) ?></h3>
<p class="user-role">
Rôle : <span><?= htmlspecialchars($user['role'] ?? 'editor') ?></span>
</p>
<?php if (!empty($user['comment'])): ?>
<p class="user-comment"><?= htmlspecialchars($user['comment']) ?></p>
<?php endif; ?>
</div>
<div class="user-actions">
<button type="button" class="button tooltip edit-user" data-tooltip="Modifier" data-user-id="<?= htmlspecialchars($user['id']) ?>" data-user-comment="<?= htmlspecialchars($user['comment'] ?? '') ?>" data-user-role="<?= htmlspecialchars($user['role'] ?? 'editor') ?>">
<i class="fas fa-edit"></i>
</button>
<?php if ($index !== 0): ?>
<button type="button" class="button tooltip delete-user" data-tooltip="Supprimer" data-user-id="<?= htmlspecialchars($user['id']) ?>">
<i class="fas fa-trash-alt"></i>
</button>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<button type="button" id="addUserBtn" class="button tooltip" data-tooltip="Ajouter un utilisateur">
<i class="fas fa-user-plus"></i>
<span class="tooltip-text">Ajouter un utilisateur</span>
</button>
</section>
<!-- Formulaire d'ajout d'utilisateur (modal) -->
<div id="addUserModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h2>Ajouter un utilisateur</h2>
</div>
<form method="POST" id="addUserForm">
<input type="hidden" name="action" value="add">
<div class="form-group">
<label for="user_id">Identifiant</label>
<input type="text" id="user_id" name="user_id" required minlength="3">
</div>
<div class="form-group">
<label for="password">Mot de passe</label>
<input type="password" id="password" name="password" required minlength="8">
</div>
<div class="form-group">
<label for="confirm_password">Confirmation du mot de passe</label>
<input type="password" id="confirm_password" name="confirm_password" required>
</div>
<div class="form-group">
<label for="role">Rôle</label>
<select id="role" name="role">
<option value="editor">Éditeur</option>
<option value="admin">Administrateur</option>
</select>
</div>
<div class="form-group">
<label for="comment">Commentaire (optionnel)</label>
<textarea id="comment" name="comment" rows="3"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="button dark cancel-btn">Annuler</button>
<button type="submit" class="button">Ajouter</button>
</div>
</form>
</div>
</div>
<!-- Formulaire d'édition d'utilisateur (modal) -->
<div id="editUserModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h2>Modifier un utilisateur</h2>
</div>
<form method="POST" id="editUserForm">
<input type="hidden" name="action" value="edit">
<input type="hidden" id="edit_user_id" name="user_id">
<div class="form-group">
<label for="new_user_id">Nouvel identifiant (laisser vide pour ne pas modifier)</label>
<input type="text" id="new_user_id" name="new_user_id" minlength="3">
</div>
<div class="form-group">
<label for="edit_password">Nouveau mot de passe (laisser vide pour ne pas modifier)</label>
<input type="password" id="edit_password" name="password" minlength="8">
</div>
<div class="form-group">
<label for="edit_role">Rôle</label>
<select id="edit_role" name="role">
<option value="editor">Éditeur</option>
<option value="admin">Administrateur</option>
</select>
</div>
<div class="form-group">
<label for="edit_comment">Commentaire</label>
<textarea id="edit_comment" name="comment" rows="3"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="button dark cancel-btn">
<i class="fas fa-times"></i>
<span class="button-text">Annuler</span>
</button>
<button type="submit" class="button">
<i class="fas fa-save"></i>
<span class="button-text">Enregistrer</span>
</button>
</div>
</form>
</div>
</div>
<!-- Formulaire de suppression (caché) -->
<form id="deleteUserForm" method="POST" style="display: none;">
<input type="hidden" name="action" value="delete">
<input type="hidden" id="delete_user_id" name="user_id">
</form>
</main>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Gestion des modales
const addUserModal = document.getElementById('addUserModal');
const editUserModal = document.getElementById('editUserModal');
// Boutons d'ouverture des modales
const addUserBtn = document.getElementById('addUserBtn');
// Boutons de fermeture des modales
const cancelBtns = document.querySelectorAll('.cancel-btn');
// Ouverture de la modale d'ajout
addUserBtn.addEventListener('click', function() {
addUserModal.style.display = 'block';
document.getElementById('addUserForm').reset();
});
// Ouverture de la modale d'édition
document.querySelectorAll('.edit-user').forEach(button => {
button.addEventListener('click', function() {
const userId = this.dataset.userId;
const userComment = this.dataset.userComment;
const userRole = this.dataset.userRole;
document.getElementById('edit_user_id').value = userId;
document.getElementById('new_user_id').value = '';
document.getElementById('edit_password').value = '';
document.getElementById('edit_comment').value = userComment;
// Sélectionner la bonne option dans le select
const roleSelect = document.getElementById('edit_role');
for (let i = 0; i < roleSelect.options.length; i++) {
if (roleSelect.options[i].value === userRole) {
roleSelect.selectedIndex = i;
break;
}
}
// Si c'est le premier utilisateur, désactiver le changement de rôle
if (userId === '<?= htmlspecialchars(reset($config['users'])['id']) ?>') {
roleSelect.disabled = true;
} else {
roleSelect.disabled = false;
}
editUserModal.style.display = 'block';
});
});
// Fermeture des modales avec les boutons Annuler
cancelBtns.forEach(button => {
button.addEventListener('click', function() {
addUserModal.style.display = 'none';
editUserModal.style.display = 'none';
});
});
// Fermeture des modales en cliquant à l'extérieur
window.addEventListener('click', function(event) {
if (event.target === addUserModal) {
addUserModal.style.display = 'none';
} else if (event.target === editUserModal) {
editUserModal.style.display = 'none';
}
});
// Validation du formulaire d'ajout
document.getElementById('addUserForm').addEventListener('submit', function(e) {
const password = document.getElementById('password').value;
const confirmPassword = document.getElementById('confirm_password').value;
if (password !== confirmPassword) {
e.preventDefault();
alert('Les mots de passe ne correspondent pas');
}
});
// Suppression d'un utilisateur
document.querySelectorAll('.delete-user').forEach(button => {
button.addEventListener('click', function() {
const userId = this.dataset.userId;
confirmDialog.show({
title: 'Suppression d\'utilisateur',
message: `Voulez-vous vraiment supprimer l'utilisateur "${userId}" ? Cette action est irréversible.`,
confirmText: 'Supprimer',
confirmClass: 'danger',
onConfirm: () => {
document.getElementById('delete_user_id').value = userId;
document.getElementById('deleteUserForm').submit();
}
});
});
});
});
</script>
<link rel="stylesheet" href="../assets/css/dialog.css">
<script src="../assets/js/dialog.js"></script>
<style>
/* Styles spécifiques à la page utilisateurs */
.users-list {
display: flex;
flex-direction: column;
gap: var(--spacing-md);
margin: var(--spacing-lg) 0;
}
.user-item {
background: var(--bg-tertiary);
padding: var(--spacing-lg);
border-radius: var(--radius-md);
border: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
}
.user-item.admin-user {
background: linear-gradient(135deg, var(--bg-tertiary), #57433a);
position: relative;
}
.user-item.admin-user::after {
content: 'Admin principal';
position: absolute;
top: 0.5rem;
right: 0.5rem;
background: var(--accent-primary);
color: var(--text-tertiary);
padding: 0.2rem 0.5rem;
border-radius: var(--radius-sm);
font-size: 0.8rem;
}
.user-info h3 {
margin: 0 0 var(--spacing-xs) 0;
color: var(--text-primary);
}
.user-role {
color: var(--text-secondary);
margin: 0 0 var(--spacing-xs) 0;
}
.user-role span {
color: var(--accent-primary);
}
.user-comment {
font-style: italic;
color: var(--text-secondary);
margin: 0;
font-size: 0.9rem;
}
.user-actions {
display: flex;
gap: var(--spacing-sm);
}
.user-actions .button {
padding: var(--spacing-sm) var(--spacing-md);
}
.delete-user {
background-color: var(--bg-secondary);
}
.delete-user:hover {
background-color: var(--error-color);
}
/* Responsiveness */
@media (max-width: 768px) {
.user-item {
flex-direction: column;
align-items: stretch;
}
.user-actions {
margin-top: var(--spacing-md);
justify-content: flex-end;
}
.modal-content {
width: 95%;
max-width: 600px;
height: auto;
max-height: 90vh;
overflow-y: auto;
}
}
</style>
</body>
</html>