ajout projet cms elyes

This commit is contained in:
elyes
2025-11-03 00:39:36 +01:00
parent a1f7262e89
commit daa719eac7
25 changed files with 924 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
<?php
// Inclusion des fichiers de config, BDD et fonctions
require_once __DIR__ . '/../inc/config.php';
require_once __DIR__ . '/../inc/db.php';
require_once __DIR__ . '/../inc/functions.php';
// Vérifie que l'utilisateur est connecté, sinon redirection
require_login();
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Vérifie la validité du jeton CSRF pour éviter les attaques
verify_csrf();
// Récupération et nettoyage des champs du formulaire
$titre = trim($_POST['titre'] ?? '');
$contenu = trim($_POST['contenu'] ?? '');
// Vérifie si les champs obligatoires sont remplis
if ($titre === '' || $contenu === '') {
$errors[] = "Tous les champs sont obligatoires.";
}
// Si pas d'erreurs, insertion de l'article dans la base
if (!$errors) {
$stmt = $pdo->prepare("INSERT INTO articles (user_id, titre, contenu, date_creation) VALUES (:uid, :titre, :contenu, NOW())");
$stmt->execute([
'uid'=>current_user_id(), // ID de l'auteur connecté
'titre'=>$titre,
'contenu'=>$contenu
]);
// Redirection vers le tableau de bord après publication
header('Location: /admin/dashboard.php');
exit;
}
}
// Inclusion du header
require_once __DIR__ . '/../inc/header.php';
?>
<h2>Écrire un article</h2>
<!-- Affiche les erreurs éventuelles -->
<?php if ($errors): ?>
<div class="error">
<?php foreach ($errors as $e): ?>
<p><?= e($e) ?></p>
<?php endforeach; ?>
</div>
<?php endif; ?>
<!-- Formulaire de création d'article -->
<form method="post">
<?= csrf_input() ?> <!-- Jeton CSRF caché -->
<div class="form-group">
<label>Titre</label>
<input type="text" name="titre" value="<?= e($_POST['titre'] ?? '') ?>">
</div>
<div class="form-group">
<label>Contenu</label>
<textarea name="contenu"><?= e($_POST['contenu'] ?? '') ?></textarea>
</div>
<!-- Bouton publier et annuler -->
<button class="btn primary" type="submit">Publier</button>
<a class="btn" href="/admin/dashboard.php">Annuler</a>
</form>
<?php
// Inclusion du footer
require_once __DIR__ . '/../inc/footer.php';
?>

View File

@@ -0,0 +1,60 @@
<?php
// Charge la config, la connexion BDD et les fonctions
require_once __DIR__ . '/../inc/config.php';
require_once __DIR__ . '/../inc/db.php';
require_once __DIR__ . '/../inc/functions.php';
// Accès réservé aux utilisateurs connectés
require_login();
// Récupère l'ID de l'article depuis l'URL et le valide
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id <= 0) { header('Location: /admin/dashboard.php'); exit; }
// Charge les infos de l'article (pour vérifier droits + afficher le titre)
$stmt = $pdo->prepare("SELECT id, user_id, titre FROM articles WHERE id = :id");
$stmt->execute(['id'=>$id]);
$article = $stmt->fetch();
if (!$article) { header('Location: /admin/dashboard.php'); exit; }
// Contrôle d'autorisation : admin ou auteur du post
if (!is_admin() && (int)$article['user_id'] !== current_user_id()) {
http_response_code(403); // interdit
echo "<div class='card error'><p>Accès refusé.</p></div>";
exit;
}
// Traitement du formulaire de confirmation (méthode POST + CSRF)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf(); // vérifie le jeton CSRF
// Si l'utilisateur confirme, on supprime l'article
if (isset($_POST['confirm']) && $_POST['confirm'] === 'yes') {
$del = $pdo->prepare("DELETE FROM articles WHERE id = :id");
$del->execute(['id'=>$id]);
}
// Retour au tableau de bord dans tous les cas
header('Location: /admin/dashboard.php');
exit;
}
// Affichage
require_once __DIR__ . '/../inc/header.php';
?>
<h2>Supprimer l'article</h2>
<div class="card">
<!-- Rappel du titre pour confirmation -->
<p>Supprimer <strong><?= e($article['titre']) ?></strong> ?</p>
<!-- Formulaire de confirmation (protégé CSRF) -->
<form method="post" style="display:inline">
<?= csrf_input() ?> <!-- jeton CSRF -->
<input type="hidden" name="confirm" value="yes">
<button class="btn danger" type="submit">Oui, supprimer</button>
</form>
<!-- Lien d'annulation -->
<a class="btn" href="/admin/dashboard.php">Annuler</a>
</div>
<?php require_once __DIR__ . '/../inc/footer.php'; ?>

