Skip to content

Releases: monta990/gdmsintegration

1.5.0

24 May 06:12

Choose a tag to compare

[1.5.0] — 2026-05-23

Fixed

  • Entity access check on AJAX endpointsalerts.ajax.php, clients.ajax.php, and ports.ajax.php now call Session::haveAccessToEntity() after parsing entities_id. A user with config:READ on entity 1 can no longer query data from entity 2 via ?entities_id=2.
  • php://input capped at 64 KB in firmware.ajax.php — replaced file_get_contents('php://input') with stream_get_contents(..., 65536) in both the upgrade and upgrade_gdms handlers.
  • Missing access control on AJAX endpointsalerts.ajax.php, alerts-dismiss.ajax.php, clients.ajax.php, and ports.ajax.php checked only checkLoginUser(). Any authenticated GLPI user could query GWN alerts, WiFi clients, and WAN port state across all entities. All four now require config:READ.
  • Alert dismiss IDs validatedalerts-dismiss.ajax.php now filters IDs through a preg_match('/^[a-zA-Z0-9_\-]{1,64}$/') whitelist before forwarding to the GWN API. Arbitrary strings are silently dropped.
  • Port modal labels showed "undefined"STR.gateway, STR.dns, STR.wanMac, STR.txrxPkts, STR.linkSpeed, and STR.description were missing from $js_strings in dashboard.php. Gateway, DNS, WAN MAC, TX/RX packets, link speed, and description rows in the port detail modal now display correctly.
  • history_import.php standalone endpoint disabled — the file now returns HTTP 404 immediately; import is handled exclusively by config.form.php which has MIME, size, and transaction controls.
  • ensureSchema() runs once per PHP process — a static flag prevents the ~40 ALTER TABLE statements from executing on every dashboard page load under concurrent PHP-FPM workers.
  • XLSX upload size limit configurable — the 5 MB cap is now a setting ("Max upload size") in the History Import card (1–50 MB, default 5 MB). Stored in max_xlsx_size_mb config column.
  • TLS certificate verification restoredCURLOPT_SSL_VERIFYPEER was false in gwnGetFirmwareVersionsBatch() while the other three curl calls used true. All GWN Cloud calls now verify the server certificate.
  • Firmware download URL restricted to Grandstream CDNupgrade_gdms now validates the downloadUrl host against an allowlist (firmware.grandstream.com, fw.gdms.cloud). Arbitrary URLs including RFC-1918 addresses and file:// URIs are rejected before being forwarded to GDMS.
  • Offline tickets now open for devices already offline when category flag is enabled — the sync previously only created offline tickets on an online→offline transition; devices that were already offline when tickets_phone / tickets_router / etc. was enabled never received a ticket. The check now also runs on offline→offline, relying on the existing duplicate guard inside createOfflineTicket() to avoid double tickets.
  • History import wrapped in DB transaction — INSERT loop now runs inside START TRANSACTION / COMMIT; any failure triggers ROLLBACK, leaving the history table in a consistent state.
  • Rate limiting moved to database — reboot and factory-reset cooldowns are now stored in last_reboot_at / last_factory_reset_at columns on the device row instead of $_SESSION. Cooldown survives session reset, new browser tabs, and direct curl calls.
  • API tokens redacted from log filesaccess_token, token, and Authorization query-string values are replaced with [REDACTED] before being written to gdmsintegration.log, even in verbose/debug mode.
  • visnetwork_url escaped in Twig — changed from |raw to |escape('html_attr') in dashboard.html.twig. (defence-in-depth)
  • Factory reset requires config:PURGE — previously required only config:UPDATE (standard technician right). Now requires the higher PURGE right, restricting factory reset to administrators and profiles explicitly granted that permission.
  • Server-side rate limiting for destructive device actions — reboot is limited to once per 60 s per device per user session; factory reset is limited to once per 5 min per device per user session. Bypass via direct POST is blocked server-side regardless of the frontend confirmation UI.
  • File upload MIME validation — history XLSX and config JSON uploads now verify the actual file magic bytes via finfo(FILEINFO_MIME_TYPE) instead of trusting the client-supplied Content-Type. Rejects non-XLSX files uploaded to the history importer and non-JSON files uploaded to the config importer before any parsing occurs.

Removed

  • Webhook receiver removedfront/webhook.php and all related infrastructure (stateless path registration, webhook_secret config field, HMAC validation logic, locale strings) have been removed. The cron sync and dashboard manual sync provide equivalent coverage without exposing an unauthenticated HTTP endpoint. The webhook_secret database column is dropped automatically on first load via ensureSchema().

