Преглед изворни кода

feat: support check dependencies through url

Yeuoly пре 6 месеци
родитељ
комит
183b943803
2 измењених фајлова са 38 додато и 2 уклоњено
  1. 17 0
      api/controllers/console/app/app.py
  2. 21 2
      api/services/app_dsl_service/service.py

+ 17 - 0
api/controllers/console/app/app.py

@@ -168,6 +168,22 @@ class AppImportFromUrlApi(Resource):
         return app, 201
 
 
+class AppImportFromUrlDependenciesCheckApi(Resource):
+    @setup_required
+    @login_required
+    @account_initialization_required
+    def post(self):
+        parser = reqparse.RequestParser()
+        parser.add_argument("url", type=str, required=True, nullable=False, location="json")
+        args = parser.parse_args()
+
+        leaked_dependencies = AppDslService.check_dependencies_from_url(
+            tenant_id=current_user.current_tenant_id, url=args["url"], account=current_user
+        )
+
+        return jsonable_encoder({"leaked": leaked_dependencies}), 200
+
+
 class AppApi(Resource):
     @setup_required
     @login_required
@@ -391,6 +407,7 @@ api.add_resource(AppListApi, "/apps")
 api.add_resource(AppImportDependenciesCheckApi, "/apps/import/dependencies/check")
 api.add_resource(AppImportApi, "/apps/import")
 api.add_resource(AppImportFromUrlApi, "/apps/import/url")
+api.add_resource(AppImportFromUrlDependenciesCheckApi, "/apps/import/url/dependencies/check")
 api.add_resource(AppApi, "/apps/<uuid:app_id>")
 api.add_resource(AppCopyApi, "/apps/<uuid:app_id>/copy")
 api.add_resource(AppExportApi, "/apps/<uuid:app_id>/export")

+ 21 - 2
api/services/app_dsl_service/service.py

@@ -37,6 +37,7 @@ from .exc import (
 logger = logging.getLogger(__name__)
 
 current_dsl_version = "0.1.3"
+dsl_max_size = 10 * 1024 * 1024  # 10MB
 
 
 class AppDslService:
@@ -49,12 +50,11 @@ class AppDslService:
         :param args: request args
         :param account: Account instance
         """
-        max_size = 10 * 1024 * 1024  # 10MB
         response = ssrf_proxy.get(url.strip(), follow_redirects=True, timeout=(10, 10))
         response.raise_for_status()
         content = response.content
 
-        if len(content) > max_size:
+        if len(content) > dsl_max_size:
             raise FileSizeLimitExceededError("File size exceeds the limit of 10MB")
 
         if not content:
@@ -68,6 +68,25 @@ class AppDslService:
         return cls.import_and_create_new_app(tenant_id, data, args, account)
 
     @classmethod
+    def check_dependencies_from_url(cls, tenant_id: str, url: str, account: Account) -> list[PluginDependency]:
+        """
+        Check dependencies from url
+        """
+        response = ssrf_proxy.get(url.strip(), follow_redirects=True, timeout=(10, 10))
+        response.raise_for_status()
+        content = response.content
+
+        if len(content) > dsl_max_size:
+            raise FileSizeLimitExceededError("File size exceeds the limit of 10MB")
+
+        try:
+            data = content.decode("utf-8")
+        except UnicodeDecodeError as e:
+            raise ContentDecodingError(f"Error decoding content: {e}")
+
+        return cls.check_dependencies(tenant_id, data, account)
+
+    @classmethod
     def check_dependencies(cls, tenant_id: str, data: str, account: Account) -> list[PluginDependency]:
         """
         Returns the leaked dependencies in current workspace