View File

@@ -0,0 +1,82 @@
<?php
// Charge la configuration, la connexion BDD et les fonctions
require_once __DIR__ . '/../inc/config.php';
require_once __DIR__ . '/../inc/db.php';
require_once __DIR__ . '/../inc/functions.php';
// Restreint l'accès : uniquement pour utilisateurs connectés
require_login();
// Récupère et valide l'ID de l'article passé en GET
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
if ($id <= 0) { header('Location: /admin/dashboard.php'); exit; }
// Récupère l'article ciblé
$stmt = $pdo->prepare("SELECT id, user_id, titre, contenu FROM articles WHERE id = :id");
$stmt->execute(['id'=>$id]);
$article = $stmt->fetch();
if (!$article) { header('Location: /admin/dashboard.php'); exit; }
// Vérifie les droits : admin ou auteur de l'article
if (!is_admin() && (int)$article['user_id'] !== current_user_id()) {
http_response_code(403); // interdit
echo "<div class='card error'><p>Accès refusé.</p></div>";
exit;
}
// Gestion du formulaire d'édition
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf(); // protège contre les attaques CSRF
// Nettoyage et validation des champs
$titre = trim($_POST['titre'] ?? '');
$contenu = trim($_POST['contenu'] ?? '');
if ($titre === '' || $contenu === '') { $errors[] = "Tous les champs sont obligatoires."; }
// Si ok, mise à jour de l'article en BDD
if (!$errors) {
$stmt = $pdo->prepare("UPDATE articles SET titre=:titre, contenu=:contenu WHERE id=:id");
$stmt->execute(['titre'=>$titre,'contenu'=>$contenu,'id'=>$id]);
// Retour au tableau de bord après sauvegarde
header('Location: /admin/dashboard.php');
exit;
}
}
// Affichage de la page (header + formulaire + footer)
require_once __DIR__ . '/../inc/header.php';
?>
<h2>Modifier l'article #<?= (int)$article['id'] ?></h2>
<?php if ($errors): ?>
<div class="error">
<?php foreach ($errors as $e): ?>
<p><?= e($e) ?></p> <!-- messages d'erreur échappés -->
<?php endforeach; ?>
</div>
<?php endif; ?>
<form method="post">
<?= csrf_input() ?> <!-- champ caché CSRF -->
<div class="form-group">
<label>Titre</label>
<!-- Pré-remplit avec la valeur existante -->
<input type="text" name="titre" value="<?= e($_POST['titre'] ?? $article['titre']) ?>">
</div>
<div class="form-group">
<label>Contenu</label>
<!-- Pré-remplit avec la saisie en cours ou la valeur existante -->
<textarea name="contenu"><?= e($_POST['contenu'] ?? $article['contenu']) ?></textarea>
</div>
<!-- Actions -->
<button class="btn primary" type="submit">Enregistrer</button>
<a class="btn" href="/admin/dashboard.php">Annuler</a>
</form>
<?php require_once __DIR__ . '/../inc/footer.php'; ?>

View File

