feat: intégration Vision — licence copymail, statut dashboard, clé dans config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jules
2026-05-06 00:36:24 +02:00
parent 01a0fea7cb
commit a0695e019d
3 changed files with 90 additions and 56 deletions

View File

@@ -1,76 +1,65 @@
<?php
/**
* vision.php — Intégration Vision (licence + config)
* CopyMail s'enregistre auprès de Vision et vérifie sa licence.
* À compléter avec l'endpoint et le format exact de l'API Vision.
* vision.php — Intégration Vision (licence)
* API : GET https://vision.copydev.fr/api/license.php?key=<key>&machine_id=<id>&hostname=<host>
*/
define('VISION_API_URL', 'https://vision.copydev.fr/api');
define('VISION_APP_ID', 'copymail');
define('VISION_LICENSE_URL', 'https://vision.copydev.fr/api/license.php');
define('VISION_PRODUCT', 'copymail');
function vision_machine_id(): string {
$id = cfg('vision_machine_id', '');
if (!$id) {
$id = strtolower('copymail-' . bin2hex(random_bytes(6)));
cfg_set('vision_machine_id', $id);
}
return $id;
}
function vision_check(): array {
$keyprog = cfg('vision_keyprog', '');
if (!$keyprog) {
return ['valid' => false, 'msg' => 'Clé Vision non configurée.'];
$key = cfg('vision_license_key', '');
if (!$key) {
return ['valid' => false, 'msg' => 'Licence non configurée.', 'unconfigured' => true];
}
$payload = [
'app' => VISION_APP_ID,
'keyprog' => $keyprog,
'version' => cfg('app_version', '1.0'),
'hostname' => cfg('hostname', gethostname()),
'ip' => $_SERVER['SERVER_ADDR'] ?? '',
];
$url = VISION_LICENSE_URL . '?' . http_build_query([
'key' => $key,
'machine_id' => vision_machine_id(),
'hostname' => cfg('hostname', gethostname()),
]);
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\n",
'content' => json_encode($payload),
'method' => 'GET',
'timeout' => 5,
'ignore_errors' => true,
]]);
$resp = @file_get_contents(VISION_API_URL . '/check', false, $ctx);
$resp = @file_get_contents($url, false, $ctx);
if ($resp === false) {
return ['valid' => true, 'msg' => 'Vision injoignable — mode dégradé.'];
// Vision injoignable — on vérifie le délai offline autorisé
$lastOk = (int)cfg('vision_last_ok', '0');
$timeout = (int)cfg('vision_offline_timeout', '72');
$elapsed = (time() - $lastOk) / 3600;
if ($lastOk && $elapsed < $timeout) {
return ['valid' => true, 'msg' => "Vision injoignable (mode dégradé, {$timeout}h max)", 'degraded' => true];
}
return ['valid' => false, 'msg' => 'Vision injoignable et délai offline dépassé.'];
}
$data = json_decode($resp, true);
return [
'valid' => (bool)($data['valid'] ?? false),
'msg' => $data['message'] ?? '',
'config' => $data['config'] ?? [],
];
}
function vision_push_config(array $config): void {
// Applique la config reçue depuis Vision en BDD
foreach ($config as $key => $value) {
cfg_set($key, $value);
if (!empty($data['valid'])) {
cfg_set('vision_last_ok', (string)time());
cfg_set('vision_offline_timeout', (string)($data['offline_timeout_hours'] ?? 72));
return [
'valid' => true,
'client' => $data['client'] ?? '',
'product' => $data['product'] ?? '',
'expires' => $data['expires_at'] ?? null,
'devices' => $data['max_devices'] ?? 1,
];
}
}
function vision_register(): bool {
$keyprog = cfg('vision_keyprog', '');
if (!$keyprog) return false;
$payload = [
'app' => VISION_APP_ID,
'keyprog' => $keyprog,
'hostname' => cfg('hostname', gethostname()),
'domain' => cfg('domain', ''),
'version' => cfg('app_version', '1.0'),
'accounts' => (int)db()->query('SELECT COUNT(*) FROM accounts WHERE active=1')->fetchColumn(),
];
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\n",
'content' => json_encode($payload),
'timeout' => 5,
'ignore_errors' => true,
]]);
$resp = @file_get_contents(VISION_API_URL . '/register', false, $ctx);
return $resp !== false;
return ['valid' => false, 'msg' => $data['message'] ?? 'Licence invalide.'];
}