Files
netconfig/API/classe_api
T
2026-05-22 13:55:01 +02:00

161 lines
5.0 KiB
Plaintext

<?php
declare(strict_types=1);
namespace PluginNetconfig\Api;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
class GlpiApiClient
{
private string $baseUrl;
private string $appToken;
private ?string $sessionToken = null;
private Client $httpClient;
public function __construct(string $baseUrl, string $appToken, string $userToken = null)
{
$this->baseUrl = rtrim($baseUrl, '/');
$this->appToken = $appToken;
$this->httpClient = new Client([
'base_uri' => $this->baseUrl . '/apirest.php/',
'timeout' => 30.0,
'headers' => [
'App-Token' => $this->appToken,
'Content-Type' => 'application/json',
],
]);
if ($userToken) {
$this->loginWithUserToken($userToken);
}
}
/**
* Login con credenziali utente (username + password)
*/
public function login(string $username, string $password): bool
{
try {
$response = $this->httpClient->post('initSession', [
'auth' => [$username, $password],
]);
$data = json_decode($response->getBody(), true);
$this->sessionToken = $data['session_token'] ?? null;
return $this->sessionToken !== null;
} catch (RequestException $e) {
error_log("GLPI API login failed: " . $e->getMessage());
return false;
}
}
/**
* Login con user token (più sicuro, generato in Profilo > API)
*/
public function loginWithUserToken(string $userToken): bool
{
try {
$response = $this->httpClient->post('initSession', [
'headers' => ['User-Token' => $userToken],
]);
$data = json_decode($response->getBody(), true);
$this->sessionToken = $data['session_token'] ?? null;
return $this->sessionToken !== null;
} catch (RequestException $e) {
error_log("GLPI API user-token login failed: " . $e->getMessage());
return false;
}
}
/**
* Logout e distruzione sessione
*/
public function logout(): void
{
if ($this->sessionToken) {
try {
$this->httpClient->delete('killSession', [
'headers' => ['Session-Token' => $this->sessionToken],
]);
} catch (\Throwable $e) {
// Ignora errori in logout
}
$this->sessionToken = null;
}
}
/**
* Esegue una chiamata API con retry automatico su token scaduto
*/
private function request(string $method, string $endpoint, array $data = []): ?array
{
$headers = $this->sessionToken ? ['Session-Token' => $this->sessionToken] : [];
try {
$response = $this->httpClient->request($method, $endpoint, [
'headers' => $headers,
'json' => $data,
]);
return json_decode($response->getBody(), true);
} catch (RequestException $e) {
// Se token scaduto (401), tenta refresh e riprova UNA volta
if ($e->getResponse()?->getStatusCode() === 401 && $this->sessionToken) {
$this->logout();
// Qui potresti ricaricare le credenziali da config/vault e fare re-login
// Per semplicità, lanciamo eccezione
throw new \RuntimeException("GLPI API session expired. Re-authentication required.");
}
throw $e;
}
}
/**
* Ottieni dispositivo di rete per ID
*/
public function getNetworkEquipment(int $id): ?array
{
$result = $this->request('GET', "NetworkEquipment/$id");
return $result && !isset($result[0]['error']) ? $result : null;
}
/**
* Cerca dispositivi per nome/IP (per mapping agent -> GLPI ID)
*/
public function searchNetworkEquipment(string $nameOrIp): array
{
$query = [
'criteria' => [
['field' => 1, 'searchtype' => 'contains', 'value' => $nameOrIp], // name
['OR' => [
['field' => 2, 'searchtype' => 'contains', 'value' => $nameOrIp], // ip
]],
],
'forcedisplay' => [1, 2, 3], // id, name, ip
];
$result = $this->request('GET', 'search/NetworkEquipment', ['criteria' => $query]);
return $result['data'] ?? [];
}
/**
* Invia configurazione al plugin (endpoint personalizzato)
*/
public function sendConfig(int $deviceId, string $config, string $agentToken): bool
{
$payload = [
'device_id' => $deviceId,
'config' => $config,
'token' => $agentToken,
'timestamp' => date('c'),
];
$result = $this->request('POST', 'plugin/netconfig/agent', $payload);
return ($result['status'] ?? '') === 'ok';
}
public function __destruct()
{
$this->logout();
}
}