@@ -0,0 +1,82 @@
<?php
// Charge la config, la connexion BDD et les fonctions
require_once __DIR__ . '/../inc/config.php';
require_once __DIR__ . '/../inc/db.php';
require_once __DIR__ . '/../inc/functions.php';
// Restreint l'accès au tableau de bord aux utilisateurs connectés
require_login();
// Affiche le header
require_once __DIR__ . '/../inc/header.php';
// Calcule le nombre d'articles : tous si admin, sinon seulement ceux de l'utilisateur
if (is_admin()) {
$countArticles = (int)$pdo->query("SELECT COUNT(*) FROM articles")->fetchColumn();
} else {
$stmtCount = $pdo->prepare("SELECT COUNT(*) FROM articles WHERE user_id = :uid");
$stmtCount->execute(['uid'=>current_user_id()]);
$countArticles = (int)$stmtCount->fetchColumn();
}
?>
<h2>Mon espace</h2>
<div class="notice">Bienvenue, <?= e(current_user_login()) ?> </div>
<p>Vos articles : <strong><?= $countArticles ?></strong></p>
<p>
<!-- Lien pour créer un nouvel article -->
<a class="btn primary" href="/admin/articles_create.php">Écrire un nouvel article</a>
<!-- Lien pour revenir à la partie publique du site -->
<a class="btn" href="/public/index.php">Retourner a l'accueil</a>
</p>
<table class="table">
<thead>
<tr>
<th>ID</th><th>Titre</th><th>Date</th><th>Auteur</th><th>Actions</th>
</tr>
</thead>
<tbody>
<?php
// Récupère la liste d'articles à afficher : tous si admin, sinon filtrés par user_id
if (is_admin()) {
$stmt = $pdo->query("
SELECT a.id, a.titre, a.date_creation, u.login AS auteur
FROM articles a
LEFT JOIN utilisateur u ON u.id = a.user_id
ORDER BY a.date_creation DESC
");
} else {
$stmt = $pdo->prepare("
SELECT a.id, a.titre, a.date_creation, u.login AS auteur
FROM articles a
LEFT JOIN utilisateur u ON u.id = a.user_id
WHERE a.user_id = :uid
ORDER BY a.date_creation DESC
");
$stmt->execute(['uid'=>current_user_id()]);
}
// Affiche chaque article dans une ligne du tableau (échappé pour éviter les attaques par xss)
foreach ($stmt as $row): ?>
<tr>
<td><?= (int)$row['id'] ?></td>
<td><?= e($row['titre']) ?></td>
<td><?= e(date('d/m/Y H:i', strtotime($row['date_creation']))) ?></td>
<td><?= e($row['auteur'] ?? 'Anonyme') ?></td>
<td>
<!-- Actions d'édition/suppression sur l'article courant -->
<a class="btn" href="/admin/articles_edit.php?id=<?= (int)$row['id'] ?>">Modifier</a>
<a class="btn danger" href="/admin/articles_delete.php?id=<?= (int)$row['id'] ?>">Supprimer</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php
// Footer
require_once __DIR__ . '/../inc/footer.php';
?>

View File

@@ -0,0 +1,77 @@
<?php
// Charge la config, la connexion BDD et les fonctions
require_once __DIR__ . '/../inc/config.php';
require_once __DIR__ . '/../inc/db.php';
require_once __DIR__ . '/../inc/functions.php';
$errors = []; // Contiendra les messages d'erreur à afficher
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf(); // Sécurise le formulaire contre les attaques CSRF
// Récupère et nettoie les identifiants saisis
$loginOrEmail = trim($_POST['login'] ?? '');
$password = $_POST['password'] ?? '';
// Validation des champs requis
if ($loginOrEmail === '' || $password === '') {
$errors[] = "Veuillez renseigner vos identifiants.";
} else {
// Recherche de l'utilisateur par login ou email (requête préparée sécurisée)
$stmt = $pdo->prepare("SELECT id, login, password, role FROM utilisateur WHERE login = :v OR email = :v LIMIT 1");
$stmt->execute(['v'=>$loginOrEmail]);
$user = $stmt->fetch();
// Vérifie le mot de passe
if ($user && password_verify($password, $user['password'])) {
// Sauvegarde l'état de connexion en session
$_SESSION['user_id'] = (int)$user['id'];
$_SESSION['login'] = $user['login'];
$_SESSION['role'] = $user['role'] ?: 'user';
// Redirige vers le tableau de bord une fois connecté
header('Location: /admin/dashboard.php'); exit;
} else {
// Message générique pour ne pas révéler si login/email existe
$errors[] = "Identifiants incorrects.";
}
}
}
// header
require_once __DIR__ . '/../inc/header.php';
?>
<h2>Connexion</h2>
<?php if ($errors): ?>
<div class="error">
<?php foreach ($errors as $e): ?>
<p><?= e($e) ?></p> <!-- Affiche les erreurs de manière échappée -->
<?php endforeach; ?>
</div>
<?php endif; ?>
<!-- Formulaire de connexion protégé par CSRF -->
<form method="post">
<?= csrf_input() ?> <!-- Champ caché contenant le jeton CSRF -->
<div class="form-group">
<label>Login ou Email</label>
<!-- Conserve la saisie utilisateur en cas d'erreur -->
<input type="text" name="login" value="<?= e($_POST['login'] ?? '') ?>">
</div>
<div class="form-group">
<label>Mot de passe</label>
<input type="password" name="password">
</div>
<button class="btn primary" type="submit">Se connecter</button>
<a class="btn" href="/admin/register.php">Créer un compte</a>
</form>
<?php
// footer
require_once __DIR__ . '/../inc/footer.php';
?>

View File

@@ -0,0 +1,5 @@
<?php
require_once __DIR__ . '/../inc/functions.php';
session_destroy();
header('Location: /public/index.php');
exit;

View File

@@ -0,0 +1,95 @@
<?php
// Charge la config, la connexion BDD et les fonction
require_once __DIR__ . '/../inc/config.php';
require_once __DIR__ . '/../inc/db.php';
require_once __DIR__ . '/../inc/functions.php';
$errors = []; // Collecte des messages d'erreur
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf(); // Protection CSRF du formulaire
// Récupération et on vide les champs
$login = trim($_POST['login'] ?? '');
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
$password2 = $_POST['password2'] ?? '';
// Validations de base
if ($login === '' || $email === '' || $password === '' || $password2 === '') { $errors[] = "Tous les champs sont obligatoires."; }
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $errors[] = "Email invalide."; }
if ($password !== $password2) { $errors[] = "Les mots de passe ne correspondent pas."; }
// Si valide, vérifie login/email puis crée l'utilisateur
if (!$errors) {
$stmt = $pdo->prepare("SELECT id FROM utilisateur WHERE login = :login OR email = :email LIMIT 1");
$stmt->execute(['login'=>$login,'email'=>$email]);
if ($stmt->fetch()) {
$errors[] = "Login ou email déjà pris."; // Conflit
} else {
// Hash sécurisé du mot de passe
$hash = password_hash($password, PASSWORD_DEFAULT);
// Insertion de l'utilisateur en base (rôle par défaut: user)
$ins = $pdo->prepare("INSERT INTO utilisateur (login, email, password, role, created_at) VALUES (:login, :email, :password, 'user', NOW())");
$ins->execute(['login'=>$login,'email'=>$email,'password'=>$hash]);
// Connexion automatique après inscription
$_SESSION['user_id'] = (int)$pdo->lastInsertId();
$_SESSION['login'] = $login;
$_SESSION['role'] = 'user';
// Redirection vers le tableau de bord
header('Location: /admin/dashboard.php'); exit;
}
}
}
// Header
require_once __DIR__ . '/../inc/header.php';
?>
<h2>Inscription</h2>
<!-- Affichage des erreurs éventuelles -->
<?php if ($errors): ?>
<div class="error">
<?php foreach ($errors as $e): ?>
<p><?= e($e) ?></p>
<?php endforeach; ?>
</div>
<?php endif; ?>
<!-- Formulaire d'inscription protégé par CSRF -->
<form method="post">
<?= csrf_input() ?> <!-- Jeton CSRF -->
<div class="form-group">
<label>Login</label>
<input type="text" name="login" value="<?= e($_POST['login'] ?? '') ?>">
</div>
<div class="form-group">
<label>Email</label>
<input type="email" name="email" value="<?= e($_POST['email'] ?? '') ?>">
</div>
<div class="form-group">
<label>Mot de passe</label>
<input type="password" name="password">
</div>
<div class="form-group">
<label>Confirmer le mot de passe</label>
<input type="password" name="password2">
</div>
<button class="btn primary" type="submit">Créer mon compte</button>
<a class="btn" href="/admin/login.php">J'ai déjà un compte</a>
</form>
<?php
// Footer
require_once __DIR__ . '/../inc/footer.php';
?>