Code of Conduct
Is there an existing issue for this?
GLPI Version
11.0.8
Plugin version
1.4.2
Bug description
Dashboard/question extraction is broken against current Metabase API versions. Several response fields the plugin reads under their old names were renamed by Metabase, and a newer native-question format ("MBQL 5") isn't handled at all. As a result:
PluginMetabaseAPIClient::getDashboardCards() returns false for every dashboard (reads ordered_cards, which no longer exists — the API now returns dashcards).
PluginMetabaseAPIClient::getCards('root') never returns questions that are in the root collection (the API returns id: "root" for that collection, but cards in it have collection_id: null — the strict === comparison never matches).
- Extracting a native question created with a current Metabase produces empty/
null SQL and no template tags, because dataset_query.native.query / dataset_query.native.template-tags moved to dataset_query.stages[0].native / dataset_query.stages[0].template-tags in current Metabase versions.
- Card sizes come back empty in dashboard JSON extraction (
sizeX/sizeY renamed to size_x/size_y).
- The "Extract" button in the collection list does nothing when GLPI's
root_doc is empty (default install) — public/metabase.js builds the AJAX URL as root_doc + '/' + GLPI_PLUGINS_PATH.metabase + ..., which becomes //plugins/... and the browser resolves it as a request to a host named plugins instead of a path.
I expected the "Extract questions" feature and dashboard card extraction to work against a current Metabase instance the same way they do with an older one. Instead they silently return nothing (no PHP error, no exception — the methods just return false/empty), which makes it look like there's simply nothing to extract.
I confirmed this is a real, reproducible bug (not a config/environment issue) by calling the affected methods directly against a live Metabase instance with real dashboards, both before and after patching — details and suggested fix below.
Second, more severe bug, also introduced in 1.4.2: upgrading a site that already had an embedded_token configured breaks the embedded dashboard on the Central page entirely with an uncaught exception (Lcobucci\JWT\Signer\InvalidKeyProvided: "Key cannot be empty"). 1.4.2 added embedded_token to secured_configs (setup.php) and expects it to be sodium-encrypted, but the migration meant to encrypt existing plain-text tokens on upgrade doesn't actually do that — see config.class.php::install():
// Encrypt embedded_token, previously stored in plain text
if (!array_key_exists('is_embedded_token_encrypted', $current_config) || !$current_config['is_embedded_token_encrypted']) {
if (!empty($current_config['embedded_token'])) {
Config::setConfigurationValues('plugin:metabase', [
'embedded_token' => $current_config['embedded_token'], // just rewrites the same plain-text value, never actually encrypts it
]);
}
Config::setConfigurationValues('plugin:metabase', ['is_embedded_token_encrypted' => 1]); // ...but marks it as encrypted anyway
}
dashboard.class.php then unconditionally does (new GLPIKey())->decrypt($config['embedded_token']) — decrypting a value that was never actually encrypted returns an empty string, which the JWT signer rejects. Any site that had embedded_token set before upgrading to 1.4.2 hits this immediately on the Central dashboard tab (fresh installs without a pre-existing token aren't affected).
Relevant log output
For the extraction bugs: none — no PHP error or exception, the affected methods simply return false/empty arrays.
For the embedded-dashboard bug:
[2026-08-05 20:44:23] glpi.CRITICAL: *** Uncaught PHP Exception Lcobucci\JWT\Signer\InvalidKeyProvided: "Key cannot be empty" at InvalidKeyProvided.php line 39
### Page URL
Setup > Metabase > (collection extraction dialog / dashboard "Extract questions" button) — not a public-facing page, it's the plugin's own admin UI.
### Steps To reproduce
**Extraction bugs:**
1. With Metabase plugin 1.4.2 configured against a current Metabase instance (reproduced on both v0.62 and v0.63.2)
2. Create a native SQL question and put it on a dashboard in Metabase (or use one in the root collection)
3. In GLPI, go to Setup > Metabase and try to extract that dashboard's questions / the root collection's questions
4. See empty result — no cards/questions come back, no error is shown anywhere
**Embedded dashboard bug:**
1. Have Metabase plugin working on an older version with `embedded_token` already configured (plain text, pre-`1.4.2`)
2. Update the plugin to `1.4.2`
3. Go to GLPI Central, open the "Painel Metabase" / embedded dashboard tab
4. See "Ocorreu um erro inesperado" / uncaught `InvalidKeyProvided` exception in `php-errors.log`
### Your GLPI setup information
GLPI version: 11.0.8
PHP version: 8.2.32 (cli, NTS)
Web server: Apache/2.4.68 (Debian)
Database: MariaDB 10.11.14
(Full System tab output from Setup > General > System can be attached if needed.)
Anything else?
Suggested fix — simple ?? fallbacks, kept backward-compatible with older Metabase versions:
// apiclient.class.php::getDashboardCards()
public function getDashboardCards($id)
{
$data = $this->httpQuery("dashboard/$id", [], 'GET');
return $data['dashcards'] ?? $data['ordered_cards'] ?? false;
}
// apiclient.class.php::getCards()
$normalized_id = $collection_id === 'root' ? null : $collection_id;
$cards = array_filter($cards, fn($card) => is_array($card)
&& array_key_exists('collection_id', $card)
&& $normalized_id === $card['collection_id']);
// config.class.php, wherever dataset_query.native.* / card sizes are read
$sql = $card['dataset_query']['native']['query']
?? $card['dataset_query']['stages'][0]['native'];
$size_x = $card['sizeX'] ?? $card['size_x'];
For the embedded-dashboard bug, the migration needs to actually encrypt the value instead of just flipping the flag, e.g.:
// config.class.php::install(), embedded_token migration block
if (!empty($current_config['embedded_token'])) {
$current_config['embedded_token'] = (new GLPIKey())->encrypt($current_config['embedded_token']);
Config::setConfigurationValues('plugin:metabase', [
'embedded_token' => $current_config['embedded_token'],
]);
}
(mirrors what the password migration a few lines above already does correctly.)
I have a working patch applying all of this cleanly on top of 1.4.2 (tested end-to-end against a live Metabase v0.63.2 instance with real dashboards — both the extraction features and the embedded dashboard) if it's useful as a starting point for a PR — happy to open one if that's welcome.
Code of Conduct
Is there an existing issue for this?
GLPI Version
11.0.8
Plugin version
1.4.2
Bug description
Dashboard/question extraction is broken against current Metabase API versions. Several response fields the plugin reads under their old names were renamed by Metabase, and a newer native-question format ("MBQL 5") isn't handled at all. As a result:
PluginMetabaseAPIClient::getDashboardCards()returnsfalsefor every dashboard (readsordered_cards, which no longer exists — the API now returnsdashcards).PluginMetabaseAPIClient::getCards('root')never returns questions that are in the root collection (the API returnsid: "root"for that collection, but cards in it havecollection_id: null— the strict===comparison never matches).nullSQL and no template tags, becausedataset_query.native.query/dataset_query.native.template-tagsmoved todataset_query.stages[0].native/dataset_query.stages[0].template-tagsin current Metabase versions.sizeX/sizeYrenamed tosize_x/size_y).root_docis empty (default install) —public/metabase.jsbuilds the AJAX URL asroot_doc + '/' + GLPI_PLUGINS_PATH.metabase + ..., which becomes//plugins/...and the browser resolves it as a request to a host namedpluginsinstead of a path.I expected the "Extract questions" feature and dashboard card extraction to work against a current Metabase instance the same way they do with an older one. Instead they silently return nothing (no PHP error, no exception — the methods just return
false/empty), which makes it look like there's simply nothing to extract.I confirmed this is a real, reproducible bug (not a config/environment issue) by calling the affected methods directly against a live Metabase instance with real dashboards, both before and after patching — details and suggested fix below.
Second, more severe bug, also introduced in
1.4.2: upgrading a site that already had anembedded_tokenconfigured breaks the embedded dashboard on the Central page entirely with an uncaught exception (Lcobucci\JWT\Signer\InvalidKeyProvided: "Key cannot be empty").1.4.2addedembedded_tokentosecured_configs(setup.php) and expects it to be sodium-encrypted, but the migration meant to encrypt existing plain-text tokens on upgrade doesn't actually do that — seeconfig.class.php::install():dashboard.class.phpthen unconditionally does(new GLPIKey())->decrypt($config['embedded_token'])— decrypting a value that was never actually encrypted returns an empty string, which the JWT signer rejects. Any site that hadembedded_tokenset before upgrading to1.4.2hits this immediately on the Central dashboard tab (fresh installs without a pre-existing token aren't affected).Relevant log output
For the extraction bugs: none — no PHP error or exception, the affected methods simply return
false/empty arrays.For the embedded-dashboard bug:
(Full System tab output from Setup > General > System can be attached if needed.)
Anything else?
Suggested fix — simple
??fallbacks, kept backward-compatible with older Metabase versions:For the embedded-dashboard bug, the migration needs to actually encrypt the value instead of just flipping the flag, e.g.:
(mirrors what the
passwordmigration a few lines above already does correctly.)I have a working patch applying all of this cleanly on top of
1.4.2(tested end-to-end against a live Metabase v0.63.2 instance with real dashboards — both the extraction features and the embedded dashboard) if it's useful as a starting point for a PR — happy to open one if that's welcome.