MACOEV.Glpi.Client 26.9.1
MACOEV.Glpi.Client
Client .NET per le API REST di GLPI 10+, condiviso fra il portale di ticketing ASL Roma 1 / PTV e il modulo Inventario Semplificato.
Target: net8.0 e net10.0.
Perche' esiste
L'integrazione GLPI viveva dentro l'applicazione Blazor di ticketing, in un unico file da 1188 righe non riusabile da fuori. Questa libreria la estrae e ne sana i difetti strutturali:
| Prima | Adesso |
|---|---|
new HttpClient() a ogni chiamata (~45 volte, alcune non disposte) |
un solo client dalla factory, con pipeline di resilienza |
Sessione Scoped: una per circuito Blazor, mai chiusa |
IGlpiSessionProvider singleton, thread-safe, con scadenza e killSession |
| Nessuna reazione al 401: la sessione scaduta faceva fallire tutto | rinnovo automatico e un solo ritentativo |
Console.WriteLine |
ILogger |
| Termini di ricerca interpolati in query string | GlpiHttpClient.Escape |
| Errori GLPI opachi | GlpiApiException con ErrorCode tipizzato |
Uso
builder.Services.AddGlpiClient(builder.Configuration);
{
"Glpi": {
"BaseUri": "https://glpi.aslroma1.it",
"AppToken": "...",
"UserToken": "...",
"SessionLifetime": "00:20:00"
}
}
Oppure in codice:
builder.Services.AddGlpiClient(options =>
{
options.BaseUri = "https://glpi.aslroma1.it";
options.AppToken = appToken;
options.UserToken = userToken;
});
BaseUri e' la radice dell'istanza GLPI senza /apirest.php.
Nota sulla sessione
Le credenziali sono quelle di un service account: la sessione aperta dal client non e'
quella dell'utente finale. Di conseguenza glpiactiveprofile restituito da initSession
descrive il service account e non e' utilizzabile per autorizzare l'utente applicativo.
Per i ruoli vanno interrogati Group_User / Profile_User sull'utente autenticato.
Modelli
I DTO vivono tutti nel namespace unico Macoev.Glpi.Client.Models, organizzati in cartelle
(Common, Session, Users, Tickets, Dropdowns, Assets, Documents, Knowbase):
un solo using per il consumatore.
I nomi JSON sono il contratto con GLPI e sono coperti da test di contratto
(ModelContractTests): un refuso in un JsonPropertyName non produce errori di
compilazione, quindi la verifica non puo' che essere automatica.
Cosa resta fuori, di proposito
| Non migrato | Perche' |
|---|---|
UserModel.Initials / FullName, DevicesSearchModel.ImageUrl, TicketInputModel.UserInfoContent |
Presentazione: dipendono da tema, logo e lingua dell'applicazione ospite |
TicketInputModel (form completo), TicketInputMoveDetailModel |
Form model con stato UI (recapiti, consensi a tre stati, edificio/piano). La libreria espone il solo TicketInput, che porta i campi che finiscono davvero sul filo |
Glpiactiveprofile, Glpiprofiles, GLPI_SessionModel, AuthenticationModel |
~600 righe senza alcun uso: la proprieta' session che le conteneva e' commentata. Descrivono comunque il service account, non l'utente applicativo |
Sviluppo
dotnet test
Servizi
| Servizio | Copre |
|---|---|
IGlpiUserService |
lettura, provisioning e plugin field degli utenti |
IGlpiTicketService |
creazione, ricerca, follow-up e validazioni |
IGlpiDropdownService |
sedi, entita', categorie ITIL, dropdown dei plugin field |
IGlpiCatalogService |
ricerche a catalogo su ConsumableItem |
IGlpiDocumentService |
allegati dei ticket |
IGlpiKnowbaseService |
articoli della Knowledge Base |
Coprono l'intera superficie del precedente IGLPIHelper (27 metodi). Alcune scelte
sono volutamente conservative, perche' il portale di ticketing in produzione ci si appoggia:
- Tutte e tre le ricerche a catalogo interrogano
ConsumableItem, anche dove il nome del metodo suggerirebbe altri itemtype. E' il comportamento in produzione. CreateTicketAsyncnon solleva se GLPI rifiuta: restituisceId = -1con il motivo inMessage, come si aspetta l'interfaccia utente.GetUserAsyncfiltra per nome esatto dopo la chiamata:searchTextdi GLPI e' una LIKE, quindi "mrossi" restituisce anche "mrossini".SearchUserByUsernameAsynce' mantenuto ma non funziona: su GLPI il criteriofield=1conequalsrestituisce sempre 0 risultati. Vedi il commento sull'interfaccia.
Modulo inventario
IGlpiInventoryService copre censimento singolo e massivo, ricerca per seriale o numero
di inventario, cambio di stato e associazione Item_Ticket.
IGlpiPluginFieldsService legge e scrive i campi dei container del plugin Fields.
Gli id delle searchoption non sono mai costanti in questi due servizi: vengono risolti
a runtime dal catalogo, perche' il plugin Fields li rinumera a ogni campo aggiunto a un
container e serial non ha lo stesso id su tutti gli itemtype.
Verificare la configurazione GLPI
export GLPI_URL=https://glpi-test.aslroma1.it
export GLPI_APP_TOKEN=...
export GLPI_USER_TOKEN=...
python3 tools/verifica-glpi.py
Controlla diritti sugli itemtype, anagrafiche popolate, presenza dei campi Fields attesi e
dei gruppi dei ruoli. Con --write esegue anche creazione asset, scrittura dei campi e
Item_Ticket. Non cancella nulla: gli elementi di prova creati vengono elencati a fine
esecuzione. Esce con codice diverso da zero se qualche controllo fallisce, quindi e'
utilizzabile come gate prima dell'avvio dello sviluppo.
Rilascio
La pubblicazione e' automatica su GitHub Actions ed e' legata al tag, non al branch:
git tag v26.8.1 && git push origin v26.8.1
Il workflow publish.yml ricava la versione dal tag (v26.8.1 -> 26.8.1), la inietta con
-p:Version=, esegue i test, impacchetta e pubblica sul feed. Richiede il secret di repository
NUGET_FEED_API_KEY. In alternativa si puo' lanciare a mano da Actions > Publish NuGet >
Run workflow indicando la versione.
Versionamento YY.M.patch.build, coerente con gli altri pacchetti MACOEV.
Attenzione alla normalizzazione NuGet: una quarta cifra a zero viene rimossa, quindi
26.8.1.0viene pubblicato come26.8.1. Conviene taggare direttamente nella forma normalizzata, per non avere tag e pacchetto con nomi diversi.
Directory.Build.targets allinea AssemblyVersion e FileVersion alla Version finale,
qualunque sia la sua provenienza.
No packages depend on MACOEV.Glpi.Client.
.NET 10.0
- Microsoft.Extensions.Http.Resilience (>= 10.9.0)
- Microsoft.Extensions.Options.DataAnnotations (>= 10.0.11)
.NET 8.0
- Microsoft.Extensions.Http.Resilience (>= 10.9.0)
- Microsoft.Extensions.Options.DataAnnotations (>= 10.0.11)
| Version | Downloads | Last updated |
|---|---|---|
| 26.14.0 | 9 | 10/20/2026 |
| 26.13.0 | 6 | 10/08/2026 |
| 26.12.1 | 5 | 10/07/2026 |
| 26.12.0 | 6 | 09/29/2026 |
| 26.11.1 | 3 | 09/28/2026 |
| 26.11.0 | 14 | 09/09/2026 |
| 26.10.1 | 1 | 09/08/2026 |
| 26.9.2 | 1 | 09/08/2026 |
| 26.9.1 | 2 | 09/08/2026 |
| 26.9.0 | 0 | 09/08/2026 |
| 26.8.9 | 1 | 09/03/2026 |
| 26.8.8 | 2 | 09/02/2026 |
| 26.8.7 | 0 | 09/02/2026 |
| 26.8.6 | 2 | 08/27/2026 |
| 26.8.5 | 2 | 08/27/2026 |
| 26.8.4 | 1 | 08/26/2026 |
| 26.8.3 | 1 | 08/26/2026 |
| 26.8.2 | 1 | 08/26/2026 |
| 26.8.1.5 | 0 | 08/26/2026 |