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


##########
superset-frontend/src/extensions/ExtensionsList.tsx:
##########
@@ -50,6 +67,100 @@ const ExtensionsList: 
FunctionComponent<ExtensionsListProps> = ({
     addDangerToast,
   );
 
+  // Load current active chatbot from settings on mount
+  useEffect(() => {
+    SupersetClient.get({ endpoint: '/api/v1/extensions/settings' })
+      .then(({ json }) => {
+        setActiveChatbotId(json?.result?.active_chatbot_id ?? null);
+      })
+      .catch(() => {
+        // non-fatal: leave activeChatbotId as null
+      });
+  }, []);
+
+  const handleUploadClick = () => {
+    fileInputRef.current?.click();
+  };
+
+  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    const file = e.target.files?.[0];
+    if (!file) return;
+
+    if (!file.name.endsWith('.supx')) {
+      addDangerToast(t('File must have a .supx extension.'));
+      e.target.value = '';
+      return;
+    }
+
+    const formData = new FormData();
+    formData.append('bundle', file);
+
+    setUploading(true);
+    SupersetClient.post({
+      endpoint: '/api/v1/extensions/',
+      body: formData,
+      headers: { Accept: 'application/json' },
+    })
+      .then(() => {
+        addSuccessToast(t('Extension installed successfully.'));
+        refreshData();
+      })
+      .catch(
+        createErrorHandler(errMsg =>
+          addDangerToast(
+            t('There was an issue installing the extension: %s', errMsg),
+          ),
+        ),
+      )
+      .finally(() => {
+        setUploading(false);
+        e.target.value = '';
+      });
+  };
+
+  const handleDelete = (extension: Extension) => {
+    const { publisher, name } = extension;
+    SupersetClient.delete({
+      endpoint: `/api/v1/extensions/${publisher}/${name}`,
+    }).then(

Review Comment:
   **Suggestion:** The delete URL is built from `extension.publisher`, but the 
backend list payload is produced by `build_extension_data` and does not include 
a `publisher` field, so this resolves to `/api/v1/extensions/undefined/<name>` 
and deletion fails. Include `publisher` in the API response (or derive it from 
`id` before calling delete). [api mismatch]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Delete action on Extensions page always hits wrong URL.
   - ❌ Uploaded .supx extensions cannot be removed via UI.
   - ⚠️ Publisher column renders empty despite manifest having publisher.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Start the backend with the extensions API enabled so 
`/api/v1/extensions/` is exposed
   by `ExtensionsRestApi.get_list` in `superset/extensions/api.py:92-138`, 
which builds each
   extension object using `build_extension_data` in 
`superset/extensions/utils.py:233-254`.
   
   2. Observe that `build_extension_data` at 
`superset/extensions/utils.py:233-241` only
   populates fields `id`, `name`, `version`, `description`, `dependencies`, and 
optionally
   `remoteEntry` / `moduleFederationName`; it does not include a `publisher` 
field, even
   though `Manifest` defines `publisher` and `name` separately in
   `superset-core/src/superset_core/extensions/types.py:38-75,133-144`.
   
   3. On the frontend, the extensions list page uses
   `useListViewResource<Extension>('extensions', ...)` in
   `superset-frontend/src/extensions/ExtensionsList.tsx:60-68`, which relies on
   `useListViewResource` at 
`superset-frontend/src/views/CRUD/hooks.ts:11-24,46-56,149-56` to
   fetch `/api/v1/extensions/?q=...` and assign `json.result` directly to
   `resourceCollection` without adding or deriving a `publisher` field.
   
   4. When a user clicks the delete icon in the Actions column rendered in
   `superset-frontend/src/extensions/ExtensionsList.tsx:187-245`, 
`ConfirmStatusChange` calls
   `handleDelete(original)` at 
`superset-frontend/src/extensions/ExtensionsList.tsx:121-136`;
   inside `handleDelete`, the destructuring `const { publisher, name } = 
extension;` at line
   122 receives an `extension` object that has no `publisher` property, so 
`publisher` is
   `undefined`, and the DELETE request is sent to 
`/api/v1/extensions/undefined/<name>` (line
   124), which does not match any real extension and results in 
`ExtensionsRestApi.delete` at
   `superset/extensions/api.py:275-340` returning 404, causing the UI to show a 
failure toast
   instead of deleting the extension.
   ```
   </details>
   
   [Fix in 
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=458f469b0c9e48cf8550f1a9cb880e21&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 | [Fix in VSCode 
Claude](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=458f469b0c9e48cf8550f1a9cb880e21&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset-frontend/src/extensions/ExtensionsList.tsx
   **Line:** 122:125
   **Comment:**
        *Api Mismatch: The delete URL is built from `extension.publisher`, but 
the backend list payload is produced by `build_extension_data` and does not 
include a `publisher` field, so this resolves to 
`/api/v1/extensions/undefined/<name>` and deletion fails. Include `publisher` 
in the API response (or derive it from `id` before calling delete).
   
   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.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40450&comment_hash=550ffee53b5ff4187a5d221bd62a6c0960ba4882ee7de28f5cefc283e3d47611&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40450&comment_hash=550ffee53b5ff4187a5d221bd62a6c0960ba4882ee7de28f5cefc283e3d47611&reaction=dislike'>👎</a>



##########
superset/extensions/api.py:
##########
@@ -16,21 +16,43 @@
 # under the License.
 import mimetypes
 from io import BytesIO
+from pathlib import Path
 from typing import Any
+from zipfile import is_zipfile, ZipFile
 
-from flask import send_file
+from flask import current_app, request, send_file
 from flask.wrappers import Response
 from flask_appbuilder.api import BaseApi, expose, protect, safe
 
+from superset.extensions import security_manager
+from superset.extensions.settings import (
+    get_extension_settings,
+    update_extension_settings,
+)

Review Comment:
   **Suggestion:** This import references a module that does not exist in the 
current codebase (`superset/extensions/settings.py`), so importing 
`superset.extensions.api` will fail at runtime with `ModuleNotFoundError` and 
break the extensions API endpoints. Add the missing module in this PR or change 
the import to the correct existing path. [import error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Enabling extensions feature crashes during app initialization.
   - ❌ /api/v1/extensions endpoints unavailable when feature flag enabled.
   - ⚠️ Frontend ExtensionsList cannot load or update extension settings.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Enable the `ENABLE_EXTENSIONS` feature flag so that the initialization 
routine in
   `superset/initialization/__init__.py:16-24` executes the block that imports 
and registers
   the extensions API: `from superset.extensions.api import ExtensionsRestApi` 
followed by
   `appbuilder.add_api(ExtensionsRestApi)`.
   
   2. When Python imports `superset.extensions.api`, it executes the top-level 
imports shown
   in `superset/extensions/api.py:17-37`, including `from 
superset.extensions.settings import
   (get_extension_settings, update_extension_settings)`.
   
   3. The `superset.extensions` package directory at `superset/extensions` 
(listed via `ls`
   output in `superset/extensions`) only contains `__init__.py`, `api.py`,
   `cache_middleware.py`, `context.py`, `contributions.py`, `discovery.py`, 
`exceptions.py`,
   `local_extensions_watcher.py`, `metadb.py`, `metastore_cache.py`, 
`pylint.py`, `ssh.py`,
   `stats_logger.py`, `types.py`, and `utils.py`; there is no `settings.py` 
file in this
   package, and an attempt to read 
`/workspace/superset/superset/extensions/settings.py`
   fails, confirming the module does not exist.
   
   4. Because `superset.extensions.settings` cannot be found, the import at
   `superset/extensions/api.py:28-31` raises `ModuleNotFoundError: No module 
named
   'superset.extensions.settings'`, which prevents `ExtensionsRestApi` from 
being imported
   and causes the initialization block in 
`superset/initialization/__init__.py:16-24` to
   fail, so the `/api/v1/extensions` endpoints (including list, post, delete, 
and settings)
   are never registered and any code depending on them (such as the 
ExtensionsList frontend
   using `/api/v1/extensions/settings` and `/api/v1/extensions/`) cannot 
function when the
   feature flag is enabled.
   ```
   </details>
   
   [Fix in 
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=e0447a741b35419f924c43ed1fa01968&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 | [Fix in VSCode 
Claude](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=e0447a741b35419f924c43ed1fa01968&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/extensions/api.py
   **Line:** 28:31
   **Comment:**
        *Import Error: This import references a module that does not exist in 
the current codebase (`superset/extensions/settings.py`), so importing 
`superset.extensions.api` will fail at runtime with `ModuleNotFoundError` and 
break the extensions API endpoints. Add the missing module in this PR or change 
the import to the correct existing path.
   
   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.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40450&comment_hash=f3e9a4d1cfa7f96f027e2fbd73a066d88fa13c62024eb9baa6fd228213a01cc3&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40450&comment_hash=f3e9a4d1cfa7f96f027e2fbd73a066d88fa13c62024eb9baa6fd228213a01cc3&reaction=dislike'>👎</a>



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