Intégration de Saiku
Le Web Component <saiku-embed/> permet d’intégrer une requête
Saiku enregistrée ou un dashboard dans n’importe quelle page
HTML — votre site marketing, un article de blog, un portail
client, un wiki, ou un dashboard React / Vue. Le même élément
personnalisé fonctionne dans tous les hôtes : JSX React,
templates Vue, Svelte, HTML pur.
C’est un véritable Web Component, pas un wrapper de framework, donc la page hôte n’a besoin de rien savoir sur les rouages internes de Saiku.
Installation
Deux façons équivalentes de charger le bundle. Choisissez celle qui convient à votre page hôte.
Aucune étape de build — pointez une balise <script> vers le
bundle que votre Saiku sert déjà :
<script src="https://YOUR-WORKSPACE.saiku.bi/ui/saiku-embed.js"></script>Le téléchargement pèse environ 213 Ko gzippés. Les navigateurs le mettent en cache, donc la deuxième page sur la même origine l’obtient instantanément.
Pour les projets React / Vue / SPA qui bundlent leur propre JS :
npm install @concepttocloud/saiku-embedimport "@concepttocloud/saiku-embed";L’import a pour effet de bord d’enregistrer la balise
saiku-embed globalement — pas de configuration
supplémentaire. La version npm suit la version Saiku une à
une.
Un exemple concret
L’intégration minimale viable — une requête enregistrée, rendue sous forme de tableau :
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" token="tx-..." path="homes/admin/Examples/Trend.saiku" height="400px"></saiku-embed>Les trois attributs porteurs sont server (origine de votre
Saiku), path (chemin de dépôt de la requête enregistrée) et
token (le jeton d’intégration — voir Création d’un
jeton ci-dessous). Tout le reste a des
valeurs par défaut sensées.
Création d’un jeton
Les jetons sont créés par un utilisateur authentifié qui peut lire la ressource. Le jeton est opaque et limité : il accorde un accès en lecture seule à une requête enregistrée ou un dashboard, expire après le TTL que vous spécifiez, et peut être révoqué à tout moment.
curl -X POST 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/tokens' \ -u admin:admin \ -H 'Content-Type: application/json' \ -d '{ "resourceKind": "query", "resourcePath": "homes/admin/Examples/Trend.saiku", "ttlHours": 72, "label": "Marketing landing page" }'
# Response:# {# "status": "OK",# "token": "tx-...",# "resourceKind": "query",# "resourcePath": "homes/admin/Examples/Trend.saiku",# "expiresAt": 1739102400000# }Collez le token dans <saiku-embed token="..."> de votre page
hôte.
Bornes du TTL. Par défaut 72 heures. Maximum 30 jours (720 heures). Un TTL court est la valeur par défaut la plus sûre pour un jeton qui traverse des pages hôtes arbitraires.
Limite par utilisateur. Chaque utilisateur peut détenir jusqu’à 200 jetons actifs à la fois. Révoquez les jetons inutilisés pour libérer du budget.
Lister vos jetons
curl 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/tokens' \ -u admin:adminLes admins peuvent lister tous les jetons du système avec
?all=true.
Révoquer un jeton
curl -X DELETE 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/tokens/<token>' \ -u admin:adminLa révocation prend effet à la toute prochaine requête — il n’y a pas de session invitée à détourner.
Intégrations publiques (anonymes)
Si une ressource doit être lisible sans jeton — un graphique public sur votre page d’accueil, un dashboard ouvert sur un blog — basculez-la en intégration publique :
curl -X POST 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/public' \ -u admin:admin \ -H 'Content-Type: application/json' \ -d '{ "resourceKind": "query", "resourcePath": "shared/public-chart.saiku", "label": "Homepage chart" }'La page hôte omet alors complètement le jeton :
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" path="shared/public-chart.saiku" render="chart"></saiku-embed>Lister + révoquer les autorisations publiques
# List your public grantscurl 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/public' \ -u admin:admin
# Revokecurl -X DELETE 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/public?kind=query&path=shared/public-chart.saiku' \ -u admin:adminRéférence des attributs
| Attribut | Défaut | Notes |
|---|---|---|
server | requis | Origine de votre launcher Saiku, par ex. https://YOUR-WORKSPACE.saiku.bi |
path | requis | Chemin de dépôt. Se termine par .saiku pour les requêtes, .saikudash pour les dashboards |
kind | query | query ou dashboard |
token | (aucun) | Jeton d’intégration de POST /saiku/api/embed/tokens. Omettre pour les lectures publiques anonymes |
render | table | Pour kind="query" : table ou chart |
mode | bar | Pour render="chart" : bar, line ou pie |
height | 400px | Hauteur CSS (une min-height sur la surface rendue) |
Les attributs sont réactifs — le composant se re-rend dès que l’un d’eux change. Dans React, Vue ou Svelte, lier un état à ces props fonctionne directement.
Exemples
Requête enregistrée sous forme de tableau
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" token="tx-..." path="homes/admin/Examples/Trend.saiku"></saiku-embed>Requête enregistrée sous forme de graphique
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" token="tx-..." path="homes/admin/Examples/Sales.saiku" render="chart" mode="bar" height="500px"></saiku-embed>Modes de graphique :
bar(par défaut) — barres catégorielles ; la première colonne non numérique est la catégorie, chaque colonne numérique devient sa propre sérieline— même disposition, séries en lignepie— première colonne numérique seulement ; retombe sur « No numeric series » si le résultat est uniquement textuel
Les info-bulles affichent les chaînes de cellule formatées par
le serveur ($1,234, 12.3%, etc.) afin que la page hôte voie
les mêmes légendes que le workbench Saiku.
Dashboard enregistré
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" token="tx-..." kind="dashboard" path="homes/admin/exec.saikudash" height="700px"></saiku-embed>Le composant récupère la mise en page du dashboard une fois, puis exécute une requête par tuile pour chaque graphique / KPI en parallèle sous la portée de données du propriétaire du dashboard. Types de tuiles en v1 :
| Type de tuile | Ce qui est rendu |
|---|---|
text | Le texte de la tuile, comme un paragraphe |
chart | Un graphique ECharts (utilise tile.chartType comme mode) |
kpi | Un grand chiffre unique issu de la mesure de la tuile |
filter | Ignorée — les widgets de filtre sont réservés au workbench en v1 |
| autre | Placeholder « Unsupported tile » |
Intégration publique anonyme
Lorsque la ressource a une autorisation publique, omettez le jeton :
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" path="shared/public.saiku" render="chart" mode="pie"></saiku-embed>Dans React
import "@concepttocloud/saiku-embed";
export function SalesEmbed({ token }: { token: string }) { return ( <saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" token={token} path="homes/admin/Examples/Sales.saiku" render="chart" mode="line" height="500px" /> );}Dans Vue
<template> <saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" :token="token" path="homes/admin/Examples/Sales.saiku" render="chart" /></template>
<script setup lang="ts">import "@concepttocloud/saiku-embed";defineProps<{ token: string }>();</script>Thématisation
L’intégration s’affiche à l’intérieur d’un
shadow root ouvert,
donc le CSS de la page hôte ne peut pas pénétrer et le CSS de
l’intégration ne peut pas s’échapper. Pour recolorer, définissez
des variables CSS sur le sélecteur saiku-embed de la page
hôte :
saiku-embed { --saiku-embed-fg: #0f172a; --saiku-embed-bg: transparent; --saiku-embed-border: #cbd5e1; --saiku-embed-header-bg: #f1f5f9; --saiku-embed-tile-bg: #ffffff; --saiku-embed-row-hover: #e2e8f0; --saiku-embed-negative: #b91c1c; --saiku-embed-error: #b91c1c; --saiku-embed-muted: #64748b;}Le mode sombre n’est qu’une media query qui bascule les mêmes variables :
@media (prefers-color-scheme: dark) { saiku-embed { --saiku-embed-fg: #f1f5f9; --saiku-embed-bg: #0f172a; --saiku-embed-border: #334155; --saiku-embed-header-bg: #1e293b; --saiku-embed-tile-bg: #1e293b; --saiku-embed-row-hover: #334155; }}Modèle de sécurité
La surface d’intégration est conçue pour des pages hôtes hostiles — votre requête enregistrée pourrait se retrouver sur un site tiers que vous ne contrôlez pas. Les valeurs par défaut reflètent cela.
Les jetons sont opaques, autoritatifs côté serveur, révocables
- Les jetons sont des identifiants aléatoires de 256 bits, encodés en Base64-URL — non devinables.
- Ils ne portent aucune revendication embarquée : le serveur conserve l’enregistrement faisant autorité (type + chemin de ressource, snapshot du propriétaire, expiration, drapeau de révocation) et le consulte à chaque requête. La révocation prend effet à la toute prochaine requête — pas d’attente de type « expiration de signature JWT ».
- Chaque jeton épingle exactement une ressource. Rejouer un
jeton contre n’importe quelle autre ressource (mauvais chemin,
mauvais type, expiré, révoqué) renvoie la même 401 opaque
EMBED_INVALID— les sondages ne peuvent rien énumérer.
Transport uniquement par en-tête
Le jeton voyage dans l’en-tête HTTP X-Saiku-Embed-Token. Nous
n’acceptons délibérément pas les paramètres de requête
?token=… car les paramètres d’URL fuient dans :
- les logs d’accès des servlets
- les logs des proxys frontaux
- l’historique du navigateur
- l’en-tête
Refererenvoyé sur chaque ressource sortante de la page hôte
Le JS fourni lit le jeton depuis votre attribut
<saiku-embed token="…"> et l’envoie comme en-tête à chaque
fetch.
Isolation des cookies inter-origines
L’intégration fait des fetch avec credentials: "omit". Si
l’utilisateur de la page hôte est connecté à Saiku dans un
autre onglet, ce cookie de session ne circule pas avec les
lectures d’intégration. Le jeton EST le seul porteur
d’authentification sur cette surface.
Portée de données du propriétaire
Les jetons et les autorisations publiques capturent un snapshot
de la liste de rôles du propriétaire au moment de la
création / autorisation et exécutent la requête d’intégration
sous cette identité via sessionService.runAs. Une requête
intégrée publiquement qui utilise des filtres injectés par
session s’affiche selon la perspective du donneur, et non sous
le défaut anonyme (vide) — ce que vous avez autorisé au moment
de l’octroi est exactement ce que le public voit.
En-têtes de réponse en défense en profondeur
Chaque réponse d’intégration porte :
X-Content-Type-Options: nosniff— les navigateurs ne doivent pas faire de MIME-sniff sur un corps JSON (qui pourrait porter du HTML de tuile texte ou des légendes de membres) et l’exécuter comme HTMLReferrer-Policy: no-referrer— ne jamais laisser fuir le jeton viaReferersur les ressources sortantesCache-Control: no-store, max-age=0— les données métier intégrées ne sont jamais mises en cache par les proxys ou l’historique du navigateur
Erreurs conviviales
Lorsqu’un fetch échoue (jeton expiré, jeton révoqué, mauvais
chemin, autorisation publique manquante), la page hôte voit un
« This embed is unavailable. » générique — pas le corps brut
EMBED_INVALID. La page hôte est un tiers et n’a pas besoin de
savoir si l’échec était dû à un jeton expiré ou à une révocation.
Taille du bundle
Environ 213 Ko gzippés au moment de la rédaction — runtime d’élément personnalisé Svelte 5 + ECharts (core + bar / line / pie + quatre composants courants, tree-shaken modulaire) + les moteurs de rendu d’intégration. Le bundle est mis en cache de manière agressive par le navigateur ; la deuxième intégration sur la même origine l’obtient instantanément.
Limitations
- Format records uniquement. Le format cellset matriciel n’est pas rendu en v1.
- Les tuiles de filtre sont ignorées sur les dashboards. L’intégration affiche les données telles qu’elles ont été conçues sans barre de filtre interactive.
- Le Markdown dans les tuiles texte s’affiche en texte
brut. Nous ne bundlons pas
markedpour limiter la taille. - Les résultats AI Query (
/ai/query) ne sont pas encore câblés comme source d’intégration. Suivi danssaiku— une PR de suivi ajouterakind="ai".
Voir aussi
- Authentification — création de clés API pour l’accès programmatique à Saiku Cloud (différent des jetons d’intégration)
- MCP — connecter des LLMs à vos cubes