ajout projet cms elyes
This commit is contained in:
76
cms_simplifie/admin/articles_create.php
Normal file
76
cms_simplifie/admin/articles_create.php
Normal 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';
|
||||
?>
|
||||
60
cms_simplifie/admin/articles_delete.php
Normal file
60
cms_simplifie/admin/articles_delete.php
Normal 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'; ?>
|
||||
82
cms_simplifie/admin/articles_edit.php
Normal file
82
cms_simplifie/admin/articles_edit.php
Normal 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'; ?>
|
||||
82
cms_simplifie/admin/dashboard.php
Normal file
82
cms_simplifie/admin/dashboard.php
Normal 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';
|
||||
?>
|
||||
77
cms_simplifie/admin/login.php
Normal file
77
cms_simplifie/admin/login.php
Normal 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';
|
||||
?>
|
||||
5
cms_simplifie/admin/logout.php
Normal file
5
cms_simplifie/admin/logout.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../inc/functions.php';
|
||||
session_destroy();
|
||||
header('Location: /public/index.php');
|
||||
exit;
|
||||
95
cms_simplifie/admin/register.php
Normal file
95
cms_simplifie/admin/register.php
Normal 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';
|
||||
?>
|
||||
Reference in New Issue
Block a user