1.4.3

22 May 07:08
198edd0

Choose a tag to compare

[1.4.3] — 2026-05-22

Fixed

  • Accessibility warnings — label/input associations — all <label> elements in the config form now have for attributes pointing to their corresponding field id. Inputs that lacked an id received one. The Entity dropdown heading was changed from <label> to <p> (no single target field). Eliminates 16 browser accessibility warnings on the config page.
  • Accessibility warnings — dashboard search field — the Vue filter bar search <input> now has id="gdms-device-search" and name="search", resolving the "form field has neither id nor name" browser warning.
  • Accessibility warnings — firmware schedule label — the "Schedule for" label in the firmware upgrade modal now has for="gdmsFwDatetime", linking it to the flatpickr date input.

Improved

  • vis-network updated to 10.1.0.

1.4.2

20 May 05:22

Choose a tag to compare

[1.4.2] — 2026-05-19

Added

  • Factory reset for UC phones/ATAs — the phone SIP detail modal now includes a Factory Reset button (before the Reboot button) with a prominent danger alert explaining the consequences. The button requires two clicks (second click turns yellow "I understand — Reset now", auto-reverts in 6 s) to prevent accidental execution. Calls GDMS task/add with taskType=2. Requires config:UPDATE permission. -BETA - THIS FEATURE MAY FAIL.

Fixed

  • Firmware scheduler date/time picker did not update the field after selectionaltInput: true combined with wrap: true caused flatpickr to insert a hidden secondary input inside the Bootstrap btn-group, leaving the visible field blank after picking a date or time. Removed altInput/altFormat; the original data-input field now updates directly with d/m/Y H:i format. Schedule submission is unaffected (reads selectedDates[0]) - BETA - THIS FEATURE MAY FAIL.
  • GWN device disappears intermittently — when the GWN Cloud ap/list request for one network timed out, the plugin treated that network as having zero devices and deleted their state records, causing devices to vanish from the dashboard until the next successful sync. gwnGetDevices() now returns false on any per-network failure, which triggers the existing removal guard so no state is deleted during a partial API failure.
  • Restart devices — an immediate execution task is scheduled to restart the device. -BETA - THIS FEATURE MAY FAIL.
  • JSON Export — now export and import correctly.

Improved

  • Firmware modal — CDN-only devices show "Latest available" — phones/ATAs (GRP, HT, WP, etc.) have no firmware version page on grandstream.com; the modal now displays "Latest available" instead of the raw CDN filename. Version sent to GDMS task is left blank when only a download URL is known, avoiding the previous incorrect behaviour of sending the current firmware version as the target.
  • Firmware check_all — parallel GWN version fetchcheck_all now fetches firmware versions for all GWN networks in a single parallelised curl_multi batch instead of one sequential HTTP call per network, matching the behaviour of the existing check action. Reduces latency proportionally to the number of configured networks.
  • Twig + Vue 3 frontendfront/dashboard.php and front/config.form.php converted to standalone Twig templates (templates/dashboard.html.twig, templates/config_form.html.twig). PHP data layer and HTML presentation fully separated. Vue 3 filter bar replaces inline JS DOM manipulation. Compatible with GLPI 11 and GLPI 12.

1.4.1

13 May 06:50
9f8332b

Choose a tag to compare

[1.4.1] — 2026-05-13

Added

  • History import from Excel — new card in Configuration lets operators restore availability history from a previously exported gdms_history_*.xlsx file (renamed from gdms_disponibilidad_*.xlsx). Device-days that already have data are skipped (non-destructive). Each imported day generates 100 synthetic records spaced ~14 min apart so the daily online/total ratio exactly reconstructs the original percentage (±1 %).
  • Plugin configuration export — download all plugin settings as a JSON backup file. An optional checkbox includes API credentials (username, keys, secrets) in the export for full migration scenarios.
  • Plugin configuration import — restore settings from a previously exported JSON backup. Credentials are only written when the source file explicitly included them; all other imports leave stored secrets unchanged.
  • Firmware modal — device name and private IP — modal header now shows the device name and its private IP (clickable link) so the operator knows which device they are updating without scrolling the table.
  • Firmware modal — copy MAC with one click — clicking the MAC code in the modal copies it to the clipboard; shows a brief "Copied!" confirmation.
  • Firmware modal — firmware downloads link — info note now includes a direct link to grandstream.com/support/firmware that opens in a new tab.
  • Firmware modal — beta-only devices show selectable version — for GDMS-managed phones whose firmware page only has a beta channel (GRP260x, WP8x6, HT8xxV2, GCC6xx), the available version is now shown as a pre-selected radio button instead of a text note, making the scheduled version clearly visible.
  • Topology — phone → PBX edges — phones are now connected to their UCM/GCC PBX in the vis-network topology graph based on shared network name; lines are drawn automatically with no extra queries.
  • Topology — localised node status — node tooltips now use the active UI language for "Online"/"Offline" instead of hard-coded English.
  • Firmware update in progress indicator — after a successful upgrade request the firmware version cell shows "Updating…" instead of going blank; reverts to the real version on the next sync.

