From 9e0c151fa60a31f0bb6d2d956eb7472832124474 Mon Sep 17 00:00:00 2001 From: Safouane Bazzi Date: Tue, 21 Oct 2025 21:34:20 +0200 Subject: [PATCH] =?UTF-8?q?Initial=20commit=20:=20CMS=20Simplifi=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 5 ++ .gitignore | 6 ++ README.md | 101 ++++++++++++++++++++++++++++++++++ admin/dashboard.php | 0 admin/login.php | 0 admin/logout.php | 0 inc/auth.php | 0 inc/db.php | 30 ++++++++++ public/add.php | 55 +++++++++++++++++++ public/admin.php | 54 ++++++++++++++++++ public/article.php | 40 ++++++++++++++ public/assets/style.css | 119 ++++++++++++++++++++++++++++++++++++++++ public/delete.php | 46 ++++++++++++++++ public/edit.php | 61 ++++++++++++++++++++ public/index.php | 48 ++++++++++++++++ public/login.php | 52 ++++++++++++++++++ public/logout.php | 5 ++ 17 files changed, 622 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 README.md create mode 100644 admin/dashboard.php create mode 100644 admin/login.php create mode 100644 admin/logout.php create mode 100644 inc/auth.php create mode 100644 inc/db.php create mode 100644 public/add.php create mode 100644 public/admin.php create mode 100644 public/article.php create mode 100644 public/assets/style.css create mode 100644 public/delete.php create mode 100644 public/edit.php create mode 100644 public/index.php create mode 100644 public/login.php create mode 100644 public/logout.php diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..8d5c26c --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +DB_HOST=127.0.0.1 +DB_NAME=cms_simplifie +DB_USER=root +DB_PASS=CHANGE_ME +APP_SECRET=CHANGE_ME_TOO \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6c4bc15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# Fichiers secrets qu'on NE VEUT PAS envoyer sur Gitea +.env +inc/config.local.php +# --- secrets --- +.env +inc/config.local.php diff --git a/README.md b/README.md new file mode 100644 index 0000000..cac3ebf --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +# Mini-Projet de Développement Web – CMS Simplifié + +## Présentation du projet +Ce mini-projet a été réalisé dans le cadre du module **Développement Web** (BTS CIEL – 2ᵉ année). + +L’objectif était de créer un **mini CMS** (Content Management System) simplifié permettant : +- la **connexion sécurisée** d’un administrateur ; +- la **création**, **modification** et **suppression** d’articles (CRUD) ; +- l’affichage des données stockées en base **MySQL**. + +Le projet est réalisé **sans framework**, uniquement avec les langages vus en cours : +**HTML, CSS, Bootstrap, PHP (PDO), et SQL**. + +--- + +## Technologies utilisées +| Technologie | Utilisation | +|--------------|--------------| +| **HTML5** | Structure des pages | +| **CSS3 / Bootstrap 5** | Mise en forme et design responsive (thème noir & or) | +| **PHP (Sessions, PDO)** | Connexion, sécurité et interaction avec MySQL | +| **MySQL** | Base de données pour les utilisateurs et articles | +| **Docker** | Conteneurs PHP/Apache et MySQL | +| **Git / Gitea** | Gestion de version et hébergement du projet | + +--- + +## Structure du projet + +cms-simplifie/ +│ +├── public/ +│ ├── assets/ +│ │ └── style.css → Design global (thème noir & or) +│ ├── add.php → Page d’ajout d’un article +│ ├── edit.php → Page de modification d’un article +│ ├── delete.php → Page de suppression d’un article +│ ├── admin.php → Tableau de bord (gestion des articles) +│ ├── login.php → Page de connexion administrateur +│ ├── logout.php → Déconnexion +│ ├── article.php → Lecture d’un article +│ └── index.php → Accueil (affichage des articles) +│ +├── inc/ +│ └── db.php → Connexion PDO sécurisée à MySQL +│ +├── scripts/ → (optionnel, outils ou scripts SQL) +│ +├── .env.example → Exemple de configuration (sans mot de passe) +├── .gitignore → Exclut .env et fichiers sensibles +├── stack.bibli.yaml / Dockerfile → Configuration Docker +└── README.md → Ce fichier + + +--- + +## Fonctionnalités principales +- Connexion d’un utilisateur (admin) avec vérification du mot de passe haché. +- Gestion complète des articles (**CRUD**) : créer, lire, modifier, supprimer. +- Interface d’administration simple et claire. +- Design **noir & or** pour une ambiance moderne et élégante. +- Sécurisation via **sessions PHP** et **requêtes préparées PDO**. +- Aucune donnée sensible visible dans le code source. + +--- + +## Sécurité +- Les identifiants MySQL sont stockés dans **`.env`**, jamais dans le code. +- Le fichier `.gitignore` empêche toute fuite de `.env`. +- Les mots de passe sont **hachés** avec `password_hash()` et vérifiés avec `password_verify()`. +- Connexion à la base via **PDO** pour éviter les injections SQL. + +--- + +## Lancer le projet en local + +### Étapes : + +1️⃣ Démarrer les conteneurs Docker : + +docker stack deploy -c stack.bibli.yaml cms + + +2️⃣ Copier le fichier .env.example pour créer ton .env personnel : + +cp .env.example .env + + +3️⃣ Modifier le fichier .env pour y mettre tes identifiants MySQL : + +DB_HOST=mysql +DB_NAME=cms_simplifie +DB_USER=root +DB_PASS=tonmotdepasse + + +4️⃣ Accéder au site localement : +👉 http://localhost:8000 + +5️⃣ Tester la connexion à la base : +👉 http://localhost:8000/test-db.php \ No newline at end of file diff --git a/admin/dashboard.php b/admin/dashboard.php new file mode 100644 index 0000000..e69de29 diff --git a/admin/login.php b/admin/login.php new file mode 100644 index 0000000..e69de29 diff --git a/admin/logout.php b/admin/logout.php new file mode 100644 index 0000000..e69de29 diff --git a/inc/auth.php b/inc/auth.php new file mode 100644 index 0000000..e69de29 diff --git a/inc/db.php b/inc/db.php new file mode 100644 index 0000000..24e4450 --- /dev/null +++ b/inc/db.php @@ -0,0 +1,30 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, +]; + +try { + $pdo = new PDO( + "mysql:host=$DB_HOST;dbname=$DB_NAME;charset=$DB_CHARSET", + $DB_USER, + $DB_PASS, + $options + ); +} catch (PDOException $e) { + error_log('Erreur connexion DB : ' . $e->getMessage()); + http_response_code(500); + exit('Erreur de connexion à la base de données.'); +} \ No newline at end of file diff --git a/public/add.php b/public/add.php new file mode 100644 index 0000000..5f1f99e --- /dev/null +++ b/public/add.php @@ -0,0 +1,55 @@ +prepare("INSERT INTO articles(titre,contenu) VALUES(?,?)"); + $stmt->execute([$titre,$contenu]); + header('Location: admin.php'); exit; + } else { $error = 'Champs obligatoires.'; } +} +?> + + + + + +Ajouter un article + + + + + + +
+
+

