codeant-ai-for-open-source[bot] commented on code in PR #36924:
URL: https://github.com/apache/superset/pull/36924#discussion_r2665142551


##########
superset-embedded-sdk/src/index.ts:
##########
@@ -238,6 +251,18 @@ export async function embedDashboard({
 
   setTimeout(refreshGuestToken, getGuestTokenRefreshTiming(guestToken));
 
+  // Register the resolvePermalinkUrl method for the iframe to call
+  // Returns null if no callback provided, allowing iframe to use default URL
+  ourPort.defineMethod(
+    'resolvePermalinkUrl',
+    async ({ key }: { key: string }) => {
+      if (!resolvePermalinkUrl) {
+        return null;
+      }
+      return resolvePermalinkUrl({ key });

Review Comment:
   **Suggestion:** The host-provided `resolvePermalinkUrl` callback may throw 
or reject; the defined method currently forwards exceptions to the comms 
boundary. Wrap the call in a try/catch and `await` the result so errors are 
handled and a safe `null` is returned on failure. [possible bug]
   
   **Severity Level:** Critical 🚨
   ```suggestion
         try {
           const url = await resolvePermalinkUrl({ key });
           return url;
         } catch (err) {
           log('Error in resolvePermalinkUrl callback', err);
           return null;
         }
   ```
   <details>
   <summary><b>Why it matters? ⭐ </b></summary>
   
   Wrapping the host-provided callback with try/catch and awaiting the result 
prevents exceptions or rejected promises in user code from propagating across 
the comms boundary. Returning null (and logging) is a safer failure mode than 
letting the RPC reject unexpectedly.
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-embedded-sdk/src/index.ts
   **Line:** 262:262
   **Comment:**
        *Possible Bug: The host-provided `resolvePermalinkUrl` callback may 
throw or reject; the defined method currently forwards exceptions to the comms 
boundary. Wrap the call in a try/catch and `await` the result so errors are 
handled and a safe `null` is returned on failure.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/src/dashboard/containers/DashboardPage.tsx:
##########
@@ -177,10 +177,11 @@ export const DashboardPage: FC<PageProps> = ({ idOrSlug 
}: PageProps) => {
       // the currently stored value when hydrating
       let activeTabs: string[] | undefined;
       let chartStates: DashboardChartStates | undefined;
+      let anchor: string | undefined;
       if (permalinkKey) {
         const permalinkValue = await getPermalinkValue(permalinkKey);
         if (permalinkValue) {
-          ({ dataMask, activeTabs, chartStates } = permalinkValue.state);
+          ({ dataMask, activeTabs, chartStates, anchor } = 
permalinkValue.state);

Review Comment:
   **Suggestion:** Destructuring `permalinkValue.state` directly assumes 
`state` exists; if `permalinkValue.state` is undefined this will throw a 
TypeError at runtime. Provide a safe default (empty object) before 
destructuring so the assignment never attempts to read properties from 
undefined. [null pointer]
   
   **Severity Level:** Minor ⚠️
   ```suggestion
         const permalinkState = permalinkValue.state ?? {};
         ({ dataMask, activeTabs, chartStates, anchor } = permalinkState as 
any);
   ```
   <details>
   <summary><b>Why it matters? ⭐ </b></summary>
   
   The current code will throw if permalinkValue exists but its `state` 
property is undefined. The proposed guard (use a default object) prevents a 
runtime TypeError and is a safe, minimal hardening. This is a real, verifiable 
failure mode given the loose typing of the API response.
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/dashboard/containers/DashboardPage.tsx
   **Line:** 181:184
   **Comment:**
        *Null Pointer: Destructuring `permalinkValue.state` directly assumes 
`state` exists; if `permalinkValue.state` is undefined this will throw a 
TypeError at runtime. Provide a safe default (empty object) before 
destructuring so the assignment never attempts to read properties from 
undefined.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/src/embedded/api.tsx:
##########
@@ -67,14 +68,28 @@ const getDashboardPermalink = async ({
     chartStates &&
     Object.keys(chartStates).length > 0;
 
-  return getDashboardPermalinkUtil({
+  const { key, url } = await getDashboardPermalinkUtil({
     dashboardId,
     dataMask,
     activeTabs,
     anchor,
     chartStates: includeChartState ? chartStates : undefined,
     includeChartState,
   });
+
+  // Ask the SDK to resolve the permalink URL
+  // Returns null if no callback was provided by the host
+  const resolvedUrl = await Switchboard.get<string | null>(
+    'resolvePermalinkUrl',
+    { key },
+  );
+
+  // If callback returned a URL, use it; otherwise use Superset's default URL
+  if (resolvedUrl) {

Review Comment:
   **Suggestion:** Unsafe return of unvalidated host-provided value: 
`resolvedUrl` is returned without verifying it's actually a string URL, which 
can lead to callers receiving non-string values (object/function) and 
subsequently throwing. Ensure `resolvedUrl` is a string before returning (and 
otherwise fall back to the default `url`). [type error]
   
   **Severity Level:** Minor ⚠️
   ```suggestion
     const resolvedUrl = await Switchboard.get<unknown | null>(
       'resolvePermalinkUrl',
       { key },
     );
   
     // Only accept a string result from the host; otherwise fall back to 
Superset's default URL
     if (typeof resolvedUrl === 'string') {
   ```
   <details>
   <summary><b>Why it matters? ⭐ </b></summary>
   
   Validating the host-provided value is sensible: ensure it's a string before 
returning to avoid surprising consumers. This prevents type/runtime errors when 
hosts return unexpected shapes.
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/embedded/api.tsx
   **Line:** 82:88
   **Comment:**
        *Type Error: Unsafe return of unvalidated host-provided value: 
`resolvedUrl` is returned without verifying it's actually a string URL, which 
can lead to callers receiving non-string values (object/function) and 
subsequently throwing. Ensure `resolvedUrl` is a string before returning (and 
otherwise fall back to the default `url`).
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



##########
superset-frontend/src/dashboard/components/URLShortLinkButton/index.tsx:
##########
@@ -69,7 +69,7 @@ export default function URLShortLinkButton({
         chartStates &&
         Object.keys(chartStates).length > 0;
 
-      const url = await getDashboardPermalink({
+      const { url } = await getDashboardPermalink({

Review Comment:
   **Suggestion:** Defensively handle different return shapes from 
`getDashboardPermalink`: the current code destructures `url` assuming the 
helper returns an object, but if it returns a plain string (or undefined) that 
destructuring will throw a runtime TypeError; instead, capture the raw result, 
detect whether it's a string or an object, and only call `setShortUrl` when a 
string URL is available. [type error]
   
   **Severity Level:** Minor ⚠️
   



##########
superset-embedded-sdk/src/index.ts:
##########
@@ -83,6 +86,15 @@ export type ObserveDataMaskCallbackFn = (
 ) => void;
 export type ThemeMode = 'default' | 'dark' | 'system';
 
+/**
+ * Callback to resolve permalink URLs.
+ * Receives the permalink key and returns the full URL to use for the 
permalink.
+ */
+export type ResolvePermalinkUrlFn = (params: {
+  /** The permalink key (e.g., "xyz789") */
+  key: string;
+}) => string | Promise<string>;
+
 export type EmbeddedDashboard = {
   getScrollSize: () => Promise<Size>;
   unmount: () => void;

Review Comment:
   **Suggestion:** Type mismatch: the handler returns `null` when no callback 
is provided, but `ResolvePermalinkUrlFn` is currently typed to only return 
`string | Promise<string>`. Make the type allow `null` (and promise-wrapped 
`null`) so consumers and TypeScript agree about the possible return values. 
[type error]
   
   **Severity Level:** Minor ⚠️
   ```suggestion
   }) => string | null | Promise<string | null>;
   ```
   <details>
   <summary><b>Why it matters? ⭐ </b></summary>
   
   The code path currently returns null when no callback is provided (and other 
suggestions also return null on failure). The exported type should reflect that 
null is a possible return value so TypeScript consumers handle it correctly. 
This fixes a real type/contract mismatch.
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-embedded-sdk/src/index.ts
   **Line:** 100:100
   **Comment:**
        *Type Error: Type mismatch: the handler returns `null` when no callback 
is provided, but `ResolvePermalinkUrlFn` is currently typed to only return 
`string | Promise<string>`. Make the type allow `null` (and promise-wrapped 
`null`) so consumers and TypeScript agree about the possible return values.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to