Yeuoly пре 8 месеци
родитељ
комит
43ffccc8fd

+ 28 - 7
api/controllers/console/workspace/plugin.py

@@ -128,10 +128,15 @@ class PluginInstallFromPkgApi(Resource):
         tenant_id = user.current_tenant_id
 
         parser = reqparse.RequestParser()
-        parser.add_argument("plugin_unique_identifier", type=str, required=True, location="json")
+        parser.add_argument("plugin_unique_identifiers", type=list, required=True, location="json")
         args = parser.parse_args()
 
-        response = PluginService.install_from_local_pkg(tenant_id, args["plugin_unique_identifier"])
+        # check if all plugin_unique_identifiers are valid string
+        for plugin_unique_identifier in args["plugin_unique_identifiers"]:
+            if not isinstance(plugin_unique_identifier, str):
+                raise ValueError("Invalid plugin unique identifier")
+
+        response = PluginService.install_from_local_pkg(tenant_id, args["plugin_unique_identifiers"])
 
         return response.model_dump()
 
@@ -155,7 +160,11 @@ class PluginInstallFromGithubApi(Resource):
         args = parser.parse_args()
 
         response = PluginService.install_from_github(
-            tenant_id, args["repo"], args["version"], args["package"], args["plugin_unique_identifier"]
+            tenant_id,
+            args["plugin_unique_identifier"],
+            args["repo"],
+            args["version"],
+            args["package"],
         )
 
         return response.model_dump()
@@ -173,10 +182,15 @@ class PluginInstallFromMarketplaceApi(Resource):
         tenant_id = user.current_tenant_id
 
         parser = reqparse.RequestParser()
-        parser.add_argument("plugin_unique_identifier", type=str, required=True, location="json")
+        parser.add_argument("plugin_unique_identifiers", type=list, required=True, location="json")
         args = parser.parse_args()
 
-        response = PluginService.install_from_marketplace_pkg(tenant_id, args["plugin_unique_identifier"])
+        # check if all plugin_unique_identifiers are valid string
+        for plugin_unique_identifier in args["plugin_unique_identifiers"]:
+            if not isinstance(plugin_unique_identifier, str):
+                raise ValueError("Invalid plugin unique identifier")
+
+        response = PluginService.install_from_marketplace_pkg(tenant_id, args["plugin_unique_identifiers"])
 
         return response.model_dump()
 
@@ -210,7 +224,14 @@ class PluginFetchInstallTasksApi(Resource):
 
         tenant_id = user.current_tenant_id
 
-        return {"tasks": PluginService.fetch_install_tasks(tenant_id)}
+        parser = reqparse.RequestParser()
+        parser.add_argument("page", type=int, required=True, location="args")
+        parser.add_argument("page_size", type=int, required=True, location="args")
+        args = parser.parse_args()
+
+        return jsonable_encoder(
+            {"tasks": PluginService.fetch_install_tasks(tenant_id, args["page"], args["page_size"])}
+        )
 
 
 class PluginFetchInstallTaskApi(Resource):
@@ -224,7 +245,7 @@ class PluginFetchInstallTaskApi(Resource):
 
         tenant_id = user.current_tenant_id
 
-        return {"task": PluginService.fetch_install_task(tenant_id, task_id)}
+        return jsonable_encoder({"task": PluginService.fetch_install_task(tenant_id, task_id)})
 
 
 class PluginUninstallApi(Resource):

+ 1 - 1
api/core/plugin/entities/plugin_daemon.py

@@ -130,6 +130,6 @@ class PluginInstallTask(BasePluginEntity):
     plugins: list[PluginInstallTaskPluginStatus] = Field(description="The status of the plugins.")
 
 
-class PluginInstallTaskStartResponse(BasePluginEntity):
+class PluginInstallTaskStartResponse(BaseModel):
     all_installed: bool = Field(description="Whether all plugins are installed.")
     task_id: str = Field(description="The ID of the install task.")

+ 2 - 1
api/core/plugin/manager/plugin.py

@@ -72,7 +72,7 @@ class PluginInstallationManager(BasePluginManager):
             headers={"Content-Type": "application/json"},
         )
 
