Saltearse al contenido

Incrustar Saiku

El Web Component <saiku-embed/> permite incrustar una consulta o un dashboard guardado de Saiku dentro de cualquier página HTML — su sitio de marketing, una entrada de blog, un portal de cliente, un wiki, o un dashboard React / Vue. El mismo custom element funciona en cualquier host: JSX de React, plantillas de Vue, Svelte, HTML plano.

Es un auténtico Web Component, no un wrapper de framework, por lo que la página host no necesita saber nada sobre los detalles internos de Saiku.

Instalación

Dos formas equivalentes de cargar el bundle. Elija la que mejor se adapte a su página host.

Sin paso de build — apunte una etiqueta <script> al bundle que su Saiku ya sirve:

<script src="https://YOUR-WORKSPACE.saiku.bi/ui/saiku-embed.js"></script>

La descarga ocupa unos 213 KB en gzip. Los navegadores la almacenan en caché, así que la segunda página del mismo origen la obtiene al instante.

Un ejemplo trabajado

El embed mínimo viable — una consulta guardada, renderizada como tabla:

<saiku-embed
server="https://YOUR-WORKSPACE.saiku.bi"
token="tx-..."
path="homes/admin/Examples/Trend.saiku"
height="400px"
></saiku-embed>

Los tres atributos esenciales son server (origen de su Saiku), path (ruta del repositorio de la consulta guardada) y token (el token de embed — consulte Generar un token más abajo). Todo lo demás tiene valores por defecto razonables.

Generar un token

Los tokens los genera un usuario autenticado que pueda leer el recurso. El token es opaco y está acotado: otorga acceso de solo lectura a una consulta o dashboard guardado, expira después del TTL que especifique y puede revocarse en cualquier momento.

Generar un token
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
# }

Pegue el token en el <saiku-embed token="..."> de su página host.

Límites del TTL. Por defecto son 72 horas. El máximo es de 30 días (720 horas). Un TTL corto es el valor por defecto más seguro para un token que viaja a través de páginas host arbitrarias.

Límite por usuario. Cada usuario puede mantener hasta 200 tokens activos a la vez. Revoque los tokens no usados para liberar el cupo.

Listar sus tokens

Ventana de terminal
curl 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/tokens' \
-u admin:admin

Los administradores pueden listar todos los tokens del sistema con ?all=true.

Revocar un token

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

La revocación surte efecto en la próxima petición — no hay sesión de invitado que secuestrar.

Embeds públicos (anónimos)

Si un recurso debe ser legible sin un token — un gráfico público en su página de aterrizaje, un dashboard abierto en un blog — márquelo como incrustable públicamente:

Ventana de terminal
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"
}'

Después, la página host omite el token por completo:

<saiku-embed
server="https://YOUR-WORKSPACE.saiku.bi"
path="shared/public-chart.saiku"
render="chart"
></saiku-embed>

Listar + revocar concesiones públicas

Ventana de terminal
# List your public grants
curl 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/public' \
-u admin:admin
# Revoke
curl -X DELETE 'https://YOUR-WORKSPACE.saiku.bi/rest/saiku/api/embed/public?kind=query&path=shared/public-chart.saiku' \
-u admin:admin

Referencia de atributos

AtributoPor defectoNotas
serverrequeridoOrigen de su launcher de Saiku, por ejemplo https://YOUR-WORKSPACE.saiku.bi
pathrequeridoRuta del repositorio. Termina en .saiku para consultas, .saikudash para dashboards
kindqueryquery o dashboard
token(ninguno)Token de embed de POST /saiku/api/embed/tokens. Omítalo para lecturas públicas anónimas
rendertablePara kind="query": table o chart
modebarPara render="chart": bar, line o pie
height400pxAltura CSS (un min-height en la superficie renderizada)

Los atributos son reactivos — el componente se vuelve a renderizar siempre que cambia cualquiera de ellos. En React, Vue o Svelte, vincular el estado a estas props funciona sin más.

Ejemplos

Consulta guardada como tabla

<saiku-embed
server="https://YOUR-WORKSPACE.saiku.bi"
token="tx-..."
path="homes/admin/Examples/Trend.saiku"
></saiku-embed>

Consulta guardada como gráfico

<saiku-embed
server="https://YOUR-WORKSPACE.saiku.bi"
token="tx-..."
path="homes/admin/Examples/Sales.saiku"
render="chart"
mode="bar"
height="500px"
></saiku-embed>

Modos de gráfico:

  • bar (por defecto) — barras categóricas; la primera columna no numérica es la categoría, cada columna numérica se convierte en su propia serie
  • line — mismo diseño, series de líneas
  • pie — solo la primera columna numérica; cae a “No numeric series” si el resultado es solo texto

Los tooltips muestran las cadenas de celda formateadas por el servidor ($1,234, 12.3%, etc.) para que la página host vea las mismas leyendas que mostraría el workbench de Saiku.

Dashboard guardado

<saiku-embed
server="https://YOUR-WORKSPACE.saiku.bi"
token="tx-..."
kind="dashboard"
path="homes/admin/exec.saikudash"
height="700px"
></saiku-embed>

