awslabs / amazon-quicksight-embedding-sdk

A SDK to help users embed QuickSight dashboards on other pages.
Apache License 2.0
172 stars 40 forks source link

addActions failing with access denied error. #192

Open kt-mattie-langenberg opened 9 months ago

kt-mattie-langenberg commented 9 months ago

Hi folks! I've been setting up a hook in my react app to embed dashboards. I'm able to see the dashboard in the UI and events are logging in the console but addVisualActions is failing. getVisualActions works.

I'm seeing a call out to: https://us-east-1.quicksight.aws.amazon.com/embed/d1b7ff50cafd465a9d2f9b451e2556e3/api/dashboards/2e590670-1e6f-4a23-9955-278f193747de/validate-partial?Operation=ValidatePartialDashboardDefinitionProxy in the network tab. That returns 403 NO_ACCESS_PRIVILEGE.

I've tried with 2.6.0, 2.4.0 and 2.3.1 with the same result.

import { useCallback, useEffect, useRef, useState } from "react";
import { createEmbeddingContext } from "amazon-quicksight-embedding-sdk";
import type {
  DashboardExperience,
  FrameOptions,
  EmbeddingContext,
} from "amazon-quicksight-embedding-sdk/dist";
export const useQuickSightDashboard = (iframeCustomStyle: string) => {
  const quickSightURL = MYLAMBDAURL;
  const dashboardRef = useRef<HTMLDivElement>(null);

  const [embeddedDashboard, setEmbeddedDashboard] =
    useState<DashboardExperience | null>(null);

  const [dashboardUrl, setDashboardUrl] = useState<string | null>(null);
  const [embeddingContext, setEmbeddingContext] =
    useState<EmbeddingContext | null>(null);

  useEffect(() => {
    const timeout = setTimeout(() => {
      fetch(quickSightURL)
        .then((response) => response.json())
        .then((response) => {
          setDashboardUrl(response.EmbedUrl);
        });
    }, 50);
    return () => clearTimeout(timeout);
  }, []);

  const createContext = async () => {
    const context = await createEmbeddingContext({
      onChange: (changeEvent, metadata) => {
        console.log("Context received a change", changeEvent, metadata);
      },
    });

    setEmbeddingContext(context);
  };

  const embedDashboard = useCallback(async () => {
    if (dashboardUrl && dashboardRef.current) {
      const options: FrameOptions = {
        resizeHeightOnSizeChangedEvent: true,
        url: dashboardUrl,
        container: dashboardRef.current,
        withIframePlaceholder: true,
        className: iframeCustomStyle,
      };

      const contentOptions = {
        onMessage: async (messageEvent: {
          eventName: string;
          message: {
            title: string;
            errorCode: string;
            changedParameters: object;
          };
        }) => {
          switch (messageEvent.eventName) {
            case "SIZE_CHANGED": {
              console.log(
                "Size changed. New dimensions:",
                messageEvent.message,
              );
              break;
            }
            case "CONTENT_LOADED": {
              console.log("Content Loaded:", messageEvent.message);
              try {
                const sheets = await newEmbeddedDashboard.getSheets();
                const { SheetId } = sheets[0];
                // const visuals =
                //   await newEmbeddedDashboard.getSheetVisuals(SheetId);
                // //const { VisualId } = visuals[1];
                const VisualId =
                  "2e590670-1e6f-4a23-9955-278f193747de_4754f7ba-ce8d-44c4-aec0-e02ccc814887";

                const newAction = await newEmbeddedDashboard.addVisualActions(
                  SheetId,
                  VisualId,
                  [
                    {
                      Name: "VIZACTION",
                      CustomActionId: "visual-action-1",
                      Status: "ENABLED",
                      Trigger: "DATA_POINT_CLICK",
                      ActionOperations: [
                        {
                          CallbackOperation: {
                            EmbeddingMessage: {},
                          },
                        },
                      ],
                    },
                  ],
                );

                console.log("newAction", newAction);
              } catch (error) {
                console.log(error);
              }

              setEmbeddedDashboard(newEmbeddedDashboard);
              break;
            }
            case "CALLBACK_OPERATION_INVOKED":
              console.log("Callback operation invoked:", messageEvent.message);

              break;
            default:
              console.warn(`Unhandled event: ${messageEvent.eventName}`);
              break;
          }
        },
      };

      const newEmbeddedDashboard = await embeddingContext.embedDashboard(
        options,
        contentOptions,
      );
    }
  }, [dashboardUrl, embeddingContext, iframeCustomStyle]);

  useEffect(() => {
    if (dashboardUrl) {
      createContext();
    }
  }, [dashboardUrl]);

  useEffect(() => {
    if (embeddingContext) {
      embedDashboard();
    }
  }, [embedDashboard, embeddingContext]);

  return { dashboardRef, embeddedDashboard };
};
bwelkin commented 9 months ago

Thank you for reporting this issue. We are investigating it.

kt-mattie-langenberg commented 8 months ago

@bwelkin Sharing some new context here.

I have found that I am able to add custom actions to embedded sheets that come from a single sheet analysis.

When I embed a sheet from a multi-sheet analysis, that fails on the permission check. The number of visualizations on the sheet doesn't seem to matter.