Zum Inhalt springen

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.

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.

Ein Token erzeugen
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

Terminal-Fenster
curl 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/tokens' \
-u admin:admin

Admins können mit ?all=true jedes Token im System auflisten.

Ein Token widerrufen

Terminal-Fenster
curl -X DELETE 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/tokens/<token>' \
-u admin:admin

Der 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:

Terminal-Fenster
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

Terminal-Fenster
# Ihre öffentlichen Erteilungen auflisten
curl 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/public' \
-u admin:admin
# Widerrufen
curl -X DELETE 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/public?kind=query&path=shared/public-chart.saiku' \
-u admin:admin

Attribut-Referenz

AttributStandardHinweise
servererforderlichOrigin Ihres Saiku-Launchers, z. B. https://YOUR-WORKSPACE.saiku.bi
patherforderlichRepository-Pfad. Endet auf .saiku für Abfragen, .saikudash für Dashboards
kindqueryquery oder dashboard
token(keiner)Embed-Token aus POST /saiku/api/embed/tokens. Für anonyme öffentliche Reads weglassen
rendertableFür kind="query": table oder chart
modebarFür render="chart": bar, line oder pie
height400pxCSS-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 Serie
  • line — gleiches Layout, Linienreihen
  • pie — 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-TypWas gerendert wird
textDer Text des Tiles als Absatz
chartEin ECharts-Chart (verwendet tile.chartType als Modus)
kpiEine 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_INVALID 401 — 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.

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ühren
  • Referrer-Policy: no-referrer — das Token niemals per Referer auf ausgehenden Assets lecken
  • Cache-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 marked nicht, um die Größe niedrig zu halten.
  • AI-Query-Ergebnisse (/ai/query) sind noch nicht als Embed-Quelle verdrahtet. Verfolgen Sie es in saiku — ein Follow-up-PR wird kind="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