El componente obtiene el diseño del dashboard una vez y luego ejecuta una consulta por mosaico de gráfico / KPI en paralelo bajo el ámbito de datos del propietario del dashboard. Tipos de mosaico en v1:

Tipo de mosaicoQué renderiza
textEl texto del mosaico, como párrafo
chartUn gráfico ECharts (usa tile.chartType como modo)
kpiUn único número grande de la medida del mosaico
filterOmitido — los widgets de filtro son solo workbench en v1
otrosMarcador “Unsupported tile”

Embed público anónimo

Cuando el recurso tiene una concesión pública, omita el token:

<saiku-embed
server="https://YOUR-WORKSPACE.saiku.bi"
path="shared/public.saiku"
render="chart"
mode="pie"
></saiku-embed>

Dentro de 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"
/>
);
}

Dentro de 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>

Temas

El embed se renderiza dentro de un shadow root abierto, por lo que el CSS de la página host no puede filtrarse hacia dentro y el CSS del embed no puede filtrarse hacia fuera. Para recolorear, defina variables CSS en el selector saiku-embed de la página host:

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;
}

El modo oscuro es solo una media query que cambia las mismas 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;
}
}

Modelo de seguridad

La superficie de embed está diseñada para páginas host hostiles — su consulta guardada podría acabar en un sitio de terceros que usted no controla. Los valores por defecto lo reflejan.

Los tokens son opacos, autoritativos en el servidor y revocables

  • Los tokens son IDs aleatorios de 256 bits, codificados en Base64-URL — no se pueden adivinar.
  • No llevan claims incrustados: el servidor conserva el registro autoritativo (tipo y ruta del recurso, snapshot del propietario, expiración, indicador de revocado) y lo consulta en cada petición. La revocación surte efecto en la próxima petición — no hay un “espere a que expire la firma” estilo JWT.
  • Cada token fija exactamente un recurso. Reproducir un token contra cualquier otro recurso (ruta incorrecta, tipo incorrecto, expirado, revocado) devuelve el mismo EMBED_INVALID 401 opaco — las sondas no pueden enumerar.

Transporte solo por encabezado

El token viaja en el encabezado HTTP X-Saiku-Embed-Token. Deliberadamente no aceptamos parámetros de query ?token=… porque los parámetros de URL se filtran a:

  • logs de acceso del servlet
  • logs del proxy frontal
  • historial del navegador
  • el encabezado Referer enviado en cada recurso saliente de la página host

El JS empaquetado lee el token del atributo <saiku-embed token="…"> y lo envía como encabezado en cada fetch.

Aislamiento de cookies cross-origin

El embed hace fetch con credentials: "omit". Si el usuario de la página host está logueado en Saiku en otra pestaña, esa cookie de sesión no fluye con las lecturas del embed. El token ES el único portador de auth en esta superficie.

Ámbito de datos del propietario

Tanto los tokens como las concesiones públicas capturan la lista de roles del propietario en el momento de generar / conceder y ejecutan la consulta del embed bajo esa identidad mediante sessionService.runAs. Una consulta incrustada públicamente que usa filtros inyectados por sesión se renderiza contra la perspectiva del otorgante, no contra el (vacío) valor por defecto anónimo — lo que autorizó al conceder es exactamente lo que ve el público.

Encabezados de respuesta de defensa en profundidad

Toda respuesta de embed lleva:

  • X-Content-Type-Options: nosniff — los navegadores no deben hacer MIME-sniff de un cuerpo JSON (que podría contener HTML de mosaico de texto o leyendas de miembros) y ejecutarlo como HTML
  • Referrer-Policy: no-referrer — nunca filtrar el token mediante Referer en recursos salientes
  • Cache-Control: no-store, max-age=0 — los datos de negocio incrustados nunca se cachean en proxies ni en el historial del navegador

Errores amigables

Cuando un fetch falla (token expirado, token revocado, ruta incorrecta, falta concesión pública), la página host ve un mensaje genérico “This embed is unavailable.” — no el cuerpo crudo EMBED_INVALID. La página host es un tercero y no necesita saber si el fallo fue un token expirado o una revocación.

Tamaño del bundle

Alrededor de 213 KB en gzip en el momento de escribir esto — runtime de custom element de Svelte 5 + ECharts (core + bar / line / pie + cuatro componentes comunes, con tree-shake modular) + los renderizadores del embed. El bundle se cachea de forma agresiva en el navegador; el segundo embed en el mismo origen lo obtiene al instante.

Limitaciones

  • Solo formato records. El formato de cellset matrix no se renderiza en v1.
  • Los mosaicos de filtro se omiten en los dashboards. El embed renderiza los datos creados tal cual sin una barra de filtros interactiva.
  • Markdown en mosaicos de texto se renderiza como texto plano. No empaquetamos marked para mantener el tamaño bajo.
  • Los resultados AI Query (/ai/query) aún no están conectados como fuente de embed. Sígalo en saiku — un PR de seguimiento añadirá kind="ai".

Véase también

  • Autenticación — generar API keys para acceso programático a Saiku Cloud (diferente de los tokens de embed)
  • MCP — conectar LLMs a sus cubos