Commit Graph

82 Commits

Author SHA1 Message Date
cedricAbonnel 819d6d1b8f chore : ajouter fichiers non versionnés (migrations SQL, 404, PROJET.md)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 09:18:34 +02:00
cedricAbonnel 16965ee8cb feat : DATA_PATH configurable, DataGit auto-commit, UpdateChecker branche (v1.4.0)
- DATA_PATH : chemin /data hors document root, configurable via .env
  (fallback sur BASE_PATH/data si absent)
- DataGit : auto-commit git sur toutes les écritures articles/livres
  (create, update, delete, meta, tags, fichiers, liens…) sauf autosave
- UpdateChecker : getBranch() / getLastChecked() / clearCache(),
  branche configurable via FOLIO_UPDATE_BRANCH (plus de main hardcodé)
- Admin dashboard : affiche la branche suivie, date du dernier contrôle,
  bouton Vérifier pour forcer le check sans attendre le TTL
- CLAUDE.md : architecture DATA_PATH et flux de déploiement documentés

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 09:17:55 +02:00
cedricAbonnel 55a2120be1 chore : CHANGELOG + bump version 1.3.0 (statistiques, permissions, setup.sh)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:53:33 +02:00
cedricAbonnel 8be56bc27f Merge pull request 'feat #64 : onglet Statistiques — pages, livres, répartition AS' (#65) from feat/books into main
Reviewed-on: #65
2026-05-14 22:50:47 +00:00
cedricAbonnel ce70daaa34 Merge pull request 'fix : vérification écriture settings + script setup.sh' (#63) from feat/wizard-multi-step into main
Reviewed-on: #63
2026-05-14 22:50:36 +00:00
cedricAbonnel 8cab6362a3 feat : onglet Statistiques — pages, livres, répartition AS avec groupes configurables
- AccessLogParser : parse COMBINED, agrège hits /post/ et /book/, cache 10 min
- AsnLookup : batch lookup ip-api.com, cache 30j, agrégation et groupes AS
- Onglet Statistiques dans l'admin : top pages, top livres, répartition réseau
- Filtrage par groupe AS (badges) + formulaire de configuration des groupes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:48:34 +02:00
cedricAbonnel dbd76556fb feat : notion de livre — grouper des pages en série ordonnée
Ajoute un concept de "livre" (série de pages ordonnées) avec :
- BookManager : CRUD JSON dans data/books/<slug>.json
- Route /book/<slug> → page de sommaire (table des matières)
- Navigation chapitre ← → en bas de chaque article membre du livre
- Bandeau "Chapitre X/N — Nom du livre" en haut de l'article
- Admin → onglet Livres : créer, éditer, supprimer un livre, ajouter/ordonner les pages via textarea slug

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:47:41 +02:00
cedricAbonnel 3bb83b3ffd feat : SearchLogParser accepte un pattern glob pour les logs d'accès
Balaye tous les fichiers correspondant au pattern (ex: *-access.log)
et leurs rotations .gz/.tar.gz. Valeur par défaut : *-access.log.
Label renommé en "Pattern des logs d'accès".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:35:19 +02:00
cedricAbonnel 981c9f6cb3 feat : SearchLogParser supporte tar.gz + config log dans onglet Recherches
- logFiles() utilise glob() au lieu d'un range fixe 1-14
- Support .tar.gz via PharData
- Champ apache_access_log déplacé du tab Site vers un bloc dédié
  dans le tab Recherches (action admin_save_searches_config)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:26:16 +02:00
cedricAbonnel d18f9abd16 feat : log Apache configurable via Administration → Site (apache_access_log)
Ajoute apacheAccessLog() dans SiteSettings — priorité au réglage admin,
fallback sur APACHE_ACCESS_LOG dans .env. Champ ajouté dans le formulaire
Site de l'administration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:16:49 +02:00
cedricAbonnel d488bcd00c fix : setup.sh — rappel redémarrage PHP-FPM en plus d'Apache pour groupe adm
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:12:31 +02:00
cedricAbonnel 157c30f20c feat : setup.sh — ajout de www-data au groupe adm pour les logs Apache
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:11:51 +02:00
cedricAbonnel fd2397ff90 feat : script setup.sh pour le déploiement initial de Folio
Crée les dossiers requis, applique setgid sur data/ et _cache/ pour
que les fichiers héritent du groupe web (www-data) quelle que soit
leur origine (PHP ou rsync), installe les dépendances et lance les
migrations SQL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:10:30 +02:00
cedricAbonnel 9091a00a32 fix : saveSiteSettings et saveSmtpSettings retournent bool, erreur affichée
file_put_contents() échouait silencieusement (permissions), provoquant
un saved=1 trompeur. Les deux fonctions retournent maintenant bool ;
les callers redirigent vers ?error=write et le template affiche un
message d'erreur explicite.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:02:54 +02:00
cedricAbonnel 370e1a9062 Merge pull request 'fix #61 : afficher les résultats de recherche au lieu de rediriger vers le 1er' (#62) from feat/wizard-multi-step into main
Reviewed-on: #62
2026-05-14 21:47:29 +00:00
cedricAbonnel d6b75d44e3 chore : version 1.2.2 + CHANGELOG (#61)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 23:47:04 +02:00
cedricAbonnel dbb4684d7c chore : version 1.3.0 + CHANGELOG (#61)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 23:46:32 +02:00
cedricAbonnel edb5f03956 fix #61 : afficher les résultats de recherche au lieu de rediriger vers le 1er
Remplace la redirection 301 vers le premier résultat par une redirection
302 vers /search?q=... pour laisser l'utilisateur choisir parmi les
résultats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 23:45:24 +02:00
cedricAbonnel 99a7f2e790 Merge pull request 'feat : wizard multi-étapes, migrations contenu, versionnage semver (v1.2.1)' (#60) from feat/wizard-multi-step into main
Reviewed-on: #60
2026-05-14 21:17:19 +00:00
cedricAbonnel 72cb7acae4 fix 1.2.1 : cache index.md, H1 rendu, scroll wizard, titre Modifier
- ArticleManager : invalider le cache si index.md est plus récent que meta.json
- migration_001 : touch(meta.json) après maj index.md pour forcer l'invalidation
- post_view.php : masquer le H1 initial du contenu (déjà affiché par le template)
- step1.php : en-tête "Modifier" sans le titre de l'article
- wizard.js : retirer scrollToCursor (erroné sur auto-resize) ; Ctrl+Home/End via scrollIntoView

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 23:07:15 +02:00
cedricAbonnel 1dbe6d8dd3 feat : versionnage semver, migrations contenu, bandeau mise à jour admin
- CHANGELOG.md : structure semver (1.0.0 / 1.1.0 / 1.2.0) remplace le journal non versionné
- public/version.txt : généré à chaque push depuis la première entrée CHANGELOG
- scripts/push.sh : extrait la version CHANGELOG avant git add
- src/UpdateChecker.php : compare version déployée vs version Gitea (raw file), cache 1 h
- templates/layout.php : bandeau alerte admin (nouvelle version / migrations en attente)
- templates/admin.php : dashboard moteur Folio (version déployée / disponible)
- scripts/migrate_content.php + migration_001 : ajout # titre dans les articles existants
- templates/maintenance.php : page HTTP 503 pendant une migration
- src/helpers.php : extractMarkdownTitle(), normalisation \r\n dans lineDiff()
- templates/wizard/step1.php : suppression champ titre, plan TOC dynamique
- public/assets/js/wizard.js : scope titleEl, scrollToCursor, buildToc, handlers externalisés

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 22:45:35 +02:00
cedricAbonnel 6200444e6d Merge pull request 'feat #58 : wizard multi-étapes création/édition article' (#59) from feat/wizard-multi-step into main
Reviewed-on: #59
2026-05-14 19:50:33 +00:00
cedricAbonnel c503f1dd66 style : formatage PHP-CS-Fixer sur le wizard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 21:48:33 +02:00
cedricAbonnel 6895a3bf65 feat #58 : wizard multi-étapes création/édition d'article
Remplace le formulaire unique par un wizard 5 étapes (création) et
6 étapes (édition) avec auto-sauvegarde en brouillon, détection de
tags depuis le texte (TagSuggester), aperçu SEO, diff avant validation
et plan Markdown dynamique dans l'éditeur.

Détail des changements :
- ArticleManager : +6 méthodes (updatePartialMeta, saveDraftOverlay,
  getDraftOverlay, hasDraftOverlay, discardDraftOverlay, commitDraftOverlay)
- .htaccess : routes /new/{uuid}/{1-5} et /edit/{uuid}/{1-6}
- index.php : cases create et edit réécrits en switch($step),
  nouveau case autosave_draft et edit_discard_draft
- assets/js/wizard.js : autosave debounce, auto-resize textarea,
  scroll curseur, plan TOC dynamique, toggle pills tags
- templates/wizard/ : nav.php + step1..6.php

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 21:46:11 +02:00
cedricAbonnel 24bb244352 perf : session lazy + CSRF cookie + 410 DokuWiki
Contexte : sur abonnel.fr, session_start() était appelé sur chaque
requête PHP (y compris bots), créant ~17 000 fichiers de session/jour
dans un répertoire custom non nettoyé par le cron Debian. Les workers
PHP-FPM grossissaient en mémoire et le pool saturait (1 188 erreurs
503 en 30 minutes).

Changements :

public/index.php
- session_start() uniquement si le cookie de session existe déjà ou si
  la requête est POST. Les bots (GET sans cookie) ne créent plus de
  session.
- CSRF commentaires migré de $_SESSION['comment_csrf'] vers un double-
  submit cookie (_csrf_c, SameSite=Strict, HttpOnly). La session n'est
  plus requise pour les visiteurs anonymes qui postent un commentaire.

templates/comments_section.php
- Génère le token CSRF et le pose en cookie (_csrf_c) au lieu de
  l'écrire en session.

public/.htaccess
- Règle Apache 410 Gone pour toute URL contenant un paramètre ?do=
  (anciens paramètres DokuWiki : do=media, do=export_pdf…). Traité par
  Apache en 2ms sans toucher PHP-FPM.

public/oidc/{start,callback,me}.php
- Correction du bug introduit par 0b8077e : config.php (qui utilise
  BASE_PATH) était chargé avant bootstrap.php (qui définit BASE_PATH).
  Fix : define('BASE_PATH', …) ajouté avant le require config.php.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 13:06:54 +02:00
cedricAbonnel f92e9425ed docs : config PHP-FPM recommandée et protection bots DokuWiki
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:16:02 +02:00
cedricAbonnel 0b8077e43c fix : orphelins search_index + SESSION_NAME non appliqué
- ArticleManager::getSearchIndex() : rebuild automatique si un UUID
  référencé dans search_index.json n'existe plus sur le disque (article
  supprimé hors CMS via rsync ou suppression manuelle). Même logique que
  getBySlug() qui nettoie déjà le slug_index à la volée.

- bootstrap.php : lire SESSION_NAME depuis $_ENV avant session_start(),
  permettant de personnaliser le nom du cookie de session via le .env.

- oidc/{start,callback,me}.php : inverser l'ordre des require pour charger
  config.php (dotenv) avant bootstrap.php, condition nécessaire pour que
  SESSION_NAME soit disponible au démarrage de la session.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:06:11 +02:00
cedricAbonnel 5828aac4f5 docs: ajouter README avec guide d'installation
Couvre prérequis, installation pas-à-pas (clone, .env, BDD, migrations,
vhost Apache/Nginx, permissions), paramètres du site, mise à jour et
structure du projet. Fixes #55.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:58:05 +02:00
cedricAbonnel 03120457a7 clean : retirer les articles de production de folio, garder data/site/
data/ ne doit pas contenir de données de site (articles, config, cache).
Seuls data/.gitkeep et data/site/ (exemples pour installation fraîche)
sont conservés. Le .gitignore est mis à jour en conséquence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:26:33 +02:00
cedricAbonnel 23acc1621f fix #54 : corriger autoloader PSR-4 — app/ → src/
L'autoloader mappait App\ vers app/ (inexistant).
Tous les namespaces App\ échouaient silencieusement sauf
quand les classes étaient chargées via require_once direct.
Première erreur visible : App\Http\Csrf introuvable → 500 sur /login/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 09:20:29 +02:00
cedricAbonnel 2c8e31baff deploy: documenter le workflow d'installation fraîche
- Ajoute .env.example avec toutes les variables requises (DB_DSN, OIDC_*,
  SMTP_*, SESSION_NAME, ADMIN_EMAIL…) — DB_DSN était absent et cassait
  database/migrate.php au premier déploiement.
- Clarifie migrate-init.php : réservé aux serveurs existants antérieurs au
  système de migrations ; pour une installation fraîche, migrate.php suffit
  (applique tout depuis migration_000).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 08:47:29 +02:00
Cedric Abonnel 8a85c15372 fix #29 : envoyer le lien magique par email (envoyer_mail_smtp) 2026-05-13 23:41:58 +02:00