Saiku einbetten
Die Web Component <saiku-embed/> ermöglicht es, eine gespeicherte
Saiku-Abfrage oder ein Dashboard in jede HTML-Seite einzubetten — Ihre
Marketing-Site, einen Blog-Beitrag, ein Kundenportal, ein Wiki oder
ein React- / Vue-Dashboard. Dasselbe Custom Element funktioniert in
jedem Host: React JSX, Vue-Templates, Svelte, einfaches HTML.
Es ist eine echte Web Component, kein Framework-Wrapper, sodass die Hostseite nichts über Saiku-Interna wissen muss.
Installation
Zwei gleichwertige Wege, das Bundle zu laden. Wählen Sie, was zu Ihrer Hostseite passt.
Kein Build-Schritt — verweisen Sie ein <script>-Tag auf das
Bundle, das Ihr Saiku bereits ausliefert:
<script src="https://YOUR-WORKSPACE.saiku.bi/ui/saiku-embed.js"></script>Der Download ist etwa 213 KB gzipped. Browser cachen ihn, sodass die zweite Seite auf derselben Origin ihn sofort erhält.
Für React- / Vue- / SPA-Projekte, die ihr eigenes JS bündeln:
npm install @concepttocloud/saiku-embedimport "@concepttocloud/saiku-embed";Der Import hat den Seiteneffekt, das saiku-embed-Tag global zu
registrieren — keine weitere Einrichtung. Der npm-Release folgt
dem Saiku-Release eins zu eins.
Ein durchgängiges Beispiel
Das minimale tragfähige Embed — eine gespeicherte Abfrage, als Tabelle gerendert:
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" token="tx-..." path="homes/admin/Examples/Trend.saiku" height="400px"></saiku-embed>Die drei tragenden Attribute sind server (Origin Ihres Saiku),
path (Repository-Pfad der gespeicherten Abfrage) und token (das
Embed-Token — siehe Ein Token erzeugen unten).
Alles andere hat sinnvolle Standardwerte.
Ein Token erzeugen
Tokens werden von einem authentifizierten Benutzer erzeugt, der die Ressource lesen darf. Das Token ist opak und gescopt: Es gewährt Lesezugriff auf eine gespeicherte Abfrage oder ein Dashboard, verfällt nach der von Ihnen angegebenen TTL und kann jederzeit widerrufen werden.
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# }Fügen Sie das token in das <saiku-embed token="..."> Ihrer Hostseite
ein.
TTL-Grenzen. Standard sind 72 Stunden. Maximum sind 30 Tage (720 Stunden). Eine kurze TTL ist die sicherste Voreinstellung für ein Token, das durch beliebige Hostseiten reist.
Limit pro Benutzer. Jeder Benutzer darf gleichzeitig bis zu 200 aktive Tokens halten. Widerrufen Sie ungenutzte Tokens, um Budget freizugeben.
Ihre Tokens auflisten
curl 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/tokens' \ -u admin:adminAdmins können mit ?all=true jedes Token im System auflisten.
Ein Token widerrufen
curl -X DELETE 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/tokens/<token>' \ -u admin:adminDer Widerruf wird mit der allernächsten Anfrage wirksam — es gibt keine Gast-Session, die übernommen werden könnte.
Öffentliche (anonyme) Embeds
Wenn eine Ressource ohne Token lesbar sein soll — ein öffentliches Chart auf Ihrer Landing Page, ein offenes Dashboard in einem Blog — schalten Sie sie öffentlich einbettbar:
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" }'Dann lässt die Hostseite das Token vollständig weg:
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" path="shared/public-chart.saiku" render="chart"></saiku-embed>Öffentliche Erteilungen auflisten + widerrufen
# Ihre öffentlichen Erteilungen auflistencurl 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/public' \ -u admin:admin
# Widerrufencurl -X DELETE 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/public?kind=query&path=shared/public-chart.saiku' \ -u admin:adminAttribut-Referenz
| Attribut | Standard | Hinweise |
|---|---|---|
server | erforderlich | Origin Ihres Saiku-Launchers, z. B. https://YOUR-WORKSPACE.saiku.bi |
path | erforderlich | Repository-Pfad. Endet auf .saiku für Abfragen, .saikudash für Dashboards |
kind | query | query oder dashboard |
token | (keiner) | Embed-Token aus POST /saiku/api/embed/tokens. Für anonyme öffentliche Reads weglassen |
render | table | Für kind="query": table oder chart |
mode | bar | Für render="chart": bar, line oder pie |
height | 400px | CSS-Höhe (eine Min-Höhe auf der gerenderten Oberfläche) |
Attribute sind reaktiv — die Komponente rendert neu, wann immer sich eines von ihnen ändert. In React, Vue oder Svelte funktioniert das Binden von State an diese Props einfach.
Beispiele
Gespeicherte Abfrage als Tabelle
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" token="tx-..." path="homes/admin/Examples/Trend.saiku"></saiku-embed>Gespeicherte Abfrage als Chart
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" token="tx-..." path="homes/admin/Examples/Sales.saiku" render="chart" mode="bar" height="500px"></saiku-embed>Chart-Modi:
bar(Standard) — kategorische Balken; die erste nicht-numerische Spalte ist die Kategorie, jede numerische Spalte wird zur eigenen Serieline— gleiches Layout, Linienreihenpie— nur die erste numerische Spalte; fällt auf „No numeric series” zurück, wenn das Ergebnis nur Text enthält
Tooltips zeigen die serverformatierten Zellstrings ($1,234, 12.3%
usw.), sodass die Hostseite dieselben Beschriftungen sieht, die das
Saiku-Workbench zeigen würde.
Gespeichertes Dashboard
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" token="tx-..." kind="dashboard" path="homes/admin/exec.saikudash" height="700px"></saiku-embed>Die Komponente lädt das Dashboard-Layout einmal und führt dann eine Tile-Abfrage pro Chart- / KPI-Tile parallel unter dem Datenscope des Dashboard-Owners aus. Tile-Typen in v1:
| Tile-Typ | Was gerendert wird |
|---|---|
text | Der Text des Tiles als Absatz |
chart | Ein ECharts-Chart (verwendet tile.chartType als Modus) |
kpi | Eine einzelne große Zahl aus dem Measure des Tiles |
filter | Übersprungen — Filter-Widgets sind in v1 nur im Workbench |
| anderer | „Unsupported tile”-Platzhalter |
Anonymes öffentliches Embed
Wenn die Ressource eine öffentliche Erteilung hat, lassen Sie das Token weg:
<saiku-embed server="https://YOUR-WORKSPACE.saiku.bi" path="shared/public.saiku" render="chart" mode="pie"></saiku-embed>In 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" /> );}In 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>Theming
Das Embed rendert in einem
offenen Shadow Root,
sodass kein CSS der Hostseite hineinleckt und kein CSS des Embeds
hinausleckt. Um neu einzufärben, setzen Sie CSS-Variablen auf dem
saiku-embed-Selektor der Hostseite:
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;}Dark Mode ist einfach eine Media Query, die dieselben Variablen umschaltet:
@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; }}Sicherheitsmodell
Die Embed-Oberfläche ist für feindliche Hostseiten konzipiert — Ihre gespeicherte Abfrage könnte auf einer Drittanbieter-Site landen, die Sie nicht kontrollieren. Die Voreinstellungen spiegeln das wider.
Tokens sind opak, server-autoritativ und widerrufbar
- Tokens sind 256-Bit zufällige IDs, Base64-URL-codiert — nicht erratbar.
- Sie tragen keine eingebetteten Claims: Der Server hält den autoritativen Eintrag (Ressourcenart + Pfad, Owner-Snapshot, Verfallszeit, Revoke-Flag) und schlägt ihn bei jeder Anfrage nach. Der Widerruf wird mit der nächsten Anfrage wirksam — kein JWT-Stil-„Warten, bis die Signatur abläuft”.
- Jedes Token bindet genau eine Ressource. Das Wiederabspielen
eines Tokens gegen eine andere Ressource (falscher Pfad, falsche
Art, abgelaufen, widerrufen) liefert denselben opaken
EMBED_INVALID401 — Probes können nicht enumerieren.
Nur Header-Transport
Das Token reist als HTTP-Header X-Saiku-Embed-Token. Wir akzeptieren
absichtlich keine ?token=…-Query-Parameter, weil URL-Parameter
lecken in:
- Servlet-Access-Logs
- Logs vorgelagerter Proxies
- Browser-Verlauf
- den
Referer-Header, der bei jedem ausgehenden Asset der Hostseite gesendet wird
Das gebündelte JS liest das Token aus Ihrem <saiku-embed token="…">-Attribut
und sendet es bei jedem Fetch als Header.
Cross-Origin-Cookie-Isolation
Das Embed führt Fetches mit credentials: "omit" aus. Wenn der
Benutzer der Hostseite zufällig in einem anderen Tab bei Saiku
angemeldet ist, fließt dieses Session-Cookie nicht mit
Embed-Reads mit. Das Token IST der einzige Auth-Träger auf dieser
Oberfläche.
Datenscope des Owners
Sowohl Tokens als auch öffentliche Erteilungen snapshotten die
Rollenliste des Owners zum Erzeugungs- / Erteilungszeitpunkt und
führen die Embed-Abfrage unter dieser Identität über
sessionService.runAs aus. Eine öffentlich eingebettete Abfrage, die
Session-injizierte Filter verwendet, rendert gegen die Perspektive
des Erteilers, nicht gegen die (leere) anonyme Voreinstellung —
was Sie zum Erteilungszeitpunkt autorisiert haben, ist genau das,
was die Öffentlichkeit sieht.
Defence-in-Depth-Response-Header
Jede Embed-Antwort trägt:
X-Content-Type-Options: nosniff— Browser dürfen einen JSON-Body (der Text-Tile-HTML oder Member-Captions enthalten kann) nicht MIME-sniffen und als HTML ausführenReferrer-Policy: no-referrer— das Token niemals perRefererauf ausgehenden Assets leckenCache-Control: no-store, max-age=0— eingebettete Geschäftsdaten werden niemals von Proxies oder dem Browser-Verlauf gecacht
Freundliche Fehler
Wenn ein Fetch fehlschlägt (abgelaufenes Token, widerrufenes Token,
falscher Pfad, fehlende öffentliche Erteilung), sieht die Hostseite
ein generisches „Dieses Embed ist nicht verfügbar.” — nicht den
rohen EMBED_INVALID-Body. Die Hostseite ist ein Drittanbieter und
muss nicht wissen, ob der Fehler ein abgelaufenes Token oder ein
Widerruf war.
Bundle-Größe
Etwa 213 KB gzipped zum Zeitpunkt des Schreibens — Svelte 5 Custom-Element-Runtime + ECharts (Core + Balken / Linie / Kreis + vier gängige Komponenten, modular tree-shaked) + die Embed-Renderer. Das Bundle wird vom Browser aggressiv gecacht; das zweite Embed auf derselben Origin erhält es sofort.
Einschränkungen
- Nur Records-Format. Das Matrix-Cellset-Format wird in v1 nicht gerendert.
- Filter-Tiles werden auf Dashboards übersprungen. Das Embed rendert die erstellten Daten wie sie sind, ohne eine interaktive Filterleiste.
- Markdown in Text-Tiles wird als Klartext gerendert. Wir bündeln
markednicht, um die Größe niedrig zu halten. - AI-Query-Ergebnisse (
/ai/query) sind noch nicht als Embed-Quelle verdrahtet. Verfolgen Sie es insaiku— ein Follow-up-PR wirdkind="ai"hinzufügen.
Siehe auch
- Authentifizierung — API-Keys für den programmatischen Saiku-Cloud-Zugriff erzeugen (anders als Embed-Tokens)
- MCP — LLMs mit Ihren Cubes verbinden