• v1.6.15 c6d36ebf7f

    emitlinks released this 2026-10-22 09:26:21 +00:00 | 49 commits to main since this release

    AirWatch Sync 1.6.15

    Correction : résultat du test/dry run affiché deux fois + détection des appareils par numéro de série

    Doublon d'affichage du test de connexion / dry run

    Symptôme : lors d'un test de connexion ou d'un dry run, le résultat s'affichait deux fois.

    Cause : les boutons de l'onglet Synchronisation étaient enregistrés deux fois dans le JS — une fois par écouteur individuel (addEventListener sur chaque bouton) et une seconde fois par un bloc forEach legacy qui ré-enregistrait les trois mêmes boutons. Chaque clic envoyait donc deux requêtes et le résultat était imprimé deux fois.

    Correction : un seul écouteur par bouton + une garde anti double-clic (un clic pendant une requête en cours est ignoré).

    Appareils AirWatch non détectés par numéro de série

    Symptôme : les appareils existaient dans la console Workspace ONE UEM mais n'étaient jamais liés aux assets GLPI existants — ils étaient recréés en doublon (ou perdus si le mapping de champ ne correspondait pas).

    Cause : la recherche d'asset existant comparait uniquement le champ serial de la table du type mappé, avec SerialNumber (puis InternalDeviceIdentifier) seul. En pratique :

    • les assets GLPI portent souvent l'IMEI dans leur numéro de série (téléphones) ;
    • un appareil peut être stocké comme Computer dans GLPI alors que le mapping de plateforme AirWatch le déclare Phone (ou inversement), dans laquelle cas la table cherchée était la mauvaise.

    Correction (SyncEngine::processDevice) : tous les identifiants exposés par AirWatch pour l'appareil (SerialNumber, IMEI, MEID, InternalDeviceIdentifier) sont maintenant comparés, sans distinction de casse, contre les deux tables Computer et Phone (type mappé en premier). L'asset existant est lié — son type prime sur le type calculé — au lieu de créer un doublon. findDeviceBySerial (sens asset → console) utilise la même liste d'identifiants.

    Aucun changement d'interface : mêmes champs de configuration, mêmes endpoints.

    Downloads
  • v1.6.14 a6b7c6e8a9

    emitlinks released this 2026-10-22 08:56:50 +00:00 | 52 commits to main since this release

    AirWatch Sync 1.6.14

    Correction authentification par certificat (CMSURL) — HTTP 401 errorCode 1006

    Symptôme : Could not verify the encrypted message. The data or the url used to sign the message is different from the one provided in the request.

    Cause : la signature CMSURL était calculée sur le chemin canonique en racine majuscule /API/... alors que la requête était envoyée vers /api/... (minuscules). La console Workspace ONE UEM compare le contenu signé à l'URL telle que demandée, caractère par caractère — le moindre écart de casse provoque le 1006 (le certificat et la structure PKCS#7 étaient déjà valides).

    Correction : AirWatchClient::canonicalPath() ne fait plus aucune conversion de casse ; la chaîne signée est désormais le chemin absolu exact de l'URL demandée (sans query string), identique caractère par caractère au chemin réellement envoyé. Vérifié contre l'implémentation PowerShell de référence (signature sur $Url.AbsolutePath) : PKCS#7 détaché + attribut PKCS#9 signingTime, contenu signé == chemin demandé.

    Aucun changement d'interface : mêmes champs de configuration, mêmes endpoints.

    Downloads
  • v1.6.13 eba30f924c

    emitlinks released this 2026-10-22 08:03:11 +00:00 | 55 commits to main since this release

    AirWatch Sync 1.6.13

    Corrections installations en sous-répertoire (/glpi/...)

    • Les URLs du plugin (page de config, endpoint de jeton CSRF, lien "recharger cette page") sont désormais dérivées de $CFG_GLPI['root_doc'], calculé par GLPI 11 depuis la requête elle-même. Ancienne logique basée sur SCRIPT_NAME qui vaut /index.php sous le kernel Symfony et perdait le préfixe /glpi/.
    • Fallback conservé pour GLPI 10 (SCRIPT_NAME /front/ ou /plugins/) et gestion des root_doc stockés en URL absolue.
    • Lien asset GLPI de l'onglet "Appareils synchronisés" : utilisait un chemin durci /phone.form.php?id=... qui omettait à la fois /glpi/ et /front/ ; maintenant construit via la racine document GLPI.
    • Select de profil et lien "Modifier" : plus de $_SERVER['PHP_SELF'] (même problème sous GLPI 11).

    État GLPI par défaut : menu déroulant

    • Le champ "État GLPI par défaut pour les appareils enrôlés" est maintenant un menu déroulant alimenté par glpi_states (nom + nom complet), au lieu d'une saisie libre. La valeur stockée reste le nom de l'état, résolu/créé par le moteur de synchronisation.

    Espacement des boutons

    • La barre d'actions du bas (Enregistrer, Tester la connexion, Simulation, Synchroniser) n'est plus collée au bas de la page : marge basse de 24px.
    • Les boutons "Ajouter un profil" / "Ajouter une correspondance" ne sont plus collés aux champs : marge haute de 10px.
    Downloads
  • v1.6.12 bddd208e41

    emitlinks released this 2026-10-22 06:35:07 +00:00 | 56 commits to main since this release

    AirWatch Sync 1.6.12

    Certificat sans saisie de chemin

    • Le certificat client ne se fournit plus par champ de chemin : upload de fichier uniquement (.pfx/.p12, .crt, .pem), le chemin stocké est affiché en lecture seule avec le sujet et la date d'expiration, plus une case pour le retirer.
    • Les fichiers PKCS#12 (.pfx/.p12) sont désormais décodés avec openssl (mot de passe du profil) : sujet et expiration s'affichent correctement.

    Onglet Connexion restructuré

    • Sections regroupées et légendées : Général, Console, API AirWatch, Authentification, Réseau, GLPI, Mappage des champs.
    Downloads
  • v1.6.11 cf7cb029c4

    emitlinks released this 2026-10-21 16:05:45 +00:00 | 57 commits to main since this release

    Post/Redirect/Get on the configuration page: a native (non-JS) form save now redirects to a clean GET URL instead of tripping GLPI 11 CSRF handling. Form actions are absolute and keep the current tab and profile.

    Downloads
  • v1.6.10 190f66ff6c

    emitlinks released this 2026-10-21 12:33:52 +00:00 | 59 commits to main since this release

    1.6.10 — CSRF / redirect fix for the settings page

    Symptom fixed: clicking Save on the plugin settings page redirected to glpi/front/central.php instead of saving.

    Root cause (verified against GLPI 11.0.11): GLPI's AccessErrorListener redirects to front/central.php when three conditions are met at once — a non-AJAX request, a failed CSRF check, and a URL carrying _redirected_from_profile_selector. All plugin forms shared one CSRF token (Session::getNewCSRFToken() reuses the session token), so submitting any one form consumed the token and every later submit on the same page failed the check.

    Changes:

    • Each form now gets its own standalone CSRF token (Session::getNewCSRFToken(true)), so saving one form no longer invalidates the others.
    • The submit handler rewrites form.action to strip _redirected_from_profile_selector, removing the only condition that turns an access error into a redirect to the home page.
    • Submissions remain AJAX (X-Requested-With: XMLHttpRequest + X-Glpi-Csrf-Token), which GLPI validates with preserve_token: true, so repeated saves keep working.
    • On failure the plugin shows an explicit error banner with a reload link instead of falling back to a native submit.

    Important after installing: GLPI marks a plugin as To update whenever its declared version changes. Until you click Mettre à jour in Administration > Plugins, the plugin is deactivated — its hooks are not loaded, the configuration menu is missing and its pages return 404.

    Verified on GLPI 11.0.11 (Docker, Apache 2.4.68): native POST with a fresh token → 200 and the config is written to glpi_plugin_airwatchsync_configs; a native POST with an already-consumed token and the profile-selector flag → 302 to front/central.php (the reported bug); the AJAX path used by the plugin → 200, token preserved, no redirect.

    Downloads
  • v1.6.9 ed13e06ed3

    emitlinks released this 2026-10-20 14:38:15 +00:00 | 60 commits to main since this release

    Fix for instances where GLPI is served from a subdirectory: plugin URLs are now derived from the request path instead of being hardcoded, so the CSRF token endpoint no longer 404s. A failed save now shows an inline error banner instead of falling back to a native submit (which landed on GLPI home with AccessDeniedHttpException).

    Downloads
  • v1.6.8 5a91886c7f

    emitlinks released this 2026-10-20 13:07:54 +00:00 | 61 commits to main since this release

    Fix: GLPI 11 AJAX form submit dropped the submit button from FormData, so save_config / add_mapping / delete_profile never reached the server. Handler now scoped to plugin forms only.

    Downloads
  • v1.6.7 11c87e0b85

    emitlinks released this 2026-10-20 11:58:51 +00:00 | 62 commits to main since this release

    Fixes the settings save button redirecting to the GLPI home page.

    GLPI 11 consumes the CSRF token on every non-AJAX POST. A page restored from the browser cache, a second open tab, or a double click on Enregistrer therefore submits an already-used token, and GLPI answers with a 403 error page instead of saving.

    Every form on the plugin configuration page now fetches a fresh token from sync.php?endpoint=token immediately before submitting.

    Other changes:

    • Configuration and Field mapping shortcuts added on the Appareils AirWatch page.
    • plugin_airwatchsync_upgrade() declared, so a version bump no longer leaves the plugin in the NOTUPDATED state (which hid the settings menu).
    Downloads
  • v1.6.6 a0364fd135

    emitlinks released this 2026-10-20 09:48:31 +00:00 | 63 commits to main since this release

    Fixes fresh-install migration on GLPI 11 (Duplicate column name). Per-entity sync profiles, bidirectional field mappings, CMSURL certificate auth.

    Downloads