Changement d'adresse IP
This commit is contained in:
@@ -17,6 +17,7 @@ import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
|
||||
import mysql.connector
|
||||
from contextlib import closing
|
||||
@@ -51,8 +52,12 @@ load_dotenv(ENV_PATH, override=True)
|
||||
# CONFIGURATION
|
||||
# ============================================================
|
||||
|
||||
TABLES = ["Saclay", "Meudon"]
|
||||
TABLES_SET = set(TABLES)
|
||||
# Table de configuration : seuls les sites avec Actif = 'ON' seront surveillés.
|
||||
TABLE_SITES_SURVEILLANCE = "Sites_Surveillance"
|
||||
|
||||
# Sécurité / secours : utilisé uniquement si la table Sites_Surveillance est absente
|
||||
# ou si elle ne retourne aucun site actif.
|
||||
TABLES_FALLBACK = ["Saclay", "Meudon"]
|
||||
|
||||
DELAI_MINUTES = 15
|
||||
RAPPEL_HEURES = 6
|
||||
@@ -269,8 +274,23 @@ def envoyer_notifications(site: str, sujet: str, message: str) -> None:
|
||||
# ACCES BASE
|
||||
# ============================================================
|
||||
|
||||
def is_safe_identifier(name: str) -> bool:
|
||||
"""
|
||||
Autorise uniquement les noms simples de tables/sites :
|
||||
lettres, chiffres et underscore.
|
||||
Cela évite toute injection SQL via un nom de table dynamique.
|
||||
"""
|
||||
return bool(re.fullmatch(r"[A-Za-z0-9_]+", name or ""))
|
||||
|
||||
|
||||
def quote_identifier(name: str) -> str:
|
||||
if not is_safe_identifier(name):
|
||||
raise ValueError(f"Nom de table/site invalide : {name!r}")
|
||||
return f"`{name}`"
|
||||
|
||||
|
||||
def get_last_update(cursor, table: str) -> datetime | None:
|
||||
cursor.execute(f"SELECT MAX(Date) FROM `{table}`")
|
||||
cursor.execute(f"SELECT MAX(Date) FROM {quote_identifier(table)}")
|
||||
row = cursor.fetchone()
|
||||
|
||||
if not row or row[0] is None:
|
||||
@@ -284,19 +304,77 @@ def get_last_update(cursor, table: str) -> datetime | None:
|
||||
return None
|
||||
|
||||
|
||||
def get_tables_a_surveiller(cursor) -> list[str]:
|
||||
"""
|
||||
Lit la table Sites_Surveillance.
|
||||
Seuls les sites Actif = 'ON' sont surveillés.
|
||||
Les sites Actif = 'OFF' sont journalisés mais ignorés.
|
||||
"""
|
||||
try:
|
||||
cursor.execute(f"""
|
||||
SELECT Lieu, Actif, Commentaire
|
||||
FROM {quote_identifier(TABLE_SITES_SURVEILLANCE)}
|
||||
ORDER BY Lieu
|
||||
""")
|
||||
rows = cursor.fetchall()
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
logging.error(
|
||||
"Impossible de lire %s : %s. Utilisation du fallback : %s",
|
||||
TABLE_SITES_SURVEILLANCE,
|
||||
e,
|
||||
", ".join(TABLES_FALLBACK),
|
||||
)
|
||||
return TABLES_FALLBACK.copy()
|
||||
|
||||
tables_actives: list[str] = []
|
||||
|
||||
for lieu, actif, commentaire in rows:
|
||||
lieu = str(lieu).strip()
|
||||
actif = str(actif).strip().upper()
|
||||
|
||||
if not is_safe_identifier(lieu):
|
||||
logging.warning("Site ignoré dans %s : nom invalide %r", TABLE_SITES_SURVEILLANCE, lieu)
|
||||
continue
|
||||
|
||||
if actif == "ON":
|
||||
tables_actives.append(lieu)
|
||||
else:
|
||||
if commentaire:
|
||||
logging.info("⏸️ %s ignoré : surveillance OFF (%s)", lieu, commentaire)
|
||||
else:
|
||||
logging.info("⏸️ %s ignoré : surveillance OFF", lieu)
|
||||
|
||||
if not tables_actives:
|
||||
logging.warning(
|
||||
"Aucun site actif dans %s. Utilisation du fallback : %s",
|
||||
TABLE_SITES_SURVEILLANCE,
|
||||
", ".join(TABLES_FALLBACK),
|
||||
)
|
||||
return TABLES_FALLBACK.copy()
|
||||
|
||||
logging.info("Sites surveillés : %s", ", ".join(tables_actives))
|
||||
return tables_actives
|
||||
|
||||
|
||||
# ============================================================
|
||||
# TRAITEMENT DES TABLES
|
||||
# ============================================================
|
||||
|
||||
def traiter_table(cursor, table: str, limite: datetime,
|
||||
tables_autorisees: set[str],
|
||||
defauts_en_cours: list[str],
|
||||
alertes_envoyees: list[str],
|
||||
erreurs_sql: list[str]) -> None:
|
||||
"""
|
||||
Gère la surveillance d'une table.
|
||||
"""
|
||||
if table not in TABLES_SET:
|
||||
logging.warning(f"Table ignorée (non whitelistée) : {table}")
|
||||
if table not in tables_autorisees:
|
||||
logging.warning(f"Table ignorée (non autorisée) : {table}")
|
||||
return
|
||||
|
||||
if not is_safe_identifier(table):
|
||||
logging.warning(f"Table ignorée (nom invalide) : {table}")
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -386,11 +464,15 @@ def main() -> None:
|
||||
with closing(cnx):
|
||||
cursor = cast(MySQLCursor, cnx.cursor())
|
||||
with closing(cursor):
|
||||
for table in TABLES:
|
||||
tables_a_surveiller = get_tables_a_surveiller(cursor)
|
||||
tables_autorisees = set(tables_a_surveiller)
|
||||
|
||||
for table in tables_a_surveiller:
|
||||
traiter_table(
|
||||
cursor=cursor,
|
||||
table=table,
|
||||
limite=limite,
|
||||
tables_autorisees=tables_autorisees,
|
||||
defauts_en_cours=defauts_en_cours,
|
||||
alertes_envoyees=alertes_envoyees,
|
||||
erreurs_sql=erreurs_sql,
|
||||
|
||||
Reference in New Issue
Block a user