commti after qwen start
This commit is contained in:
+160
@@ -0,0 +1,160 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user