Initial commit — Serveur Lucas SmartEye
API réception alertes chute (SmartEye/YOLO), analyse IA (Gemini 2.5 Flash), gestion alertes avec escalade (watchdog), notifications Firebase, dashboard web, documentation MkDocs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
137
provision.php
Normal file
137
provision.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/**
|
||||
* provision.php — Provisioning d'un nouveau site client
|
||||
*
|
||||
* Crée un nouveau client dans database.json, assigne un site_number,
|
||||
* génère un token, crée le dossier client, et retourne les infos
|
||||
* de provisioning (dont un QR code encodé en base64).
|
||||
*
|
||||
* POST /provision.php
|
||||
* Content-Type: application/json
|
||||
* Authorization: Bearer <ADMIN_PASSWORD>
|
||||
*
|
||||
* {
|
||||
* "client_id": "dupont_marie",
|
||||
* "name": "Marie Dupont",
|
||||
* "senior_name": "Mamie Marie",
|
||||
* "address": "12 rue des Roses",
|
||||
* "city": "20270 Aleria",
|
||||
* "latitude": "42.1028",
|
||||
* "longitude": "9.5147",
|
||||
* "emergency_number": "15",
|
||||
* "contacts": [{"name": "Jean", "role": "Fils", "phone": "+33698765432"}]
|
||||
* }
|
||||
*/
|
||||
header("Content-Type: application/json");
|
||||
header("Access-Control-Allow-Origin: *");
|
||||
header("Access-Control-Allow-Methods: POST, OPTIONS");
|
||||
header("Access-Control-Allow-Headers: Content-Type, Authorization");
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(204); exit; }
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
die(json_encode(["success" => false, "message" => "POST uniquement"]));
|
||||
}
|
||||
|
||||
// Authentification admin
|
||||
$ADMIN_PASS = "smart123";
|
||||
$auth_header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
|
||||
$provided_pass = str_replace('Bearer ', '', $auth_header);
|
||||
if ($provided_pass !== $ADMIN_PASS) {
|
||||
http_response_code(401);
|
||||
die(json_encode(["success" => false, "message" => "Authentification admin requise"]));
|
||||
}
|
||||
|
||||
$input = json_decode(file_get_contents("php://input"), true);
|
||||
$client_id = preg_replace('/[^a-z0-9_]/', '', strtolower($input['client_id'] ?? ''));
|
||||
|
||||
if (empty($client_id)) {
|
||||
http_response_code(400);
|
||||
die(json_encode(["success" => false, "message" => "client_id requis"]));
|
||||
}
|
||||
|
||||
$DB_FILE = "database.json";
|
||||
$db = json_decode(file_get_contents($DB_FILE), true);
|
||||
|
||||
// Vérifier unicité
|
||||
foreach ($db['clients'] as $c) {
|
||||
if (strcasecmp($c['name'] ?? '', $client_id) === 0 || strcasecmp($c['name'] ?? '', $input['name'] ?? '') === 0) {
|
||||
http_response_code(409);
|
||||
die(json_encode(["success" => false, "message" => "Client déjà existant"]));
|
||||
}
|
||||
}
|
||||
|
||||
// Calculer le prochain site_number
|
||||
$max_site = 0;
|
||||
foreach ($db['clients'] as $c) {
|
||||
$sn = $c['site_number'] ?? 0;
|
||||
if ($sn > $max_site) $max_site = $sn;
|
||||
}
|
||||
$site_number = $max_site + 1;
|
||||
|
||||
// Générer le token
|
||||
$token = bin2hex(random_bytes(4));
|
||||
|
||||
// Calculer les ports
|
||||
$base_port = 8550 + ($site_number - 1) * 10;
|
||||
|
||||
// Créer l'entrée client
|
||||
$db['clients'][$client_id] = [
|
||||
"name" => $input['name'] ?? $client_id,
|
||||
"token" => $token,
|
||||
"created_at" => date("Y-m-d H:i:s"),
|
||||
"site_number" => $site_number,
|
||||
"site_status" => "provisioned",
|
||||
"senior_name" => $input['senior_name'] ?? $input['name'] ?? '',
|
||||
"senior_nickname" => $input['senior_nickname'] ?? '',
|
||||
"senior_photo" => "",
|
||||
"latitude" => $input['latitude'] ?? '',
|
||||
"longitude" => $input['longitude'] ?? '',
|
||||
"emergency_number" => $input['emergency_number'] ?? '15',
|
||||
"fcm_tokens" => [],
|
||||
"contacts" => $input['contacts'] ?? [],
|
||||
"address" => $input['address'] ?? '',
|
||||
"city" => $input['city'] ?? '',
|
||||
"phone_mobile" => $input['phone_mobile'] ?? '',
|
||||
"phone_fixed" => '',
|
||||
"age" => $input['age'] ?? '',
|
||||
"sex" => $input['sex'] ?? 'F',
|
||||
"alerte" => false,
|
||||
];
|
||||
|
||||
// Créer le dossier client
|
||||
$client_dir = "clients/" . ($input['name'] ?? $client_id) . "/";
|
||||
if (!is_dir($client_dir)) {
|
||||
mkdir($client_dir, 0775, true);
|
||||
}
|
||||
|
||||
// Sauvegarder la DB
|
||||
file_put_contents($DB_FILE, json_encode($db, JSON_PRETTY_PRINT));
|
||||
|
||||
// Données de provisioning pour le QR code
|
||||
$provision_data = [
|
||||
"client_id" => $input['name'] ?? $client_id,
|
||||
"token" => $token,
|
||||
"site_number" => $site_number,
|
||||
"server" => "57.128.74.87",
|
||||
];
|
||||
|
||||
// Écrire la demande de firewall dans une file d'attente
|
||||
$fw_queue = "/var/www/lucas/firewall_queue.txt";
|
||||
$fw_cmd = "ufw allow " . $base_port . ":" . ($base_port + 9) . "/tcp comment 'Site $site_number - $client_id'";
|
||||
file_put_contents($fw_queue, $fw_cmd . "\n", FILE_APPEND);
|
||||
|
||||
// Réponse
|
||||
echo json_encode([
|
||||
"success" => true,
|
||||
"status" => "provisioned",
|
||||
"client_id" => $input['name'] ?? $client_id,
|
||||
"token" => $token,
|
||||
"site_number" => $site_number,
|
||||
"base_port" => $base_port,
|
||||
"port_range" => $base_port . "-" . ($base_port + 9),
|
||||
"provision_qr_data" => json_encode($provision_data),
|
||||
"firewall_queued" => true,
|
||||
"message" => "Client provisionné. Ports $base_port-" . ($base_port + 9) . " en attente d'ouverture firewall.",
|
||||
], JSON_PRETTY_PRINT);
|
||||
?>
|
||||
Reference in New Issue
Block a user