feat(v2.0.2): Corrections de sécurité critiques et fonctionnalité de réactivation des devis

- Correction de 14 vulnérabilités SQL (8 critiques, 6 moyennes)
- Suppression de la fonction autocomplete non utilisée
- Migration complète vers PDO avec requêtes préparées
- Ajout du bouton 'Réactiver' pour les devis archivés (statut 20 → 1)
- Conversion des appels $.ajax en fetch API (vanilla JS)
- Correction des erreurs JavaScript empêchant l'attachement d'événements
- Mise à jour de la documentation (README.md et TODO.md)

Sécurité: Utilisation systématique de intval() et requêtes préparées PDO
UI: Nouveau bouton vert dans la grille 2x2 des actions sur devis archivés
Historique: Traçabilité dans devis_histo lors de la réactivation
This commit is contained in:
2025-09-12 20:25:48 +02:00
parent eabb4bf67a
commit 443b0509df
16 changed files with 4355 additions and 3318 deletions

View File

@@ -1,16 +1,36 @@
<?php
$sch = "";
$search = "";
if ($_POST) {
if (isset($_POST["schClients"])) {
$search = nettoie_input(trim($_POST["schClients"]));
$sch = 'c.libelle LIKE "%' . $search . '%" OR c.adresse1 LIKE "%' . $search . '%" OR c.cp LIKE "%' . $search . '%" OR c.ville LIKE "%' . $search . '%" OR c.contact_nom LIKE "%' . $search . '%" OR c.contact_prenom LIKE "%' . $search . '%" OR c.contact_fonction LIKE "%' . $search . '%" ';
$search = trim($_POST["schClients"]);
}
}
//! On récupère la liste des clients
$sql = 'SELECT c.* FROM clients c ';
if ($sch != "") {
$sql .= 'WHERE ' . $sch;
if ($search != "") {
// SÉCURITÉ : Utilisation de requêtes préparées pour éviter l'injection SQL
try {
$db = Database::getInstance();
$sql = 'SELECT c.* FROM clients c
WHERE c.libelle LIKE :search
OR c.adresse1 LIKE :search
OR c.cp LIKE :search
OR c.ville LIKE :search
OR c.contact_nom LIKE :search
OR c.contact_prenom LIKE :search
OR c.contact_fonction LIKE :search
ORDER BY c.libelle';
$stmt = $db->prepare($sql);
$searchParam = '%' . $search . '%';
$stmt->bindParam(':search', $searchParam, PDO::PARAM_STR);
$stmt->execute();
$aModel["clients"] = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
error_log("Erreur recherche clients : " . $e->getMessage());
$aModel["clients"] = [];
}
} else {
$sql = 'SELECT c.* FROM clients c ORDER BY c.libelle';
$aModel["clients"] = getinfos($sql, "gen");
}
$sql .= 'ORDER BY c.libelle';
$aModel["clients"] = getinfos($sql, "gen");