#53 résumé req/IPs par statut dans Erreurs 404 #54 titre onglet avec compteur non résolus #2 Tout/Aucun dans resize (tailles + formats) #7 backup filename affiché dans résultats resize #8 flash message résumé après upload #6 renommage inline sur preview_text + preview_other #23 filtre + tri par nom/taille/date dans corbeille #20 sélection multiple + batch restore/delete corbeille #45 /sitemap.xml (assets publics) #52 ignoreip fail2ban sync sur Ignorer/Retirer une IP #1 cairosvg>=2.7 dans requirements.txt #51 ignored_ips.json exclu du rsync --delete #48 as_cache/ exclu du rsync --delete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
207 lines
10 KiB
Markdown
207 lines
10 KiB
Markdown
# Changelog — Alpinux Static
|
||
|
||
## [2.0.0] — 2026-05-06
|
||
|
||
### Ajouté
|
||
- **Erreurs 404 (#53)** : barre de résumé rouge/verte affichant le total requêtes·IPs ventilé entre erreurs actives et résolues (calculé après vérification batch)
|
||
- **Erreurs 404 (#54)** : titre de l'onglet navigateur mis à jour avec le nombre d'erreurs non résolues (`Erreurs 404 (12) — Static Alpinux`)
|
||
- **Resize (#2)** : boutons « Tout / Aucun » pour les groupes Tailles et Formats
|
||
- **Resize (#7)** : nom du fichier backup affiché dans les résultats de génération
|
||
- **Upload (#8)** : message de résumé après upload (X envoyé(s), Y sauvegardé(s), Z ignoré(s)…)
|
||
- **Renommage (#6)** : bouton ✏️ disponible sur les pages `preview_text` et `preview_other` (idem `preview_image`)
|
||
- **Corbeille (#23)** : filtre texte + tri par nom / taille / date
|
||
- **Corbeille (#20)** : sélection multiple — cases à cocher, « Tout sélectionner », restaurer/supprimer en lot
|
||
- **Sitemap (#45)** : route `/sitemap.xml` listant les assets publics (logo/, wiki/, error/)
|
||
- **Ignorer IP (#52)** : « Ignorer cette IP » ajoute/retire automatiquement l'IP dans `fail2ban ignoreip global-blacklist`
|
||
- **SVG (#1)** : `cairosvg>=2.7` ajouté à `requirements.txt` (`libcairo2` disponible sur le serveur)
|
||
|
||
### Corrigé
|
||
- **Déploiement (#51)** : `ignored_ips.json` exclu du rsync `--delete` — les IPs ignorées ne sont plus effacées au déploiement
|
||
- **Déploiement (#48)** : `as_cache/` exclu du rsync `--delete` — le cache RIPE local est préservé entre déploiements
|
||
|
||
---
|
||
|
||
## [1.10.0] — 2026-05-06
|
||
|
||
### Modifié
|
||
- Erreurs 404 : les pastilles de statut (●) rouges sont désormais **vérifiées automatiquement** au chargement de la page — elles passent en vert si le fichier existe maintenant, sans nécessiter un clic
|
||
- Nouveau endpoint `POST /errors/status-batch` : vérifie jusqu'à 200 chemins en une seule requête (simple `os.path.exists` côté serveur)
|
||
|
||
---
|
||
|
||
## [1.9.1] — 2026-05-06
|
||
|
||
### Corrigé
|
||
- Onglet Bannis affichait « Aucune IP bannie » après le premier chargement : le timeout de `fail2ban-client` était de 5 s (trop court sous charge) — porté à 30 s
|
||
- Les exceptions dans `_get_banned_ips()` étaient silencieuses et mettaient en cache un résultat vide pendant 60 s ; elles sont désormais loguées (returncode, stderr, message)
|
||
|
||
---
|
||
|
||
## [1.9.0] — 2026-05-06
|
||
|
||
### Ajouté
|
||
- Onglet Bannis : blocs AS **repliables par défaut** (▶/▼), bouton « Tout déplier / Tout replier »
|
||
- La recherche dynamique déplie automatiquement les blocs contenant un résultat
|
||
- Résolution ASN en **triple fallback** : ip-api.com → ipinfo.io → **Team Cymru whois** (TCP port 43, fonctionne même si HTTPS sortant bloqué)
|
||
|
||
### Corrigé
|
||
- Onglet Bannis **trop lent / Internal Server Error** : les lookups ASN se faisaient de façon synchrone au chargement de la page pour chaque CIDR banni
|
||
- Le tab est désormais chargé en **AJAX** (lazy, à la première activation seulement)
|
||
- Nouveau endpoint `GET /errors/banned-groups` : un seul `SELECT ANY()` PostgreSQL au lieu de N requêtes individuelles
|
||
- Les entrées avec `asn` vide ne sont plus utilisées depuis le cache (`AND asn != ''`) — elles sont automatiquement re-tentées avec le fallback
|
||
- Résolution des « AS inconnu » : les CIDRs bannis via « Ban AS » sont résolus depuis `as_cache/*.json` (index local RIPE, zéro appel API) puis nom/pays récupérés en 1 requête PostgreSQL `DISTINCT ON (asn)`
|
||
- **17 172 entrées ASN** résolues en base via batch Team Cymru (les CIDRs précédemment bannis sans lookup individuel)
|
||
|
||
---
|
||
|
||
## [1.8.0] — 2026-05-06
|
||
|
||
### Modifié
|
||
- Fusion des pages **Erreurs 404** et **Bannis** en une seule page avec deux onglets (URL `/errors/`)
|
||
- L'onglet actif est mémorisé dans le hash d'URL (`#errors` / `#banned`)
|
||
- Suppression du lien « Bannis » dans la navigation (accessible via l'onglet de la page Erreurs)
|
||
- Route `/errors/banned/` redirige vers `/errors/#banned`
|
||
|
||
---
|
||
|
||
## [1.7.0] — 2026-05-06
|
||
|
||
### Ajouté
|
||
- Page **Bannis** (`/errors/banned/`) : liste tous les bannissements fail2ban (`global-blacklist`) groupés par AS, avec nom de l'opérateur et pays
|
||
- Débloquer une IP/CIDR individuelle ou tout un AS d'un seul clic
|
||
- Filtre de recherche dynamique par IP, CIDR ou nom d'AS
|
||
- Mise à jour en temps réel des lignes après déblocage (pas de rechargement)
|
||
- Sudoers `static-cdn` : ajout de la permission `unbanip`
|
||
|
||
---
|
||
|
||
## [1.6.1] — 2026-05-06
|
||
|
||
### Modifié
|
||
- Cache IP→ASN migré de la mémoire process vers **PostgreSQL** (`ip_asn_cache`) — TTL 30 jours, partagé entre tous les workers gunicorn, pas de lock SQLite
|
||
- Pool de connexions `ThreadedConnectionPool` (1–3 conns par worker), schéma créé automatiquement au premier démarrage
|
||
- Graceful degradation : si `DATABASE_URL` absent ou PostgreSQL indisponible, l'app appelle ip-api.com sans cache
|
||
|
||
---
|
||
|
||
## [1.6.0] — 2026-05-06
|
||
|
||
### Ajouté
|
||
- Erreurs 404 : clic sur 🔨 affiche l'AS de l'IP (via ip-api.com) avec le nom, le pays et le nombre de préfixes IPv4
|
||
- Bannir l'IP seule **ou** bannir tout l'AS d'un coup (tous ses préfixes CIDR via RIPE Stat, cache 30 jours)
|
||
- Erreurs 404 : les IPs déjà bannies dans fail2ban (`global-blacklist`) sont masquées de la liste et du détail
|
||
|
||
### Modifié
|
||
- fail2ban `ignoreip` : ton IP publique (`82.65.88.34`) protégée sur toutes les jails
|
||
- Sudoers `static-cdn` : ajout de la permission `fail2ban-client status global-blacklist`
|
||
|
||
---
|
||
|
||
## [1.5.2] — 2026-05-06
|
||
|
||
### Ajouté
|
||
- Erreurs 404 : champ de recherche dynamique — filtre les lignes par chemin ou adresse IP à chaque frappe, avec compteur de résultats
|
||
|
||
---
|
||
|
||
## [1.5.1] — 2026-05-06
|
||
|
||
### Corrigé
|
||
- Ignorer une IP : `/opt/static-cdn/` appartenait à `abonnelc` alors que le service tourne sous `static-cdn` — écriture de `ignored_ips.json` silencieusement impossible ; corrigé par `chown -R static-cdn` + script de déploiement mis à jour
|
||
- Ignorer une IP : invalidation du cache multi-worker gunicorn basée sur le `mtime` de `ignored_ips.json` (chaque worker re-parse dès que le fichier change)
|
||
- Bannir une IP : règle sudoers créée pour `static-cdn` (compte de service réel, pas `abonnelc`) avec chemins absolus `/usr/bin/sudo` et `/usr/bin/fail2ban-client`
|
||
|
||
---
|
||
|
||
## [1.5.0] — 2026-05-06
|
||
|
||
### Ajouté
|
||
- Onglet **Erreurs** dans la navigation : analyse des logs Apache des 7 derniers jours (fichiers `.gz` inclus)
|
||
- Tableau des erreurs 404 trié par fréquence, avec badge statut coloré (✗ actif / ✓ résolu) cliquable
|
||
- Détail par chemin (AJAX) : liste des IPs avec compteur, dernière date, referers
|
||
- Ignorer une IP (devs, tests, IPs internes) — persisté dans `ignored_ips.json`, cache invalidé
|
||
- Bannir une IP directement depuis l'interface via `fail2ban-client set global-blacklist banip`
|
||
- Section des IPs ignorées avec suppression individuelle
|
||
|
||
---
|
||
|
||
## [1.4.2] — 2026-05-06
|
||
|
||
### Corrigé
|
||
- Statistiques : la page affichait une erreur de génération alors qu'ISPConfig génère déjà le rapport GoAccess chaque nuit — `STATS_FILE` pointe maintenant directement sur le fichier ISPConfig
|
||
|
||
---
|
||
|
||
## [1.4.1] — 2026-05-06
|
||
|
||
### Corrigé
|
||
- Changelog : `TypeError` au rendu — clé `items` du dict en conflit avec la méthode Python `dict.items()` en Jinja2 (renommée `entries`)
|
||
- Sélecteur de largeur : boutons L et ∞ sans effet — `max-width:none` + `margin:auto` sur flex child rétrécissait `<main>` ; remplacé par `data-cw` sur `<html>` + sélecteurs CSS d'attribut
|
||
|
||
---
|
||
|
||
## [1.4.0] — 2026-05-06
|
||
|
||
### Ajouté
|
||
- Sélecteur de largeur du contenu dans le header : Étroit (900 px), Normal (1 200 px), Large (1 600 px), Plein — préférence mémorisée dans le navigateur
|
||
- Changelog avec numéro de version sémantique, accessible depuis le footer
|
||
|
||
### Corrigé
|
||
- Décalage de largeur entre les pages dû à l'apparition/disparition de la scrollbar (`scrollbar-gutter: stable`)
|
||
- Labels EXIF non traduits : `ResolutionUnit`, `XResolution`, `YResolution`
|
||
- Valeur numérique brute pour `ColorSpace` → libellé lisible (sRGB, Adobe RGB, Non calibré)
|
||
|
||
### Modifié
|
||
- Contenu principal en pleine largeur (suppression du `max-width` fixe sur `<main>`)
|
||
|
||
---
|
||
|
||
## [1.3.0] — 2026-05-06
|
||
|
||
### Ajouté
|
||
- Prévisualisation des fichiers depuis la corbeille (propriétés, métadonnées, téléchargement)
|
||
- Footer sur toutes les pages avec liens de navigation et numéro de version
|
||
- Stats corbeille dans le tableau de bord (nombre de fichiers, taille totale, date du plus ancien)
|
||
|
||
### Modifié
|
||
- Header compact : avatar initiale + prénom + icône déconnexion (suppression du bouton texte)
|
||
- Suppression du lien « Tableau de bord » dans la navigation (doublon avec le logo)
|
||
- `user`, `humansize`, `trash_count` centralisés dans le context processor Flask (disponibles sur toutes les pages)
|
||
|
||
---
|
||
|
||
## [1.2.0] — 2026-05-06
|
||
|
||
### Ajouté
|
||
- Corbeille : mise à la corbeille depuis `/browse`, restauration avec gestion des conflits (écraser / renommer), suppression définitive
|
||
- Purge automatique des éléments en corbeille depuis plus de 30 jours
|
||
- Badge dans la navigation indiquant le nombre d'éléments en corbeille
|
||
- Page `/trash` avec tableau partagé (mode `browse` / `trash`) et bouton « Vider la corbeille »
|
||
|
||
---
|
||
|
||
## [1.1.0] — 2026-05-06
|
||
|
||
### Ajouté
|
||
- Redimensionnement d'images depuis la prévisualisation : tailles prédéfinies, dimension libre, formats PNG/JPG/ICO
|
||
- Gestion des conflits lors du redimensionnement (backup, écraser, renommer, ignorer)
|
||
- Renommage de fichiers inline dans `/browse` et la page de prévisualisation
|
||
- Affichage des métadonnées image (dimensions, format, mode couleur, DPI, EXIF)
|
||
- Dimension libre avec contrainte de proportions (mode « carré »)
|
||
|
||
### Corrigé
|
||
- Échec du redimensionnement sur les fichiers ICO en mode palette (conversion RGBA avant LANCZOS)
|
||
- Aucune sélection de taille ou format → copie à l'identique (comportement par défaut)
|
||
|
||
---
|
||
|
||
## [1.0.0] — 2026-05-03
|
||
|
||
### Ajouté
|
||
- Upload de fichiers par glisser-déposer avec gestion des conflits (écraser, backup, renommer, ignorer)
|
||
- Parcourir les assets CDN depuis `/browse` avec fil d'Ariane
|
||
- Statistiques de consultation via GoAccess (`/stats`), générées à la demande
|
||
- Authentification SSO via AlpID (Keycloak / OpenID Connect)
|
||
- Recherche dans les fichiers
|
||
- Scripts rsync `push-assets.sh` et `pull-assets.sh` pour la synchronisation locale ↔ serveur
|
||
- Script `deploy-app.sh` pour le déploiement de l'application Flask
|