Access denied exception with addVisualActions

Hi folks. My dashboard is loading and I’m seeing events come through in my console (including ADD_VISUAL_ACTIONS). getSheets and getSheetVisuals are working, but I’m unable to get past my addVisualActions call.

It’s erroring with INVALID_INPUT and “Access denied exception”

Is this a configuration issue? or have I missed something in the documentation?

                const sheets = await newEmbeddedDashboard.getSheets();
                const { SheetId } = sheets[0];
                const visuals =
                  await newEmbeddedDashboard.getSheetVisuals(SheetId);
                const { VisualId } = visuals[0];

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

Hello @mattienodj, welcome to the Quicksight community!

Could you try using the addActions instead?

That method just gives me a type error.

TypeError: newEmbeddedDashboard.addVisualAction is not a function
at onMessage (useQuickSightDashboard.ts:73:62)

Property ‘addVisualAction’ does not exist on type ‘DashboardExperience’. Did you mean ‘addVisualActions’?ts(2551)

I’m going to try another clean install.

This is what my hook looks like at present.

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 = MYWORKINGURL;
  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);
        });
    }, 2000);
    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[2];

                const newAction = await newEmbeddedDashboard.addVisualActions(
                  SheetId,
                  VisualId,
                  [
                    {
                      Name: "VizAction",
                      CustomActionId: "customvizaction",
                      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 };
};```

The frame is rendered properly in the browser. I see my dashboard there, and I’m seeing events in console. Just that addVisualActions being grumpy.

A bit more information.

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 is what returns the returns 403 NO_ACCESS_PRIVILEGE, but I can’t find any documentation reference that or any information about permissions other than the setup for the anonymous URL embedding.

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

Hi @mattienodj,

This question may be difficult to answer through the community forum, I will message you privately to discuss solutions.

Many Thanks,
Andrew

1 Like

Hey @abacon and @mattienodj !

Were you all able to solve this issue and if so could you share your solution here to help the community?

I’m working through a support ticket with AWS now. I will definitely share the outcome here if we get this solved.

1 Like