#68 — site-survey-db
PLANIFIÉ
Priorité: 🟠 HAUTE · Type: TYPE B · Conteneur: rgz-api · Code: app/api/v1/endpoints/sites.py
Dépendances: #4 rgz-db
Description
Base de données géographique des sites hotspot ACCESS. Stocke les coordonnées GPS, informations réseaux et métriques terrain pour les 22 sites actuels dans 8 villes du Bénin. Alimente le dashboard RF (#41) et les rapports ARCEP (#47).
La table reseller_sites est la source de vérité pour la localisation de chaque point d'accès. Elle est utilisée par le module VLAN (#31) pour l'adressage IP, par le monitoring RF (#41) pour la heatmap, et par l'onboarding (#56) pour créer les sites lors de la mise en service.
Expose une API REST et un endpoint GeoJSON compatible Leaflet.js pour les cartes dans le dashboard NOC (#52).
Architecture Interne
POST /api/v1/sites → Création site (onboarding #56)
↓
DB: reseller_sites (lat, lng, city, quarter, nas_id, ap_ip)
↓
GET /api/v1/sites/map → GeoJSON pour Leaflet.js
GET /api/v1/sites → Liste paginée
GET /api/v1/sites/{id} → Détail + métriques RSSI actuelles
↓
Join avec snmp_metrics → RSSI/SNR temps réel par siteTable DB reseller_sites
CREATE TABLE reseller_sites (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
reseller_id UUID NOT NULL REFERENCES resellers(id),
site_number INT NOT NULL,
nas_id TEXT NOT NULL UNIQUE, -- ex: access_kossou
ssid TEXT NOT NULL, -- ex: ACCESS Kossou
latitude DOUBLE PRECISION NOT NULL,
longitude DOUBLE PRECISION NOT NULL,
city TEXT NOT NULL, -- ex: Cotonou
quarter TEXT, -- ex: Akpakpa
ap_ip TEXT NOT NULL, -- ex: 10.142.0.2
vlan_id INT,
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(reseller_id, site_number)
);8 villes couvertes
| Ville | Sites actuels |
|---|---|
| Cotonou | ~10 |
| Abomey-Calavi | ~4 |
| Porto-Novo | ~3 |
| Parakou | ~2 |
| Bohicon | ~1 |
| Natitingou | ~1 |
| Kandi | ~1 |
| Lokossa | ~1 |
Configuration
DATABASE_URL=postgresql://rgz:password@rgz-db:5432/rgzEndpoints API
| Méthode | Route | Réponse | Auth |
|---|---|---|---|
| GET | /api/v1/sites | {items:[], total, page, pages} | JWT |
| POST | /api/v1/sites | 201 {site} | Admin JWT |
| GET | /api/v1/sites/{id} | {site + rssi_actuel} | JWT |
| PUT | /api/v1/sites/{id} | 200 {site} | Admin JWT |
| DELETE | /api/v1/sites/{id} | 204 | Admin JWT |
| GET | /api/v1/sites/map | GeoJSON FeatureCollection | Public |
| GET | /api/v1/sites/by-nas/{nas_id} | {site} | JWT |
GET /api/v1/sites/map — GeoJSON
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.3912, 6.3654]
},
"properties": {
"id": "550e8400-...",
"nas_id": "access_kossou",
"ssid": "ACCESS Kossou",
"city": "Cotonou",
"rssi_dbm": -68,
"status": "active"
}
}
]
}POST /api/v1/sites
{
"reseller_id": "550e8400-e29b-41d4-a716-446655440000",
"site_number": 1,
"nas_id": "access_kossou",
"ssid": "ACCESS Kossou",
"latitude": 6.3654,
"longitude": 2.3912,
"city": "Cotonou",
"quarter": "Akpakpa",
"ap_ip": "10.142.0.2",
"vlan_id": 142
}Commandes Utiles
# Lister tous les sites
curl -H "Authorization: Bearer $JWT" \
https://api-rgz.duckdns.org/api/v1/sites
# Carte GeoJSON (public)
curl https://api-rgz.duckdns.org/api/v1/sites/map | python3 -m json.tool
# Trouver site par NAS-ID
curl -H "Authorization: Bearer $JWT" \
https://api-rgz.duckdns.org/api/v1/sites/by-nas/access_kossou
# Compter sites par ville
docker exec rgz-db psql -U postgres -c \
"SELECT city, COUNT(*) FROM reseller_sites GROUP BY city ORDER BY count DESC;"Sécurité
| Règle | Implémentation |
|---|---|
| SEC-01 | Revendeur voit uniquement ses propres sites |
| Public | /api/v1/sites/map public (sans données personnelles) |
| Admin | POST/PUT/DELETE → Admin JWT uniquement |
Implémentation TODO
- [ ] Endpoint
app/api/v1/endpoints/sites.py - [ ] Table
reseller_sitesmigration SQL - [ ] GET /api/v1/sites/map → GeoJSON + join RSSI actuel
- [ ] GET /api/v1/sites/by-nas/
- [ ] Import initial CSV des 22 sites existants
- [ ] SEC-01 IDOR par reseller_id
- [ ] Tests unitaires endpoints
Dernière mise à jour: 2026-02-21