Ajouter un article

+
+
+
+ + +
+
+ + +
+
+ + Annuler +
+
+
+
+ + \ No newline at end of file diff --git a/public/admin.php b/public/admin.php new file mode 100644 index 0000000..70394b7 --- /dev/null +++ b/public/admin.php @@ -0,0 +1,54 @@ +query("SELECT * FROM articles ORDER BY date_creation DESC"); +$articles = $stmt->fetchAll(); +?> + + + + + +Administration + + + + + + + +
+
+

Articles

+ Ajouter +
+ + +
Aucun article.
+ +
+ +
+
+
+ +
+ +
+ +
+ +
+ + + \ No newline at end of file diff --git a/public/article.php b/public/article.php new file mode 100644 index 0000000..bd2263c --- /dev/null +++ b/public/article.php @@ -0,0 +1,40 @@ +prepare("SELECT id,titre,contenu,date_creation FROM articles WHERE id=?"); +$stmt->execute([$id]); +$article=$stmt->fetch(); +if(!$article){http_response_code(404);exit('404 - Article non trouvé');} +?> + + + + + +<?= htmlspecialchars($article['titre']) ?> + + + + + + +
+
+
+

+ +
+
+
+ +
+ + \ No newline at end of file diff --git a/public/assets/style.css b/public/assets/style.css new file mode 100644 index 0000000..e5513a1 --- /dev/null +++ b/public/assets/style.css @@ -0,0 +1,119 @@ +:root{ + --bg-dark:#121212; + --bg-card:#1e1e1e; + --text-light:#f5f5f5; + --text-muted:#b3b3b3; + --accent:#d4af37; +} + +body{ + background:var(--bg-dark); + color:var(--text-light); + font-family:'Inter',sans-serif; +} + +.container-narrow{max-width:860px} + +.navbar{ + background:linear-gradient(90deg,#1a1a1a,#333); + box-shadow:0 2px 15px rgba(0,0,0,.6); +} +.navbar .navbar-brand{ + color:var(--accent)!important; + font-weight:600; + letter-spacing:.5px; +} +.navbar .navbar-text{ + color:var(--text-light)!important; +} +.navbar a.btn-outline-accent{ + border-color:var(--accent)!important; + color:var(--accent)!important; +} +.navbar a.btn-outline-accent:hover{ + background:var(--accent); + color:#000!important; +} + +h1,h2,h3,h4,h5{color:var(--text-light);margin:0 0 .6rem} +.item-title{color:var(--text-light)} +.text-muted{color:var(--text-muted)!important} + +.card{ + background:var(--bg-card); + border:1px solid #2d2d2d; + box-shadow:0 8px 25px rgba(0,0,0,.5); + color:var(--text-light); + border-radius:10px; +} + +.btn-accent{ + background:var(--accent); + color:#000; + border:0; + font-weight:600; + transition:.25s; +} +.btn-accent:hover{ + background:#b8952d; + color:#000; +} + +.btn-outline-accent{ + background:transparent; + border:1px solid var(--accent); + color:var(--accent); + font-weight:600; + transition:.25s; +} +.btn-outline-accent:hover{ + background:var(--accent); + color:#000; +} + +.btn-danger{ + background:#b51c1c; + border:none; + color:#fff; + font-weight:600; + transition:.25s; +} +.btn-danger:hover{ + background:#d62828; + color:#fff; +} + +.form-control,textarea{ + background:#2a2a2a; + border:1px solid #444; + color:var(--text-light); +} +.form-control:focus,textarea:focus{ + border-color:var(--accent); + box-shadow:0 0 0 .15rem rgba(212,175,55,.25); + background:#2f2f2f; + color:#fff; +} + +.alert{ + background:#2d2d2d; + color:#ccc; + border:none; +} +.list-group-item{ + background:#1c1c1c; + border:1px solid #333; +} +.list-group-item .text-muted{ + color:var(--text-muted)!important; +} + +a{ + color:var(--accent); + text-decoration:none; + font-weight:500; +} +a:hover{ + text-decoration:underline; + color:#f1c94e; +} \ No newline at end of file diff --git a/public/delete.php b/public/delete.php new file mode 100644 index 0000000..dacc0d8 --- /dev/null +++ b/public/delete.php @@ -0,0 +1,46 @@ +prepare("SELECT id,titre FROM articles WHERE id=?"); +$stmt->execute([$id]); +$article = $stmt->fetch(); +if(!$article){ http_response_code(404); exit('404'); } +if($_SERVER['REQUEST_METHOD']==='POST'){ + $del = $pdo->prepare("DELETE FROM articles WHERE id=?"); + $del->execute([$id]); + header('Location: admin.php'); exit; +} +?> + + + + + +Supprimer un article + + + + + + +
+
+

Confirmation

+
Supprimer « » ?
+
+ + Annuler +
+
+
+ + \ No newline at end of file diff --git a/public/edit.php b/public/edit.php new file mode 100644 index 0000000..5179cec --- /dev/null +++ b/public/edit.php @@ -0,0 +1,61 @@ +prepare("SELECT id,titre,contenu FROM articles WHERE id=?"); +$stmt->execute([$id]); +$article = $stmt->fetch(); +if(!$article){ http_response_code(404); exit('404'); } +$error = null; +if($_SERVER['REQUEST_METHOD']==='POST'){ + $titre = trim($_POST['titre'] ?? ''); + $contenu = trim($_POST['contenu'] ?? ''); + if($titre!=='' && $contenu!==''){ + $upd = $pdo->prepare("UPDATE articles SET titre=?,contenu=? WHERE id=?"); + $upd->execute([$titre,$contenu,$id]); + header('Location: admin.php'); exit; + } else { $error = 'Champs obligatoires.'; } +} +?> + + + + + +Modifier un article + + + + + + +
+
+

Modifier l’article

+
+
+
+ + +
+
+ + +
+
+ + Annuler +
+
+
+
+ + \ No newline at end of file diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..665eff2 --- /dev/null +++ b/public/index.php @@ -0,0 +1,48 @@ +prepare("SELECT id,titre,SUBSTRING(contenu,1,180) AS intro,date_creation FROM articles ORDER BY date_creation DESC LIMIT 10"); +$stmt->execute(); +$articles=$stmt->fetchAll(); +?> + + + + + +Accueil + + + + + + +
+

Derniers articles

+ +
Aucun article pour le moment.
+ +
+ +
+
+
+
+ +
+

...

+ Lire +
+
+ +
+ +
+ + \ No newline at end of file diff --git a/public/login.php b/public/login.php new file mode 100644 index 0000000..6f656f6 --- /dev/null +++ b/public/login.php @@ -0,0 +1,52 @@ +prepare("SELECT * FROM utilisateur WHERE login=?"); + $stmt->execute([$login]); + $user=$stmt->fetch(); + if($user && password_verify($password,$user['password'])){ + $_SESSION['user_id']=$user['id']; + $_SESSION['user_login']=$user['login']; + header('Location: admin.php'); exit; + } else { $error='Identifiants incorrects.'; } +} +?> + + + + + +Connexion + + + + + + +
+
+

Connexion

+
+
+
+ + +
+
+ + +
+ +
+
+
+ + \ No newline at end of file diff --git a/public/logout.php b/public/logout.php new file mode 100644 index 0000000..ee222ca --- /dev/null +++ b/public/logout.php @@ -0,0 +1,5 @@ +