Fixed

  • CSRF double-upgrade failure — second firmware upgrade in the same session failed with CSRF error. Root cause: GLPI 11 consumes single-use form tokens but preserves X-Glpi-Csrf-Token header tokens (preserve_token: true). All firmware upgrade fetches now send X-Requested-With: XMLHttpRequest + X-Glpi-Csrf-Token header; the body token field is removed.

Improved

  • Sync performance — eliminated up to 3 DB round-trips per device: device state is loaded once into an in-process PHP cache (primeCache()) so getState() and saveStateWithNetwork() skip per-device find() calls; existing topology links are pre-loaded into a PHP set so link deduplication is a hash lookup; all history snapshots are flushed in a single bulk INSERT at the end of the loop instead of one per device. Expected reduction: ~35 % fewer queries on a 35-device account.
  • vis-network updated to 10.0.3.

1.4.0

10 May 08:01
6ecfb07

Choose a tag to compare

[1.4.0] — 2026-05-10

Added

  • Phone SIP status dot — phones show a colour-coded 9 px dot in the Ports column (green = SIP registered, red = unregistered; dimmed when offline). Clicking opens a SIP detail modal with: SIP status, extension, site, private IP (clickable), public IP (WHOIS link), last seen, PBX/UCM IP, Do Not Disturb, provisioning sync status + error, scheduled task.
  • Phone SIP dot tooltip — hovering the SIP dot shows a native tooltip: SIP state, extension (if any), Do Not Disturb flag.
  • PBX / UCM in phone modal — SIP modal shows the UCM/GCC device in the same network as a clickable private IP link with device name. Matched by siteName; no extra API call.
  • ATA / HT devices show phone modal — any device whose model prefix matches the phone list (HT, GRP, GXP, GXV, GXW, WP, DP, GHP, GVC, GSC, GDS) renders the SIP dot and modal regardless of GLPI itemtype (Phone or NetworkEquipment).
  • GDMS provisioning fields synced — four new fields from device/list persisted per device: dnd, is_synchronized, sync_failure_msg, scheduled_task.
  • accountStatus → SIP status mappingaccountStatus (1 = registered) now mapped to sip_status; was previously unpopulated.
  • lastTime → last seen fallback — GDMS lastTime string used as last_seen when GWN lastSeen epoch is absent.
  • IPv4/IPv6 display preference — new "Private IP display" config setting (IPv4 preferred by default); fallback to other version when preferred is absent; both shown as clickable links when both present.
  • IPv6 addresses clickable — IPv6 in the Private IP column rendered as http://[addr]/ links (RFC 2732).
  • Correct IPv4/IPv6 routing at syncprivateIp values containing : stored in ipv6 column instead of private_ip.

1.3.8

09 May 07:26
a92e60a

Choose a tag to compare

[1.3.8] — 2026-05-09

Fixed

  • GLPI 11/12 compatibility — replaced removed Html::displayRightError() with throw new \Glpi\Exception\Http\AccessDeniedHttpException() in front/history_export.php; compatible with both GLPI 11 and 12.
  • GLPI 11/12 compatibility — replaced non-existent Html::forbidden() with throw new \Glpi\Exception\Http\AccessDeniedHttpException() in front/dashboard.php; method never existed in either GLPI version.
  • GLPI 12 compatibilityHooks::CSRF_COMPLIANT registration in setup.php now guarded with defined() check; constant was removed in GLPI 12 causing a PHP fatal error on plugin load.
  • GLPI 12 compatibility — replaced $DB->doQueryOrDie() with $DB->doQuery() in setup.php (install/uninstall); method was removed in GLPI 12. Both methods throw on error so behavior is identical across versions.
  • GLPI 11/12 compatibility — fixed $rightname PHP compile error; GLPI 12 added string type to CommonGLPI::$rightname while GLPI 11 leaves it untyped — PHP requires child type to match parent exactly. Introduced PluginGdmsintegrationBaseGLPI and PluginGdmsintegrationBaseTM abstract shim classes with conditional type declaration (GLPI_VERSION >= 12); all five plugin classes now extend the appropriate shim and inherit $rightname without redeclaring it.

