fix(superset): resolver slug → UUID antes de gerar guest token e embeddar
O SDK do Superset exige o UUID do embedded config (não o slug) tanto no
embedDashboard quanto no guest token. Agora o backend resolve:
slug → dashboard ID → embedded UUID → guest token com UUID
E retorna { token, embeddedId } para o frontend usar no embedDashboard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6e8a3261bb
commit
023451e000
|
|
@ -27,7 +27,8 @@ export function SupersetDashboard({
|
|||
const [status, setStatus] = useState<"loading" | "ready" | "error" | "unavailable">("loading");
|
||||
const [errorMsg, setErrorMsg] = useState<string>("");
|
||||
|
||||
const fetchGuestToken = useCallback(async (): Promise<string> => {
|
||||
// Busca token e embeddedId (UUID) do backend
|
||||
const fetchTokenData = useCallback(async (): Promise<{ token: string; embeddedId: string }> => {
|
||||
const resp = await fetch("/api/superset/guest-token", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
|
|
@ -38,8 +39,7 @@ export function SupersetDashboard({
|
|||
const err = await resp.json().catch(() => ({ error: "Erro desconhecido" }));
|
||||
throw new Error(err.error || `HTTP ${resp.status}`);
|
||||
}
|
||||
const { token } = await resp.json();
|
||||
return token;
|
||||
return resp.json();
|
||||
}, [dashboardId]);
|
||||
|
||||
const loadDashboard = useCallback(async () => {
|
||||
|
|
@ -56,6 +56,9 @@ export function SupersetDashboard({
|
|||
return;
|
||||
}
|
||||
|
||||
// Resolve embeddedId (UUID) e obtém token inicial
|
||||
const { embeddedId } = await fetchTokenData();
|
||||
|
||||
// Importa SDK dinamicamente (só quando necessário)
|
||||
const { embedDashboard } = await import("@superset-ui/embedded-sdk");
|
||||
|
||||
|
|
@ -65,10 +68,13 @@ export function SupersetDashboard({
|
|||
}
|
||||
|
||||
sdkRef.current = await embedDashboard({
|
||||
id: dashboardId,
|
||||
id: embeddedId, // UUID do embedded config (não o slug)
|
||||
supersetDomain: window.location.origin + "/superset",
|
||||
mountPoint: containerRef.current,
|
||||
fetchGuestToken,
|
||||
fetchGuestToken: async () => {
|
||||
const { token } = await fetchTokenData();
|
||||
return token;
|
||||
},
|
||||
dashboardUiConfig: {
|
||||
hideTitle: true,
|
||||
hideChartControls: false,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,29 @@ export function registerSupersetRoutes(app: Express): void {
|
|||
const token = await getServiceToken();
|
||||
const user = req.user as any;
|
||||
|
||||
// Resolve slug → dashboard ID → embedded UUID
|
||||
const dashResp = await fetch(`${SUPERSET_URL}/api/v1/dashboard/${dashboardId}`, {
|
||||
headers: { "Authorization": `Bearer ${token}` },
|
||||
});
|
||||
if (!dashResp.ok) {
|
||||
return res.status(404).json({ error: `Dashboard '${dashboardId}' não encontrado no Superset` });
|
||||
}
|
||||
const dashData = await dashResp.json();
|
||||
const dbNumericId = dashData.result?.id;
|
||||
|
||||
const embeddedResp = await fetch(`${SUPERSET_URL}/api/v1/dashboard/${dbNumericId}/embedded`, {
|
||||
headers: { "Authorization": `Bearer ${token}` },
|
||||
});
|
||||
if (!embeddedResp.ok) {
|
||||
return res.status(404).json({ error: `Dashboard '${dashboardId}' não tem embedding habilitado` });
|
||||
}
|
||||
const embeddedData = await embeddedResp.json();
|
||||
const embeddedUuid = embeddedData.result?.uuid;
|
||||
|
||||
if (!embeddedUuid) {
|
||||
return res.status(404).json({ error: `UUID de embedding não encontrado para '${dashboardId}'` });
|
||||
}
|
||||
|
||||
const guestResp = await fetch(`${SUPERSET_URL}/api/v1/security/guest_token/`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
|
|
@ -51,7 +74,7 @@ export function registerSupersetRoutes(app: Express): void {
|
|||
first_name: user?.name?.split(" ")[0] || "Arcádia",
|
||||
last_name: user?.name?.split(" ").slice(1).join(" ") || "User",
|
||||
},
|
||||
resources: [{ type: "dashboard", id: dashboardId }],
|
||||
resources: [{ type: "dashboard", id: embeddedUuid }],
|
||||
rls: user?.tenantId ? [{ clause: `tenant_id = ${user.tenantId}` }] : [],
|
||||
}),
|
||||
});
|
||||
|
|
@ -62,7 +85,7 @@ export function registerSupersetRoutes(app: Express): void {
|
|||
}
|
||||
|
||||
const { token: guestToken } = await guestResp.json();
|
||||
res.json({ token: guestToken, supersetUrl: "/superset" });
|
||||
res.json({ token: guestToken, embeddedId: embeddedUuid, supersetUrl: "/superset" });
|
||||
} catch (err: any) {
|
||||
console.error("[Superset] guest-token error:", err.message);
|
||||
res.status(502).json({ error: err.message });
|
||||
|
|
|
|||
Loading…
Reference in New Issue