2026-10-21 22:25:03 +02:00
2026-10-21 22:17:26 +02:00
2026-10-21 21:58:07 +02:00
2026-10-21 22:18:01 +02:00
2026-10-21 22:23:43 +02:00
2026-10-21 22:25:03 +02:00
2026-10-21 22:12:44 +02:00

NetMonster Admin

Espace d'administration multi-pays pour traiter les fichiers .ntm (NetMonster) et gerer une base d'antennes cellulaires par pays/operateur, avec verification manuelle systematique avant toute ecriture en base finale.

Structure du projet

netmonster_admin/
├── sql/
│   ├── 01_schema.sql                  Schema complet (installation neuve)
│   └── migration_add_radio_params.sql Migration pour bases existantes (bande/frequence/azimut/largeur)
├── lib/
│   ├── db.php                         Connexion PDO partagee (a configurer)
│   ├── csrf.php                       Protection CSRF par jeton de session
│   └── ntm_import_to_staging.php      Parseur .ntm -> staging_cells, extrait les parametres radio
├── admin/                             Dossier protege par authentification
│   ├── admin_auth.php                 Barriere de session, durcissement (cookies, timeout, anti brute-force)
│   ├── login.php                      Page de connexion
│   ├── index.php                      Accueil : recapitulatif + carte de toutes les antennes validees
│   ├── review.php                     File de validation groupee par site (carte + cadastre)
│   ├── import_ntm.php                 Upload manuel d'un fichier .ntm + apercu du regroupement
│   ├── manual_add.php                 Ajout manuel d'un site multi-cellules
│   ├── edit_site.php                  Edition/suppression d'un site deja valide
│   ├── countries_settings.php         Gestion des pays et operateurs sans SQL
│   ├── export.php                     Export de la base validee (.ntm / .csv) pour mise en production
│   └── assets/theme.css               Feuille de style commune a toutes les pages
├── uploads/                           Fichiers .ntm deposes (a proteger contre l'execution PHP, voir plus bas)
├── nginx_uploads_protection.txt        Bloc de configuration Nginx a ajouter
├── INSTALL.md                         Guide d'installation complet (Debian 13, domaine + HTTPS)
├── INSTALL_TEST_VM.md                 Guide rapide pour VM de test (VMware Workstation, NAT, sans domaine)
├── SECURITY_AUDIT_V1.md               Audit de securite detaille, page par page
└── README.md                         Ce fichier

Pages de l'espace admin

Toutes les pages partagent le meme menu de navigation : Accueil - Validation - Import .ntm - Ajout manuel - Edition de site - Pays & operateurs - Export

Page Role
index.php Vue d'ensemble : compteurs (sites/cellules/en attente), carte groupee de toutes les antennes validees, repartition par operateur/techno, activite recente
review.php File d'attente des lignes importees ou saisies manuellement, regroupees automatiquement par site physique probable, avec carte + cadastre configurable par pays, validation ou rejet
import_ntm.php Depot manuel d'un fichier .ntm depuis l'admin (en plus du flux contribute.php existant), avec apercu immediat du regroupement par site et historique des imports
manual_add.php Saisie manuelle d'un site avec plusieurs cellules/secteurs, chacune avec ses parametres radio (bande, frequence, azimut, largeur de bande)
edit_site.php Recherche et correction d'un site deja valide : deplacement de la position sur la carte (marqueur glissable), edition des cellules, suppression
countries_settings.php Ajout/modification/suppression de pays (avec configuration cadastre WMS) et d'operateurs (MCC/MNC), sans ecrire de SQL
export.php Export filtrable de la base validee au format .ntm (reconstruit le format d'origine) ou .csv, pour publication sur le serveur de diffusion separe

Pipeline de donnees

Fichier .ntm (via contribute.php OU via admin/import_ntm.php)
        |
        v
importNtmFileToStaging()  -->  staging_cells (status = pending)
        |                       extrait aussi : eNB, bande, frequence,
        |                       azimut, largeur de bande depuis le champ
        |                       Location du fichier .ntm
        v
/admin/review.php  : regroupement automatique par site (eNB reel pour la
                      4G, proximite GPS pour les autres technos), carte +
                      cadastre, ajout de secteurs/bandes manquants,
                      validation manuelle
        |
        v
   sites + cells (base finale VALIDEE)
        |
        v
/admin/edit_site.php : corrections ponctuelles post-validation si besoin
        |
        v
/admin/export.php : export .ntm ou .csv
        |
        v
  Publication manuelle vers votre serveur de diffusion
  (hors perimetre de cet espace admin)

Rien n'atteint sites/cells sans validation humaine dans /admin/review.php, que la donnee vienne d'un import .ntm ou d'une saisie manuelle.

Regroupement par site physique

La fonction deriveSiteKey() (dupliquee dans review.php et import_ntm.php, a synchroniser si vous la modifiez) regroupe les cellules d'un meme site probable :

  • 4G : regroupement par l'eNB reel, transmis explicitement dans le fichier .ntm (position 5 de la ligne 4G;...). Ce n'est plus une valeur recalculee a partir du Cell Identity : le format .ntm fournit deja l'eNB directement, l'utiliser tel quel evite les regroupements errones observes avec un decalage de bits.
  • 3G / 2G / CDMA / 5G : le format .ntm ne transmet pas d'identifiant de site fiable pour ces technologies (le RNC en 3G gere plusieurs sites, la 5G ne transmet pas de gNB explicite). Le regroupement se fait par proximite GPS (~11 metres) combinee au LAC/TAC.

Extraction automatique des parametres radio

Le champ Location des fichiers .ntm reels contient souvent des informations structurees au format "eNB ID {n} - {TECH} {bande} {frequence} - {azimut}° - {largeur} - {adresse}". Le parseur (lib/ntm_import_to_staging.php) extrait automatiquement ces elements dans des colonnes dediees (band, frequency, azimuth, bandwidth, address_desc) plutot que de les laisser dans du texte libre. Ces memes champs sont saisissables individuellement dans manual_add.php et edit_site.php, et export.php recompose le champ Location a partir de ces colonnes structurees (donc toujours a jour, meme apres une correction manuelle).

Securite

Voir SECURITY_AUDIT_V1.md pour le detail complet. Points cles :

  • CSRF : tous les formulaires de mutation (review.php, manual_add.php, edit_site.php, countries_settings.php, import_ntm.php, login.php) integrent csrf_field() et verifient require_csrf_token(). export.php n'en a pas besoin (lecture seule, GET uniquement).
  • Sessions : cookies avec HttpOnly, SameSite=Strict, et flag Secure detecte automatiquement selon que la requete est en HTTPS. Expiration automatique apres 30 minutes d'inactivite.
  • Anti brute-force : verrouillage temporaire (5 minutes) apres 5 echecs de connexion consecutifs.
  • PHP 8.3+ : tous les appels a htmlspecialchars() sur des colonnes numeriques (int, float) sont precedes d'un cast (string) explicite, requis depuis PHP 8.1+ et strictement applique en 8.3.
  • Upload .ntm : validation d'extension, limite de taille (10 Mo par defaut), verification is_uploaded_file(), nom de fichier assaini avant ecriture disque.

Action serveur requise

Le dossier uploads/ (cree automatiquement par import_ntm.php) doit etre protege contre l'execution de PHP. Ajoutez le contenu de nginx_uploads_protection.txt a votre configuration Nginx, puis :

sudo nginx -t && sudo systemctl reload nginx

Installation

  • Deploiement complet (domaine + HTTPS) : suivez INSTALL.md.
  • VM de test rapide (VMware Workstation, NAT, sans domaine) : suivez INSTALL_TEST_VM.md.

Resume rapide pour une base neuve :

  1. Executer sql/01_schema.sql sur votre base MariaDB/MySQL.
  2. Configurer lib/db.php avec vos identifiants.
  3. Creer un compte admin :
    php -r "echo password_hash('votre_mot_de_passe', PASSWORD_DEFAULT), PHP_EOL;"
    
    INSERT INTO admin_users (username, password_hash, role) VALUES ('votre_login', '<hash>', 'admin');
    
  4. Appliquer la protection Nginx du dossier uploads/ (voir ci-dessus).
  5. Ouvrir /admin/login.php.

Si vous partez d'une base existante (mise a jour depuis une version anterieure)

Si votre base a ete creee avant l'ajout des parametres radio detailles, appliquez la migration :

mysql -u netmonster_user -p netmonster < sql/migration_add_radio_params.sql

Cette migration ajoute les colonnes band, frequency, azimuth, bandwidth sur cells et staging_cells, et address_desc sur sites et staging_cells.

Ajouter un nouveau pays

Aucun SQL requis : ouvrez /admin/countries_settings.php et renseignez le MCC, le code ISO2, le nom du pays, les coordonnees de centrage carte, et si disponible l'URL d'un service WMS cadastre national (avec son attribution obligatoire). Ajoutez ensuite les operateurs (MCC/MNC/nom commercial) du pays. La page review.php et le tableau de bord s'adaptent automatiquement des que vous filtrez sur ce pays, sans modification de code.

Attribution des fonds de carte (obligatoire)

  • OpenStreetMap : mention "(c) OpenStreetMap contributors" affichee en permanence sur toutes les cartes (accueil, validation, edition de site), conformement a la licence ODbL. Ne jamais la masquer.
  • Cadastre national : chaque pays configure dans countries_settings.php doit avoir son propre texte d'attribution (ex: "Administration du Cadastre et de la Topographie (ACT)" pour le Luxembourg).

Notes techniques

  • Les tuiles OSM standard (tile.openstreetmap.org) sont adaptees a un usage interne a faible trafic. Pour un futur serveur public a fort volume, prevoir un fournisseur de tuiles commercial ou un hebergement de tuiles dedie.
  • Le champ NCI (5G) peut depasser la capacite d'un entier 32 bits PHP sur certains systemes : verifiez l'absence de troncature sur votre environnement de production.
  • Formats .ntm geres : 2G, 3G, 4G, 5G, CDMA (voir les commentaires dans lib/ntm_import_to_staging.php pour le detail exact des colonnes par technologie).
  • Un seul compte administrateur est prevu pour cette V1 : aucune restriction d'acces par perimetre pays/operateur n'a ete implementee (non necessaire dans ce contexte).

Pourquoi sur Gitea ?

Un peu moins de gafam dans ce monde de brut :)

Languages
PHP 100%