• v1.6.37 e8ea7cb0a8

    v1.6.37 Stable

    emitlinks released this 2026-10-28 15:47:34 +00:00 | 1 commits to main since this release

    v1.6.37

    Nom de l’appareil AirWatch (nom composé) : description raccourcie + jetons OS adaptatifs

    Changements

    • Le texte d’aide sous le champ « Nom de l’appareil AirWatch (nom composé) » est raccourci : un seul paragraphe précisant la syntaxe {glpi:…} / {airwatch:…} et le rôle des jetons OS / OSVersion.
    • {airwatch:OS} donne désormais le libellé court de la plateforme : Android, Apple (iOS, iPadOS et macOS) ou Windows.
    • {airwatch:OSVersion} donne le numéro de version seul : la « vraie » version Windows pour les builds (10.0.26100 → 11 24H2), et le préfixe plateforme est retiré quand le payload le contient (iOS 18.4 → 18.4, Android 15 → 15, Windows 11 Pro → 11 Pro).
    • Le même élagage s’applique à l’OS écrit dans GLPI (glpi_items_operatingsystems) : plus de préfixe dupliqué (avant : « Apple iOS iOS 18.4 », « Android Android 15 » ; après : « Apple iOS 18.4 », « Android 15 »).
    • Exemple de modèle {glpi:name} - {airwatch:OS} {airwatch:OSVersion} : « iPhone 15 … - Apple 18.4 », « Pixel 8 … - Android 15 », « … HP EliteBook … - Windows 11 24H2 ».

    Vérifié en e2e sur le conteneur GLPI 11.0.11 de référence

    • dry run : ok:true, erreurs=0, mis à jour=10 ;
    • synchro complète : ok:true, erreurs=0, mis à jour=10, OS écrits=10, matériels=10, réseaux=10 ;
    • noms composés et versions GLPI vérifiés en base (assertion 5/5 appareils) : iPhone 15 → « - Apple 18.4 », Pixel 8 → « - Android 15 », Surface Pro 9 → « - Windows 11 Pro », HP EliteBook → « - Windows 11 24H2 », iPhone SE → « - Apple 17.5.1 ».

    Installation

    Remplacer le contenu de /var/www/html/plugins/airwatchsync/, puis relancer l’installation qui remet le plugin à l’état activé (GLPI passe le plugin en « à mettre à jour » dès que le fichier XML passe à une version supérieure) :

    php bin/console plugin:install airwatchsync --allow-superuser --force -u <admin>
    php bin/console plugin:activate airwatchsync --allow-superuser
    
    Downloads
  • v1.6.36 408f369ed0

    v1.6.36 Stable

    emitlinks released this 2026-10-28 13:44:35 +00:00 | 3 commits to main since this release

    v1.6.36

    Les cartes réseau : un port réseau GLPI par carte AirWatch (DeviceNetworkInfo)

    Chaque carte du tableau DeviceNetworkInfo du payload (fields Name, MACAddress, IPAddress, Vendor, ConnectionType) crée son propre port réseau GLPI :

    • le nom de la carte devient le nom du port,
    • le fournisseur (Vendor) et le type de connexion (ConnectionType) sont inscrits dans le commentaire du port,
    • l'adresse IP de la carte est jointe comme adresse IP du port.

    Quand DeviceNetworkInfo est absent, les champs top-level MacAddress / IPAddress servent de repli (une seule carte). Les MAC en double sont dédoublonnés insensiblement à la casse (la carte primaire listée aussi en top-level ne génère pas un second port).

    L'onglet AirWatch affiche désormais le résumé de toutes les cartes (ex. « Ethernet MAC …, IP …; Wi-Fi MAC …, IP … »).

    Vérifié en e2e sur le conteneur GLPI 11.1 de référence

    • dry run : ok:true, 0 erreur ;
    • synchro complète : ok:true, net_synced=10, 0 erreur ;
    • 12 ports statiques / 10 adresses IP sur les 10 appareils AirWatch (2 ports + 2 IPs sur AW-1004 et AW-1006, 1 port sur chacun des 8 autres, dont 6 portent une IP — les 2 appareils sans IPAddress restent sans IP) ;
    • ports nommés « Ethernet » / « Wi-Fi », comment Vendor: …; Type: …, pas de port dupliqué sur la MAC de la carte primaire.

    Installation

    Remplacer le contenu de /var/www/html/plugins/airwatchsync/ puis : php bin/console plugin:install airwatchsync --allow-superuser --force

    Downloads
  • v1.6.35 8b034a8f2a

    v1.6.35 Stable

    emitlinks released this 2026-10-28 13:16:35 +00:00 | 11 commits to main since this release

    v1.6.35

    Les cartes réseau : un port réseau GLPI par carte AirWatch (DeviceNetworkInfo)

    Chaque carte du tableau DeviceNetworkInfo du payload (fields Name, MACAddress, IPAddress, Vendor, ConnectionType) crée son propre port réseau GLPI :

    • le nom de la carte devient le nom du port,
    • le fournisseur (Vendor) et le type de connexion (ConnectionType) sont inscrits dans le commentaire du port,
    • l'adresse IP de la carte est jointe comme adresse IP du port.

    Quand DeviceNetworkInfo est absent, les champs top-level MacAddress / IPAddress servent de repli (une seule carte). Les MAC en double sont dédoublonnés insensiblement à la casse (la carte primaire listée aussi en top-level ne génère pas un second port).

    L'onglet AirWatch affiche désormais le résumé de toutes les cartes (ex. « Ethernet MAC …, IP …; Wi-Fi MAC …, IP … »).

    Vérifié en e2e sur le conteneur GLPI 11.1 de référence

    • dry run : ok:true, 0 erreur ;
    • synchro complète : ok:true, net_synced=10, 0 erreur ;
    • 12 ports statiques / 12 adresses IP sur les 10 appareils AirWatch (2 ports + 2 IPs sur AW-1004 et AW-1006, 1 port + 1 IP sur les 8 autres) ;
    • ports nommés « Ethernet » / « Wi-Fi », comment Vendor: …; Type: …, pas de port dupliqué sur la MAC de la carte primaire.

    Installation

    Remplacer le contenu de /var/www/html/plugins/airwatchsync/ puis : php bin/console plugin:install airwatchsync --allow-superuser --force

    Downloads
  • v1.6.34 8be4fb7b43

    v1.6.34 Stable

    emitlinks released this 2026-10-28 11:15:30 +00:00 | 15 commits to main since this release

    v1.6.34

    Corrige l'erreur fatale rencontrée sur toutes les synchros (complètes, dry run, depuis la config ou l'onglet AirWatch d'un asset) :

    runDevice(18957): Call to undefined method GlpiPlugin\Airwatchsync\SyncEngine::resolveDeviceNetwork()
    

    netSkipCode() — exécutée pour chaque appareil avant toute écriture — appelait resolveDeviceNetwork() qui n'était jamais définie dans la classe : toute synchro crashait avant de s'exécuter.

    • Ajout de SyncEngine::resolveDeviceNetwork() (extraction unique des données réseau du payload).
    • networkDescription() (onglet AirWatch) et syncNetwork() (sync réseau) basculent dessus.
    • Nouvelle vérification statique tools/static_call_check.php : détecte tout appel $this->méthode() non défini dans le plugin (ce type d'erreur).

    Vérifié en e2e sur le conteneur GLPI 11.1 de référence

    • dry run : ok:true, 0 erreur ;
    • synchro complète : ok:true, hw_synced=10, net_synced=10, 0 erreur, ports réseau (MAC + IP) effectivement écrits dans GLPI ;
    • Call to undefined method absente du log.

    Installation

    Remplacer le contenu de /var/www/html/plugins/airwatchsync/ puis : php bin/console plugin:install airwatchsync --allow-superuser --force

    Downloads
  • v1.6.33 a74fec41a5

    emitlinks released this 2026-10-28 09:26:01 +00:00 | 16 commits to main since this release

    AirWatch Sync 1.6.33

    1.6.33 — les erreurs de synchro affichent la vraie cause (plus de carte GLPI générique)

    Correction (erreur « GLPI a rejeté la requête » sur toutes les synchros, y compris dry run)

    • front/sync.php captait aucune exception : toute erreur PHP (base de
      données, moteur, config) devenait la page d'erreur HTML de GLPI que la
      JS traduisait en « GLPI a rejeté la requête. Recharger la page et
      réessayer. » Le message réel était invisible.
    • L'endpoint renvoie maintenant du JSON ok:false avec le message exact
      de l'exception (et le type d'erreur) ; la page de configuration et le
      panneau de synchro par appareil affichent ce message en rouge.
    • Isolation par appareil : un payload d'appareil corrompu dans AirWatch
      n'interrompt plus toute la synchro (les autres appareils continuent,
      l'erreur est listée dans le résultat).
    • Isolation par profil : un profil en erreur n'empêche plus les autres
      profils de se synchroniser.
    • Toute erreur fatale est tracée dans var/log/.../airwatchsync_error.log
      avec la stack trace complète (pour diagnostics sur votre instance).

    À faire de votre côté

    1. Installer ce zip, rechargement forcé (Ctrl+F5).
    2. Relancer une synchro (dry run ou réelle).
    3. Si une erreur s'affiche, elle contient désormais le message exact :
      envoyez-le pour identifier la cause racine sur votre instance.

    Pensez à recharger la page en force (Ctrl+F5) après l'installation.

    Downloads
  • v1.6.31 7ce6cd3972

    emitlinks released this 2026-10-27 16:18:17 +00:00 | 18 commits to main since this release

    AirWatch Sync 1.6.31

    1.6.31 — la synchro fonctionne même quand un proxy supprime l'en-tête CSRF

    Correction (erreur « GLPI a rejeté la requête » sur la synchro)

    • Un reverse proxy ou un WAF placé devant GLPI peut supprimer les en-têtes
      custom. En requête AJAX (X-Requested-With), GLPI 11 ne valide que
      l'en-tête X-Glpi-Csrf-Token : supprimé par le proxy, chaque POST
      recevait un 403 alors que le jeton du corps de requête était valide.
    • Les appels de synchro (page de configuration et panneau par appareil)
      sont maintenant des POST simples sans flag XHR : GLPI valide alors
      _glpi_csrf_token dans le corps, qui arrive toujours au serveur.
    • Après un 403, un jeton frais est récupéré via endpoint=token et la
      requête est relancée une fois ; si cet endpoint est injoignable, un
      message d'erreur propre s'affiche au lieu d'un TypeError.
    • Le jeton de la page est consommé par un POST simple : il est maintenant
      rafraîchi automatiquement après chaque succès, donc le clic suivant ne
      passe pas par un 403.

    Vérifié

    • Syntaxe PHP (php -l) et JS généré (node --check) des deux pages.
    • Tests logiques Node modélisant le listener CSRF de GLPI 11 + un proxy qui
      supprime l'en-tête : l'ancienne version (1.6.30) reproduit exactement les
      erreurs signalées (403 en AJAX, TypeError dans l'UI) ; la nouvelle version
      réussit dans tous les scénarios (jeton valide, jeton déjà consommé,
      endpoint de jeton mort, avec ou sans proxy).
    • Déployé et testé sur le conteneur de référence GLPI 11 : la page rendue
      n'envoie plus l'en-tête XHR sur les POST de synchro, et le POST avec jeton
      de corps (la requête exacte envoyée par le nouveau JS) reçoit une réponse
      JSON 200.

    Pensez à recharger la page en force (Ctrl+F5) après l'installation.

    Downloads
  • v1.6.30 57e81b1c7f

    emitlinks released this 2026-10-27 13:15:30 +00:00 | 19 commits to main since this release

    AirWatch Sync 1.6.30

    1.6.30 — le résultat de la synchro n'est plus écrasé par une erreur CSRF

    Correction (erreur « Cannot read properties of undefined (reading 'error') »)

    • Quand le jeton CSRF de la page était périmé ou consommé (jetons purgés de
      la session, onglet gardé ouvert, rechargement partiel), GLPI répondait une
      page HTML au premier POST. L'ancienne logique de retry relançait la
      fonction en récursif et perdait la réponse JSON de la synchro : la
      synchro réussissait côté serveur, mais l'interface affichait l'erreur
      JavaScript Cannot read properties of undefined (reading 'error').
    • Le retry est maintenant une simple reprise avec un jeton frais : la
      réponse JSON remonte jusqu'au rendu, et le résultat de la synchro s'affiche
      normalement.

    Message d'échec plus explicite

    • Si la requête échoue encore après le retry (jeton refusé, session expirée,
      erreur serveur), le message « GLPI a rejeté la requête » est conservé et
      accompagné d'un extrait de la réponse du serveur, ce qui permet de voir la
      cause réelle au lieu d'une erreur JavaScript ou d'un message tronqué.

    Appliqué aussi au panneau par appareil

    • Le bouton de synchro d'un asset (DevicePanel) avait exactement le même
      défaut : même correction.

    Vérifié

    • Syntaxe PHP (php -l) et JS généré (node --check) des deux pages.
    • Tests logiques Node avec stub fetch reproduisant le 403 CSRF de GLPI :
      l'ancienne version reproduit l'erreur exacte de l'utilisateur (la synchro
      passe côté serveur mais l'UI affiche le TypeError) ; la nouvelle version
      affiche le résultat dans tous les scénarios (retry réussi, endpoint de
      jeton mort, serveur toujours en erreur).
    Downloads
  • v1.6.29 fafc06ddde

    emitlinks released this 2026-10-27 12:30:24 +00:00 | 21 commits to main since this release

    AirWatch Sync 1.6.29

    1.6.29 — compatibilité GLPI 10 + stockage Apple

    Compatibilité GLPI 10 (correction du fatal qui coupait la synchro)

    • Sur GLPI 10, DB::tableFields() est private : toutes les vérifications
      de colonnes (OS / matériel / réseau) déclenchaient une fatal qui interrompait
      la synchronisation entière avant toute écriture, même avec les options
      activées.
    • Toutes les vérifications passent désormais par DB::listFields()
      (compatible GLPI 10 et 11).

    Système d'exploitation

    • os_sync_computer est activé par défaut pour les nouveaux profils
      (les appareils porteurs d'un agent GLPI restent exclus, l'inventaire agent
      prime).
    • Fallback de stockage Apple : le v0 expose la capacité dans DeviceCapacity
      (pas TotalDiskCapacity) — lu désormais en dernier recours, ce qui
      remplit le disque dur sur les iPhone/iPad.

    Vérifié

    • Conteneur GLPI 10 de référence, payloads v0 réels :
      • Laptop HP EliteBook (Windows) : OS Windows / 11 24H2, RAM 16384 Mo,
        constructeur résolu via le menu déroulant de correspondance.
      • iPhone 14 Pro : Apple iOS / 17.5.1, RAM 2959 Mo, stockage 128 Go
        (DeviceCapacity), port réseau MAC posé.
    • Tests offline : tests/os_test.php et tools/v0_field_test.php — tous
      passants.
    Downloads
  • v1.6.28 bd0c302732

    emitlinks released this 2026-10-27 09:41:55 +00:00 | 25 commits to main since this release

    AirWatch Sync 1.6.28

    1.6.28 — le nom AirWatch (nom composé) suit les règles de l'onglet Correspondance

    Synchronisation du nom d'appareil pilotée par l'onglet Correspondance

    • Le nom AirWatch recomposé (modèle des champs nom + champs nom AirWatch)
      n'était pas synchronisé sur les deux côtés : la console recevait le nom
      écrit sous le champ brut de la correspondance (Name), que la console
      v0 ne lit pas (les appareils v0 portent DeviceFriendlyName) — le nom
      GLPI changeait donc sans que le nom AirWatch ne change.
    • Nouveau : le champ d'écriture est résolu sur le champ de nom réellement
      porté par l'appareil (DeviceFriendlyName > DeviceReportedName > Name),
      ce qui renomme correctement la console sur toutes les API versions.
    • Le sens de la correspondance est maintenant respecté :
      • AirWatch → GLPI : le nom recomposé remplace le nom dans la console
        ET dans GLPI en une seule synchro ;
      • GLPI → AirWatch : le nom GLPI est la source de vérité et arrive
        dans la console via le champ de la correspondance (GLPI n'est jamais
        réécrit) ;
      • Champ désactivé : aucune écriture de nom, ni côté GLPI ni côté
        console.
    • Édition de la correspondance du nom (désactivation, changement de
      direction) sans redémarrage de service.

    Tests

    • Test offline de l'écriture v0 : le champ Name mappé sur un appareil v0
      est écrit sous DeviceFriendlyName (les autres champs passent tels quels).
    • Test de template de nom : correspondance nom activée + modèle de profil →
      une synchro compose et pousse le nom (le dry-run ne pousse rien).
    • E2E complet (8 appareils, GLPI + mock AirWatch) : 4 cas — correspondance
      par défaut (Name) AirWatch → GLPI, Name GLPI → AirWatch, champ
      désactivé, champ explicite DeviceFriendlyName ; chaque cas vérifie que
      le nom a bien été écrit des deux côtés en une seule synchro.
    Downloads
  • v1.6.27 733b1db1a4

    emitlinks released this 2026-10-26 20:50:16 +00:00 | 26 commits to main since this release

    AirWatch Sync 1.6.27

    1.6.27 — synchronisation OS/matériel/réseau, menus de statuts fiables, nom écrit dès la 1re synchro

    Synchronisation de l'OS, du matériel et du réseau

    • Nouveau(s) interrupteur(s) par profil (section « Synchronisation ») : OS, matériel,
      réseau, chacun avec un maître + par type d'appareil (smartphones / tablettes /
      ordinateurs). Colonne de configuration correspondante (migration automatique).
    • OS : Android, Apple iOS, Windows, Apple macOS écrits dans
      glpi_items_operatingsystems (version + architecture). Builds Windows résolus
      (10.0.22621 → 11 22H2, builds inconnus laissés tels quels).
    • Matériel : RAM (Mo), processeur + nombre de cœurs, stockage (Mo) écrits via le
      modèle device GLPI 11 (glpi_items_devicememories / glpi_items_deviceprocessors
      / glpi_items_deviceharddrives), une seule ligne par asset (mise à jour).
    • Réseau : adresse MAC → glpi_networkports (un port par asset, mis à jour) et
      adresse IP → glpi_ipaddresses liée au port. Anciens ports/IP orphelins nettoyés.
    • Jamais d'écriture sur un asset géré par l'agent d'inventaire GLPI ; jamais de
      Phone → Computer ; types de port respectent networkport_types de l'instance.
    • Résumé de synchro : compteurs os_written, hw_synced, net_synced.

    Menus déroulants « Statut → état GLPI » : plus de statuts fantômes

    • Les menus (correspondance statuts + état par défaut du profil) ne listent que les
      états réellement présents dans glpi_states de l'instance.
    • Une cible sauvegardée qui n'existe plus est signalée inline (« cet état n'existe
      plus, il ne sera pas appliqué ») et ignorée par la synchro, sans perte du reste de
      la correspondance.

    Nom d'appareil : écrit dès la 1re synchro

    • Le nom AirWatch recomposé (modèle des champs nom) est écrit dans GLPI pendant le
      même run que la création/mise à jour de l'appareil, au lieu d'attendre la synchro
      suivante ; le dry-run reflète également le nom qui serait écrit.

    Compatibilité GLPI 11

    • DBmysql::insert() retourne désormais true : id récupéré via insertId()
      (8 usages corrigés : ports réseau, RAM/CPU/disque, manufactories, logiciels).
    • DBmysqlIterator::next() est désormais void : itération en foreach
      (nettoyage des anciens ports réseau).

    Divers

    • Mock AirWatch complété : MacAddress, IPAddress, TotalPhysicalMemory,
      ProcessorArchitecture sur les 8 appareils de démonstration.
    • Tests offline : 57 assertions (tests/os_test.php) + tests de correspondance v0.

    Installation

    • Dézipper dans glpi/plugins/, puis activer/mettre à jour le plugin depuis
      Administration → Plugins. La migration ajoute les colonnes os_sync_enabled,
      hw_sync_enabled, net_sync_enabled (valeur par défaut 1 = activé) aux profils
      existants.
    Downloads