From be12cadea6e11edeb7b25ed997c572451876fede Mon Sep 17 00:00:00 2001 From: voxan Date: Wed, 21 Oct 2026 22:18:01 +0200 Subject: [PATCH] Maj SQL --- sql/install_full_schema.sql | 529 +++++++++++++++++++----------------- 1 file changed, 280 insertions(+), 249 deletions(-) diff --git a/sql/install_full_schema.sql b/sql/install_full_schema.sql index 94c01c4..30d7bea 100644 --- a/sql/install_full_schema.sql +++ b/sql/install_full_schema.sql @@ -1,261 +1,292 @@ --- ===================================================================== --- NetMonster Admin — Schema COMPLET pour INSTALLATION NEUVE --- Fichier unique : contient tout ce qu'il faut executer une seule fois --- sur une base vide pour obtenir un environnement pret a l'emploi. --- --- Regroupe et remplace, dans l'ordre : --- 1. schema_v3_with_radio_params.sql (tables de base + donnees Luxembourg) --- 2. migration_fix_uniq_cell.sql (deja integre : uniq_cell inclut sub_id2 des la creation) --- 3. migration_security_hardening.sql / schema_v3_addendum_login_attempts.sql --- (table login_attempts pour le rate limiting de connexion) --- --- Usage (installation neuve uniquement) : --- mysql -u netmonster_user -p netmonster < install_full_schema.sql --- --- Si vous avez DEJA une base existante avec un schema anterieur, --- N'UTILISEZ PAS ce fichier : utilisez plutot, selon votre situation : --- - migration_fix_uniq_cell.sql (si votre contrainte uniq_cell --- ne contient pas encore sub_id2) --- - migration_security_hardening.sql (si vous n'avez pas encore la --- table login_attempts) --- Ces deux fichiers de migration restent disponibles independamment --- dans ce dossier pour les mises a jour d'une base deja en production, --- sans risque de perte de donnees. --- --- Toutes les instructions CREATE TABLE utilisent IF NOT EXISTS et les --- INSERT de reference utilisent ON DUPLICATE KEY UPDATE : ce fichier --- est idempotent, l'executer une seconde fois par erreur ne casse rien --- et ne duplique aucune donnee. --- ===================================================================== - +-- ===================================================================== +-- NetMonster Admin — Schema COMPLET pour INSTALLATION NEUVE +-- Fichier unique : contient tout ce qu'il faut executer une seule fois +-- sur une base vide pour obtenir un environnement pret a l'emploi. +-- +-- Regroupe et remplace, dans l'ordre : +-- 1. schema_v3_with_radio_params.sql (tables de base + donnees Luxembourg) +-- 2. migration_fix_uniq_cell.sql (deja integre : uniq_cell inclut sub_id2 des la creation) +-- 3. migration_security_hardening.sql / schema_v3_addendum_login_attempts.sql +-- (table login_attempts pour le rate limiting de connexion) +-- +-- Usage (installation neuve uniquement) : +-- mysql -u netmonster_user -p netmonster < install_full_schema.sql +-- +-- Si vous avez DEJA une base existante avec un schema anterieur, +-- N'UTILISEZ PAS ce fichier : utilisez plutot, selon votre situation : +-- - migration_fix_uniq_cell.sql (si votre contrainte uniq_cell +-- ne contient pas encore sub_id2) +-- - migration_security_hardening.sql (si vous n'avez pas encore la +-- table login_attempts) +-- Ces deux fichiers de migration restent disponibles independamment +-- dans ce dossier pour les mises a jour d'une base deja en production, +-- sans risque de perte de donnees. +-- +-- Toutes les instructions CREATE TABLE utilisent IF NOT EXISTS et les +-- INSERT de reference utilisent ON DUPLICATE KEY UPDATE : ce fichier +-- est idempotent, l'executer une seconde fois par erreur ne casse rien +-- et ne duplique aucune donnee. +-- ===================================================================== + + +-- --------------------------------------------------------------------- +-- 1. PAYS +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS countries ( +id INT AUTO_INCREMENT PRIMARY KEY, +mcc VARCHAR(3) NOT NULL UNIQUE, +iso2 VARCHAR(2) NOT NULL, +name VARCHAR(100) NOT NULL, +default_lat DOUBLE NULL, +default_lon DOUBLE NULL, +default_zoom TINYINT NULL DEFAULT 9, +cadastre_wms_url VARCHAR(255) NULL, +cadastre_wms_layer VARCHAR(100) NULL, +cadastre_attribution_html VARCHAR(500) NULL, +cadastre_srs VARCHAR(20) NULL DEFAULT 'EPSG:3857' +) ENGINE=InnoDB; + +INSERT INTO countries (mcc, iso2, name, default_lat, default_lon, default_zoom, +cadastre_wms_url, cadastre_wms_layer, cadastre_attribution_html, cadastre_srs) +VALUES ( +'270','LU','Luxembourg', 49.8153, 6.1296, 9, +'https://wms.geoportail.lu/public_map_layers/service', +'359', +'Cadastre : © Administration du Cadastre et de la Topographie (ACT)', +'EPSG:3857' +) +ON DUPLICATE KEY UPDATE name = VALUES(name); + + +-- --------------------------------------------------------------------- +-- 2. OPERATEURS +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS operators ( +id INT AUTO_INCREMENT PRIMARY KEY, +country_id INT NOT NULL, +mcc VARCHAR(3) NOT NULL, +mnc VARCHAR(2) NOT NULL, +brand VARCHAR(50) NOT NULL, +full_name VARCHAR(100), +UNIQUE KEY plmn (mcc, mnc), +FOREIGN KEY (country_id) REFERENCES countries(id) +) ENGINE=InnoDB; + +INSERT INTO operators (country_id, mcc, mnc, brand, full_name) +SELECT c.id, '270','01','POST', 'POST Luxembourg' FROM countries c WHERE c.mcc='270' +UNION ALL SELECT c.id, '270','05','LoL', 'Luxembourg Online S.A.' FROM countries c WHERE c.mcc='270' +UNION ALL SELECT c.id, '270','77','Tango', 'Tango SA' FROM countries c WHERE c.mcc='270' +UNION ALL SELECT c.id, '270','99','Orange', 'Orange Communications Luxembourg S.A.' FROM countries c WHERE c.mcc='270' +ON DUPLICATE KEY UPDATE brand = VALUES(brand); + + +-- --------------------------------------------------------------------- +-- 3. SITES = lieu physique (pylone, toit...). Regroupe plusieurs cellules. +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS sites ( +id BIGINT AUTO_INCREMENT PRIMARY KEY, +country_id INT NOT NULL, +operator_id INT NOT NULL, +lat DOUBLE NOT NULL, +lon DOUBLE NOT NULL, +location_desc VARCHAR(255), +address_desc VARCHAR(255), +created_at DATETIME DEFAULT CURRENT_TIMESTAMP, +created_by VARCHAR(100), +FOREIGN KEY (country_id) REFERENCES countries(id), +FOREIGN KEY (operator_id) REFERENCES operators(id), +INDEX idx_geo (lat, lon) +) ENGINE=InnoDB; + + +-- --------------------------------------------------------------------- +-- 4. CELLS = table finale VALIDEE. Une ligne = une cellule/secteur radio. +-- Inclut les parametres radio detailles (bande, frequence, azimut, +-- largeur de bande), stockes de facon structuree plutot que noyes +-- dans un texte libre. +-- +-- uniq_cell inclut DEJA sub_id2 (eNB/RNC) des la creation : deux eNB +-- distincts peuvent legitimement partager le meme cell_id + area_code +-- (le CID local est souvent un petit compteur par eNB), ce n'est donc +-- pas un doublon. Le vrai doublon est : meme eNB + meme Cell ID + meme +-- area_code. (Correctif anciennement livre a part dans +-- migration_fix_uniq_cell.sql, integre ici directement.) +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS cells ( +id BIGINT AUTO_INCREMENT PRIMARY KEY, +site_id BIGINT NOT NULL, +tech ENUM('2G','3G','4G','5G','CDMA') NOT NULL, +mcc VARCHAR(3) NOT NULL, +mnc VARCHAR(2) NOT NULL, +cell_id BIGINT NOT NULL, +area_code INT NOT NULL, +sub_id INT, -- BSIC / PSC / PCI +sub_id2 INT, -- RNC / eNB +band VARCHAR(20), -- ex: "B7", "N78" +frequency VARCHAR(20), -- ex: "700MHz" +azimuth SMALLINT, -- 0-359 degres +bandwidth VARCHAR(20), -- ex: "10MHz" +arfcn BIGINT, +validated_at DATETIME DEFAULT CURRENT_TIMESTAMP, +validated_by VARCHAR(100), +FOREIGN KEY (site_id) REFERENCES sites(id) ON DELETE CASCADE, +UNIQUE KEY uniq_cell (tech, mcc, mnc, sub_id2, cell_id, area_code), +INDEX idx_operator_tech (mcc, mnc, tech), +INDEX idx_band (band) +) ENGINE=InnoDB; + + +-- --------------------------------------------------------------------- +-- 5. STAGING = zone de quarantaine. Rien n'entre dans sites/cells sans +-- passer par ici et etre valide manuellement dans l'admin. +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS staging_batches ( +id INT AUTO_INCREMENT PRIMARY KEY, +label VARCHAR(255), +created_at DATETIME DEFAULT CURRENT_TIMESTAMP, +created_by VARCHAR(100) +) ENGINE=InnoDB; + +CREATE TABLE IF NOT EXISTS staging_cells ( +id BIGINT AUTO_INCREMENT PRIMARY KEY, +import_id INT, +batch_id INT NULL, +tech ENUM('2G','3G','4G','5G','CDMA') NOT NULL, +mcc VARCHAR(3) NOT NULL, +mnc VARCHAR(2) NOT NULL, +operator_guess INT, +cell_id BIGINT NOT NULL, +area_code INT NOT NULL, +sub_id INT, +sub_id2 INT, +band VARCHAR(20), +frequency VARCHAR(20), +azimuth SMALLINT, +bandwidth VARCHAR(20), +address_desc VARCHAR(255), +lat DOUBLE, +lon DOUBLE, +location_desc VARCHAR(255), +arfcn BIGINT, +raw_line TEXT, +source ENUM('ntm_import','manual_form','cellmapper_import') NOT NULL DEFAULT 'ntm_import', +possible_dup_of BIGINT NULL, +status ENUM('pending','validated','rejected','edited') DEFAULT 'pending', +submitted_at DATETIME DEFAULT CURRENT_TIMESTAMP, +reviewed_at DATETIME NULL, +reviewed_by VARCHAR(100) NULL, +reject_reason VARCHAR(255) NULL, +FOREIGN KEY (operator_guess) REFERENCES operators(id), +FOREIGN KEY (possible_dup_of) REFERENCES cells(id), +FOREIGN KEY (batch_id) REFERENCES staging_batches(id), +INDEX idx_status (status), +INDEX idx_source (source) +) ENGINE=InnoDB; + +-- Note : la valeur 'cellmapper_import' a ete ajoutee a l'ENUM `source` +-- pour tracer les cellules completees/creees via admin/cellmapper_import.php +-- (voir aussi lib none dedie : la logique vit directement dans la page). + + +-- --------------------------------------------------------------------- +-- 6. IMPORTS = historique des depots de fichiers .ntm +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS imports ( +id INT AUTO_INCREMENT PRIMARY KEY, +filename VARCHAR(255) NOT NULL, +country_id INT, +uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP, +processed_at DATETIME NULL, +total_lines INT DEFAULT 0, +staged_count INT DEFAULT 0, +error_count INT DEFAULT 0, +status ENUM('uploaded','processing','done','error') DEFAULT 'uploaded', +FOREIGN KEY (country_id) REFERENCES countries(id) +) ENGINE=InnoDB; + + +-- --------------------------------------------------------------------- +-- 7. COMPTES ADMIN (separation stricte admin / public) +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS admin_users ( +id INT AUTO_INCREMENT PRIMARY KEY, +username VARCHAR(100) NOT NULL UNIQUE, +password_hash VARCHAR(255) NOT NULL, +role ENUM('admin','reviewer') DEFAULT 'reviewer', +created_at DATETIME DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB; + + +-- --------------------------------------------------------------------- +-- 8. RATE LIMITING DE CONNEXION (durcissement securite du 20/09/2026) +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS login_attempts ( +id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, +username_normalized VARCHAR(190) NOT NULL, +ip_address VARCHAR(45) NOT NULL, +attempted_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, +success TINYINT(1) NOT NULL DEFAULT 0, +turnstile_verified TINYINT(1) NOT NULL DEFAULT 0, +PRIMARY KEY (id), +KEY idx_username_ip_time (username_normalized, ip_address, attempted_at), +KEY idx_ip_time (ip_address, attempted_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- --------------------------------------------------------------------- --- 1. PAYS +-- 9. TABLES ADDITIONNELLES (Couches, Backups, Historique d'imports) -- --------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS countries ( -id INT AUTO_INCREMENT PRIMARY KEY, -mcc VARCHAR(3) NOT NULL UNIQUE, -iso2 VARCHAR(2) NOT NULL, -name VARCHAR(100) NOT NULL, -default_lat DOUBLE NULL, -default_lon DOUBLE NULL, -default_zoom TINYINT NULL DEFAULT 9, -cadastre_wms_url VARCHAR(255) NULL, -cadastre_wms_layer VARCHAR(100) NULL, -cadastre_attribution_html VARCHAR(500) NULL, -cadastre_srs VARCHAR(20) NULL DEFAULT 'EPSG:3857' + +-- Pour admin/map_layers.php +CREATE TABLE IF NOT EXISTS map_layers ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(100) NOT NULL, + layer_key VARCHAR(50) NOT NULL, + color VARCHAR(7) NOT NULL, + is_visible TINYINT(1) DEFAULT 1, + sort_order INT DEFAULT 0, + description TEXT ) ENGINE=InnoDB; -INSERT INTO countries (mcc, iso2, name, default_lat, default_lon, default_zoom, -cadastre_wms_url, cadastre_wms_layer, cadastre_attribution_html, cadastre_srs) -VALUES ( -'270','LU','Luxembourg', 49.8153, 6.1296, 9, -'https://wms.geoportail.lu/public_map_layers/service', -'359', -'Cadastre : © Administration du Cadastre et de la Topographie (ACT)', -'EPSG:3857' -) -ON DUPLICATE KEY UPDATE name = VALUES(name); - - --- --------------------------------------------------------------------- --- 2. OPERATEURS --- --------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS operators ( -id INT AUTO_INCREMENT PRIMARY KEY, -country_id INT NOT NULL, -mcc VARCHAR(3) NOT NULL, -mnc VARCHAR(2) NOT NULL, -brand VARCHAR(50) NOT NULL, -full_name VARCHAR(100), -UNIQUE KEY plmn (mcc, mnc), -FOREIGN KEY (country_id) REFERENCES countries(id) +-- Pour admin/backup.php +CREATE TABLE IF NOT EXISTS backup_log ( + id INT AUTO_INCREMENT PRIMARY KEY, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + admin_username VARCHAR(100) NOT NULL, + label VARCHAR(255) NOT NULL, + note TEXT, + size_bytes_reported BIGINT ) ENGINE=InnoDB; -INSERT INTO operators (country_id, mcc, mnc, brand, full_name) -SELECT c.id, '270','01','POST', 'POST Luxembourg' FROM countries c WHERE c.mcc='270' -UNION ALL SELECT c.id, '270','05','LoL', 'Luxembourg Online S.A.' FROM countries c WHERE c.mcc='270' -UNION ALL SELECT c.id, '270','77','Tango', 'Tango SA' FROM countries c WHERE c.mcc='270' -UNION ALL SELECT c.id, '270','99','Orange', 'Orange Communications Luxembourg S.A.' FROM countries c WHERE c.mcc='270' -ON DUPLICATE KEY UPDATE brand = VALUES(brand); - - --- --------------------------------------------------------------------- --- 3. SITES = lieu physique (pylone, toit...). Regroupe plusieurs cellules. --- --------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS sites ( -id BIGINT AUTO_INCREMENT PRIMARY KEY, -country_id INT NOT NULL, -operator_id INT NOT NULL, -lat DOUBLE NOT NULL, -lon DOUBLE NOT NULL, -location_desc VARCHAR(255), -address_desc VARCHAR(255), -created_at DATETIME DEFAULT CURRENT_TIMESTAMP, -created_by VARCHAR(100), -FOREIGN KEY (country_id) REFERENCES countries(id), -FOREIGN KEY (operator_id) REFERENCES operators(id), -INDEX idx_geo (lat, lon) +-- Pour admin/import_history.php +CREATE TABLE IF NOT EXISTS import_batches ( + id INT AUTO_INCREMENT PRIMARY KEY, + filename VARCHAR(255) NOT NULL, + imported_at DATETIME DEFAULT CURRENT_TIMESTAMP, + imported_by VARCHAR(100), + status VARCHAR(50), + rows_total INT DEFAULT 0, + rows_imported INT DEFAULT 0, + rows_rejected INT DEFAULT 0, + country_id INT, + FOREIGN KEY (country_id) REFERENCES countries(id) ) ENGINE=InnoDB; - --- --------------------------------------------------------------------- --- 4. CELLS = table finale VALIDEE. Une ligne = une cellule/secteur radio. --- Inclut les parametres radio detailles (bande, frequence, azimut, --- largeur de bande), stockes de facon structuree plutot que noyes --- dans un texte libre. --- --- uniq_cell inclut DEJA sub_id2 (eNB/RNC) des la creation : deux eNB --- distincts peuvent legitimement partager le meme cell_id + area_code --- (le CID local est souvent un petit compteur par eNB), ce n'est donc --- pas un doublon. Le vrai doublon est : meme eNB + meme Cell ID + meme --- area_code. (Correctif anciennement livre a part dans --- migration_fix_uniq_cell.sql, integre ici directement.) --- --------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS cells ( -id BIGINT AUTO_INCREMENT PRIMARY KEY, -site_id BIGINT NOT NULL, -tech ENUM('2G','3G','4G','5G','CDMA') NOT NULL, -mcc VARCHAR(3) NOT NULL, -mnc VARCHAR(2) NOT NULL, -cell_id BIGINT NOT NULL, -area_code INT NOT NULL, -sub_id INT, -- BSIC / PSC / PCI -sub_id2 INT, -- RNC / eNB -band VARCHAR(20), -- ex: "B7", "N78" -frequency VARCHAR(20), -- ex: "700MHz" -azimuth SMALLINT, -- 0-359 degres -bandwidth VARCHAR(20), -- ex: "10MHz" -arfcn BIGINT, -validated_at DATETIME DEFAULT CURRENT_TIMESTAMP, -validated_by VARCHAR(100), -FOREIGN KEY (site_id) REFERENCES sites(id) ON DELETE CASCADE, -UNIQUE KEY uniq_cell (tech, mcc, mnc, sub_id2, cell_id, area_code), -INDEX idx_operator_tech (mcc, mnc, tech), -INDEX idx_band (band) +CREATE TABLE IF NOT EXISTS import_errors ( + id INT AUTO_INCREMENT PRIMARY KEY, + batch_id INT NOT NULL, + line_number INT, + message TEXT, + raw_line TEXT, + FOREIGN KEY (batch_id) REFERENCES import_batches(id) ON DELETE CASCADE ) ENGINE=InnoDB; - --- --------------------------------------------------------------------- --- 5. STAGING = zone de quarantaine. Rien n'entre dans sites/cells sans --- passer par ici et etre valide manuellement dans l'admin. --- --------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS staging_batches ( -id INT AUTO_INCREMENT PRIMARY KEY, -label VARCHAR(255), -created_at DATETIME DEFAULT CURRENT_TIMESTAMP, -created_by VARCHAR(100) -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS staging_cells ( -id BIGINT AUTO_INCREMENT PRIMARY KEY, -import_id INT, -batch_id INT NULL, -tech ENUM('2G','3G','4G','5G','CDMA') NOT NULL, -mcc VARCHAR(3) NOT NULL, -mnc VARCHAR(2) NOT NULL, -operator_guess INT, -cell_id BIGINT NOT NULL, -area_code INT NOT NULL, -sub_id INT, -sub_id2 INT, -band VARCHAR(20), -frequency VARCHAR(20), -azimuth SMALLINT, -bandwidth VARCHAR(20), -address_desc VARCHAR(255), -lat DOUBLE, -lon DOUBLE, -location_desc VARCHAR(255), -arfcn BIGINT, -raw_line TEXT, -source ENUM('ntm_import','manual_form','cellmapper_import') NOT NULL DEFAULT 'ntm_import', -possible_dup_of BIGINT NULL, -status ENUM('pending','validated','rejected','edited') DEFAULT 'pending', -submitted_at DATETIME DEFAULT CURRENT_TIMESTAMP, -reviewed_at DATETIME NULL, -reviewed_by VARCHAR(100) NULL, -reject_reason VARCHAR(255) NULL, -FOREIGN KEY (operator_guess) REFERENCES operators(id), -FOREIGN KEY (possible_dup_of) REFERENCES cells(id), -FOREIGN KEY (batch_id) REFERENCES staging_batches(id), -INDEX idx_status (status), -INDEX idx_source (source) -) ENGINE=InnoDB; - --- Note : la valeur 'cellmapper_import' a ete ajoutee a l'ENUM `source` --- pour tracer les cellules completees/creees via admin/cellmapper_import.php --- (voir aussi lib none dedie : la logique vit directement dans la page). - - --- --------------------------------------------------------------------- --- 6. IMPORTS = historique des depots de fichiers .ntm --- --------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS imports ( -id INT AUTO_INCREMENT PRIMARY KEY, -filename VARCHAR(255) NOT NULL, -country_id INT, -uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP, -processed_at DATETIME NULL, -total_lines INT DEFAULT 0, -staged_count INT DEFAULT 0, -error_count INT DEFAULT 0, -status ENUM('uploaded','processing','done','error') DEFAULT 'uploaded', -FOREIGN KEY (country_id) REFERENCES countries(id) -) ENGINE=InnoDB; - - --- --------------------------------------------------------------------- --- 7. COMPTES ADMIN (separation stricte admin / public) --- --------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS admin_users ( -id INT AUTO_INCREMENT PRIMARY KEY, -username VARCHAR(100) NOT NULL UNIQUE, -password_hash VARCHAR(255) NOT NULL, -role ENUM('admin','reviewer') DEFAULT 'reviewer', -created_at DATETIME DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB; - - --- --------------------------------------------------------------------- --- 8. RATE LIMITING DE CONNEXION (durcissement securite du 20/09/2026) --- --- Compteur d'echecs de connexion stocke en base (et non en session --- PHP), afin qu'un attaquant ne puisse pas remettre son compteur a --- zero en vidant ses cookies ou en ouvrant une navigation privee. --- Utilise par admin/admin_auth.php (is_login_locked_out, --- record_login_attempt) et admin/login.php. --- --- Deux seuils appliques cote PHP a partir de cette meme table : --- - 5 echecs sur le couple (identifiant, IP) en 15 min -> verrouillage cible --- - 30 echecs sur l'IP seule (tous identifiants confondus) en 15 min --- -> verrouillage large, plus permissif pour ne pas bloquer tout --- le monde depuis une IP partagee (ex: sortie Tailscale commune) --- --------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS login_attempts ( -id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, -username_normalized VARCHAR(190) NOT NULL, -ip_address VARCHAR(45) NOT NULL, -attempted_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, -success TINYINT(1) NOT NULL DEFAULT 0, -turnstile_verified TINYINT(1) NOT NULL DEFAULT 0, -PRIMARY KEY (id), -KEY idx_username_ip_time (username_normalized, ip_address, attempted_at), -KEY idx_ip_time (ip_address, attempted_at) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - --- Purge recommandee via cron (pas dans ce fichier), pour eviter que --- la table ne grossisse indefiniment : --- DELETE FROM login_attempts WHERE attempted_at < NOW() - INTERVAL 30 DAY; - - --- ===================================================================== --- Fin du schema. A ce stade, la base contient : --- - Luxembourg (MCC 270) + POST/LoL/Tango/Orange pre-configures --- - Toutes les tables necessaires au fonctionnement complet de --- l'admin (import .ntm, import CellMapper, validation staging, --- edition de sites, export, rate limiting login) --- - AUCUN compte administrateur : creez-en un manuellement, voir --- INSTALL.md ou INSTALL_TEST_VM.md, section "Creation du compte --- administrateur". +-- ===================================================================== +-- Fin du schema. A ce stade, la base contient : +-- - Luxembourg (MCC 270) + POST/LoL/Tango/Orange pre-configures +-- - Toutes les tables necessaires au fonctionnement complet de +-- l'admin (import .ntm, import CellMapper, validation staging, +-- edition de sites, export, rate limiting login) +-- - AUCUN compte administrateur : creez-en un manuellement, voir +-- INSTALL.md ou INSTALL_TEST_VM.md, section "Creation du compte +-- administrateur". -- ===================================================================== \ No newline at end of file