1.3.7

03 May 21:06
7687f08

Choose a tag to compare

[1.3.7] — 2026-05-03

Security - OWASP

  • Credential redaction in debug logs — GWN OAuth token request URL and token response are no longer logged verbatim. Debug output now shows only appID and expires_in, preventing client_secret and access_token from appearing in files/_log/gdmsintegration.log even when verbose mode is enabled. (OWASP A02/A09)
  • Advisory lock queries use escaped identifiersGET_LOCK/RELEASE_LOCK raw SQL queries in the sync engine now call $DB->escape() on the lock name, following defense-in-depth for all raw query parameters. (OWASP A03)
  • Webhook signature mismatch returns 204 — failed HMAC verification no longer returns HTTP 403 (which confirmed the endpoint existed and the signature was checked). Now returns 204 No Content, removing the oracle useful for probing or brute-forcing. (OWASP A07)
  • Webhook GET handler removed — the unauthenticated GET health-check response that disclosed plugin name and endpoint path has been removed. Non-POST requests now receive 405 with no body. (OWASP A05)
  • Webhook payload logging scoped — log line now records only entity, mac, and status rather than up to 500 chars of raw JSON payload. (OWASP A09)
  • Firmware endpoint requires READ rightfirmware.ajax.php read actions (check, check_all) now require Session::checkRight('config', READ) instead of a plain session check, preventing any authenticated GLPI user from querying firmware status of all devices. (OWASP A01)

1.3.6

30 Apr 07:23
adf48f5

Choose a tag to compare

[1.3.6] — 2026-04-30

Added

  • Ticket creation by device type — new "Ticket creation by device type" config section with five independent toggles: IP Phones (GRP/GXP/GXV/WP), Routers (GWN7001/7002/7003), Switches (GWN7800/GSS), Access Points (GWN76xx), and IP PBX / UCM (UCM/GCC). All enabled by default for backward compatibility. Disabling a toggle suppresses offline incident tickets for that device category; ticket resolution remains unaffected so existing open tickets still auto-close. Translated in es_MX, fr_FR, de_DE.
  • GLPI asset name on tickets — offline and WAN-down ticket subjects now use the GLPI asset name when the device is already registered in GLPI. Falls back to the GDMS cloud name for unregistered devices.
  • Private IP in offline tickets — offline incident ticket body now includes the device's private/LAN IP alongside the public IP.
  • Dashboard UX improvements — device name and Critical SLA banner links now open in a new browser tab; private IP cell is clickable and opens the device's admin page (http://<private_ip>) in a new tab; model, MAC, and serial cells copy their value to the clipboard on click (brief ✓ flash confirms the copy).

1.3.5

23 Apr 22:58
6a47781

Choose a tag to compare

[1.3.5] — 2026-04-23

Added

  • Disable WAN port tickets — new config toggle wan_tickets_enabled (enabled by default). When turned off, the plugin stops opening incident tickets for WAN link-down and no-internet events entirely. Debounce timers and port state tracking continue normally so the feature can be re-enabled at any time without side-effects. Resolved tickets are still closed automatically. Active regardless of sync method (cron or manual).

1.3.4

23 Apr 05:28
1c665ce

Choose a tag to compare

[1.3.4] — 2026-04-22

Fixed

  • False WAN tickets on all ports — WAN port ticket loop iterated every port in wan_ports_json including LAN ports (role=0). LAN link-down events now correctly skipped via role != 1 guard at the top of the loop.
  • Non-router devices treated as routers$is_gwn_router used !$is_gwn_switch as the only exclusion, so APs (GWN76xx) and any NetworkEquipment with a networkId could enter the router WAN port code path. Now uses explicit preg_match('/^GWN700[123]/i', $gdms_model) — only GWN7001/7002/7003 trigger WAN port monitoring.

Added

  • Asset user as ticket requester — when a GLPI asset has a user assigned (users_id), that user is set as requester on auto-generated offline and WAN-down tickets. Takes priority over the entity-level default requester configured in plugin settings.
  • WAN no-internet debounce — new config option wan_debounce_seconds (default 300 s, range 0–3600). When connectStatus drops to 0 (internet lost) the plugin waits the configured number of seconds before opening a ticket. Prevents false alerts caused by transient high-latency events that momentarily fail the router's internet reachability test. Physical link-down events (Case A) are never debounced. Timer is stored inside wan_ports_json and survives across sync cycles. Setting to 0 restores the previous immediate-open behaviour. Translated in es_MX, fr_FR, de_DE.