|
@@ -1,7 +1,10 @@
|
|
|
import uuid
|
|
|
+from typing import cast
|
|
|
|
|
|
from flask_login import current_user
|
|
|
from flask_restful import Resource, inputs, marshal, marshal_with, reqparse
|
|
|
+from sqlalchemy import select
|
|
|
+from sqlalchemy.orm import Session
|
|
|
from werkzeug.exceptions import BadRequest, Forbidden, abort
|
|
|
|
|
|
from controllers.console import api
|
|
@@ -12,15 +15,16 @@ from controllers.console.wraps import (
|
|
|
enterprise_license_required,
|
|
|
setup_required,
|
|
|
)
|
|
|
-from core.model_runtime.utils.encoders import jsonable_encoder
|
|
|
from core.ops.ops_trace_manager import OpsTraceManager
|
|
|
+from extensions.ext_database import db
|
|
|
from fields.app_fields import (
|
|
|
app_detail_fields,
|
|
|
app_detail_fields_with_site,
|
|
|
app_pagination_fields,
|
|
|
)
|
|
|
from libs.login import login_required
|
|
|
-from services.app_dsl_service import AppDslService
|
|
|
+from models import Account, App
|
|
|
+from services.app_dsl_service import AppDslService, ImportMode
|
|
|
from services.app_service import AppService
|
|
|
|
|
|
ALLOW_CREATE_APP_MODES = ["chat", "agent-chat", "advanced-chat", "workflow", "completion"]
|
|
@@ -93,99 +97,6 @@ class AppListApi(Resource):
|
|
|
return app, 201
|
|
|
|
|
|
|
|
|
-class AppImportDependenciesCheckApi(Resource):
|
|
|
- @setup_required
|
|
|
- @login_required
|
|
|
- @account_initialization_required
|
|
|
- @cloud_edition_billing_resource_check("apps")
|
|
|
- def post(self):
|
|
|
- """Check dependencies"""
|
|
|
- # The role of the current user in the ta table must be admin, owner, or editor
|
|
|
- if not current_user.is_editor:
|
|
|
- raise Forbidden()
|
|
|
-
|
|
|
- parser = reqparse.RequestParser()
|
|
|
- parser.add_argument("data", type=str, required=True, nullable=False, location="json")
|
|
|
- args = parser.parse_args()
|
|
|
-
|
|
|
- leaked_dependencies = AppDslService.check_dependencies(
|
|
|
- tenant_id=current_user.current_tenant_id, data=args["data"], account=current_user
|
|
|
- )
|
|
|
-
|
|
|
- return jsonable_encoder({"leaked": leaked_dependencies}), 200
|
|
|
-
|
|
|
-
|
|
|
-class AppImportApi(Resource):
|
|
|
- @setup_required
|
|
|
- @login_required
|
|
|
- @account_initialization_required
|
|
|
- @marshal_with(app_detail_fields_with_site)
|
|
|
- @cloud_edition_billing_resource_check("apps")
|
|
|
- def post(self):
|
|
|
- """Import app"""
|
|
|
- # The role of the current user in the ta table must be admin, owner, or editor
|
|
|
- if not current_user.is_editor:
|
|
|
- raise Forbidden()
|
|
|
-
|
|
|
- parser = reqparse.RequestParser()
|
|
|
- parser.add_argument("data", type=str, required=True, nullable=False, location="json")
|
|
|
- parser.add_argument("name", type=str, location="json")
|
|
|
- parser.add_argument("description", type=str, location="json")
|
|
|
- parser.add_argument("icon_type", type=str, location="json")
|
|
|
- parser.add_argument("icon", type=str, location="json")
|
|
|
- parser.add_argument("icon_background", type=str, location="json")
|
|
|
- args = parser.parse_args()
|
|
|
-
|
|
|
- app = AppDslService.import_and_create_new_app(
|
|
|
- tenant_id=current_user.current_tenant_id, data=args["data"], args=args, account=current_user
|
|
|
- )
|
|
|
-
|
|
|
- return app, 201
|
|
|
-
|
|
|
-
|
|
|
-class AppImportFromUrlApi(Resource):
|
|
|
- @setup_required
|
|
|
- @login_required
|
|
|
- @account_initialization_required
|
|
|
- @marshal_with(app_detail_fields_with_site)
|
|
|
- @cloud_edition_billing_resource_check("apps")
|
|
|
- def post(self):
|
|
|
- """Import app from url"""
|
|
|
- # The role of the current user in the ta table must be admin, owner, or editor
|
|
|
- if not current_user.is_editor:
|
|
|
- raise Forbidden()
|
|
|
-
|
|
|
- parser = reqparse.RequestParser()
|
|
|
- parser.add_argument("url", type=str, required=True, nullable=False, location="json")
|
|
|
- parser.add_argument("name", type=str, location="json")
|
|
|
- parser.add_argument("description", type=str, location="json")
|
|
|
- parser.add_argument("icon", type=str, location="json")
|
|
|
- parser.add_argument("icon_background", type=str, location="json")
|
|
|
- args = parser.parse_args()
|
|
|
-
|
|
|
- app = AppDslService.import_and_create_new_app_from_url(
|
|
|
- tenant_id=current_user.current_tenant_id, url=args["url"], args=args, account=current_user
|
|
|
- )
|
|
|
-
|
|
|
- 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
|
|
@@ -263,10 +174,24 @@ class AppCopyApi(Resource):
|
|
|
parser.add_argument("icon_background", type=str, location="json")
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
- data = AppDslService.export_dsl(app_model=app_model, include_secret=True)
|
|
|
- app = AppDslService.import_and_create_new_app(
|
|
|
- tenant_id=current_user.current_tenant_id, data=data, args=args, account=current_user
|
|
|
- )
|
|
|
+ with Session(db.engine) as session:
|
|
|
+ import_service = AppDslService(session)
|
|
|
+ yaml_content = import_service.export_dsl(app_model=app_model, include_secret=True)
|
|
|
+ account = cast(Account, current_user)
|
|
|
+ result = import_service.import_app(
|
|
|
+ account=account,
|
|
|
+ import_mode=ImportMode.YAML_CONTENT.value,
|
|
|
+ yaml_content=yaml_content,
|
|
|
+ name=args.get("name"),
|
|
|
+ description=args.get("description"),
|
|
|
+ icon_type=args.get("icon_type"),
|
|
|
+ icon=args.get("icon"),
|
|
|
+ icon_background=args.get("icon_background"),
|
|
|
+ )
|
|
|
+ session.commit()
|
|
|
+
|
|
|
+ stmt = select(App).where(App.id == result.app.id)
|
|
|
+ app = session.scalar(stmt)
|
|
|
|
|
|
return app, 201
|
|
|
|
|
@@ -407,10 +332,6 @@ class AppTraceApi(Resource):
|
|
|
|
|
|
|
|
|
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")
|