-    def fetch_plugin_installation_tasks(self, tenant_id: str) -> Sequence[PluginInstallTask]:
+    def fetch_plugin_installation_tasks(self, tenant_id: str, page: int, page_size: int) -> Sequence[PluginInstallTask]:
         """
         Fetch plugin installation tasks.
         """
@@ -80,6 +80,7 @@ class PluginInstallationManager(BasePluginManager):
             "GET",
             f"plugin/{tenant_id}/management/install/tasks",
             list[PluginInstallTask],
+            params={"page": page, "page_size": page_size},
         )
 
     def fetch_plugin_installation_task(self, tenant_id: str, task_id: str) -> PluginInstallTask:

+ 23 - 13
api/services/plugin/plugin_service.py

@@ -51,9 +51,9 @@ class PluginService:
         return manager.fetch_plugin_manifest(tenant_id, plugin_unique_identifier)
 
     @staticmethod
-    def fetch_install_tasks(tenant_id: str) -> Sequence[PluginInstallTask]:
+    def fetch_install_tasks(tenant_id: str, page: int, page_size: int) -> Sequence[PluginInstallTask]:
         manager = PluginInstallationManager()
-        return manager.fetch_plugin_installation_tasks(tenant_id)
+        return manager.fetch_plugin_installation_tasks(tenant_id, page, page_size)
 
     @staticmethod
     def fetch_install_task(tenant_id: str, task_id: str) -> PluginInstallTask:
@@ -61,17 +61,19 @@ class PluginService:
         return manager.fetch_plugin_installation_task(tenant_id, task_id)
 
     @staticmethod
-    def upload_pkg(tenant_id: str, pkg: bytes) -> str:
+    def upload_pkg(tenant_id: str, pkg: bytes, verify_signature: bool = False) -> str:
         """
         Upload plugin package files
 
         returns: plugin_unique_identifier
         """
         manager = PluginInstallationManager()
-        return manager.upload_pkg(tenant_id, pkg)
+        return manager.upload_pkg(tenant_id, pkg, verify_signature)
 
     @staticmethod
-    def upload_pkg_from_github(tenant_id: str, repo: str, version: str, package: str) -> str:
+    def upload_pkg_from_github(
+        tenant_id: str, repo: str, version: str, package: str, verify_signature: bool = False
+    ) -> str:
         """
         Install plugin from github release package files,
         returns plugin_unique_identifier
@@ -84,14 +86,15 @@ class PluginService:
         return manager.upload_pkg(
             tenant_id,
             pkg,
+            verify_signature,
         )
 
     @staticmethod
-    def install_from_local_pkg(tenant_id: str, plugin_unique_identifier: str):
+    def install_from_local_pkg(tenant_id: str, plugin_unique_identifiers: Sequence[str]):
         manager = PluginInstallationManager()
         return manager.install_from_identifiers(
             tenant_id,
-            [plugin_unique_identifier],
+            plugin_unique_identifiers,
             PluginInstallationSource.Package,
             {},
         )
@@ -115,21 +118,28 @@ class PluginService:
         )
 
     @staticmethod
-    def install_from_marketplace_pkg(tenant_id: str, plugin_unique_identifier: str):
+    def install_from_marketplace_pkg(
+        tenant_id: str, plugin_unique_identifiers: Sequence[str], verify_signature: bool = False
+    ):
         """
         Install plugin from marketplace package files,
         returns installation task id
         """
         manager = PluginInstallationManager()
 
-        pkg = download_plugin_pkg(plugin_unique_identifier)
-
-        # upload pkg to plugin daemon
-        pkg_id = manager.upload_pkg(tenant_id, pkg)
+        # check if already downloaded
+        for plugin_unique_identifier in plugin_unique_identifiers:
+            try:
+                manager.fetch_plugin_manifest(tenant_id, plugin_unique_identifier)
+                # already downloaded, skip
+            except Exception:
+                # plugin not installed, download and upload pkg
+                pkg = download_plugin_pkg(plugin_unique_identifier)
+                manager.upload_pkg(tenant_id, pkg, verify_signature)
 
         return manager.install_from_identifiers(
             tenant_id,
-            [pkg_id],
+            plugin_unique_identifiers,
             PluginInstallationSource.Marketplace,
             {
                 "plugin_unique_identifier": plugin_unique_identifier,