161 lines
5.0 KiB
Plaintext
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();
|
|
}
|
|
}
|