mirror of
https://github.com/langgenius/dify.git
synced 2026-09-19 10:11:30 +08:00
refactor: replace manual model_validate with @model_validate in workspace plugin/tool controllers (#40238)
This commit is contained in:
@@ -24,6 +24,7 @@ from controllers.console.wraps import (
|
||||
RBACResourceScope,
|
||||
account_initialization_required,
|
||||
is_admin_or_owner_required,
|
||||
model_validate,
|
||||
rbac_permission_required,
|
||||
setup_required,
|
||||
with_current_tenant_id,
|
||||
@@ -592,10 +593,10 @@ class PluginListApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user_id
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str, user_id: str):
|
||||
args = ParserList.model_validate(request.args.to_dict(flat=True))
|
||||
@model_validate(ParserList)
|
||||
def get(self, req_data: ParserList, tenant_id: str, user_id: str):
|
||||
try:
|
||||
plugins_with_total = PluginService.list_with_total(tenant_id, user_id, args.page, args.page_size)
|
||||
plugins_with_total = PluginService.list_with_total(tenant_id, user_id, req_data.page, req_data.page_size)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
|
||||
@@ -660,10 +661,10 @@ class PluginInstalledIdsApi(Resource):
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str):
|
||||
args = PluginInstalledIdsQuery.model_validate(request.args.to_dict(flat=True))
|
||||
@model_validate(PluginInstalledIdsQuery)
|
||||
def get(self, req_data: PluginInstalledIdsQuery, tenant_id: str):
|
||||
try:
|
||||
plugin_ids = PluginService.list_installed_plugin_ids(tenant_id, args.category)
|
||||
plugin_ids = PluginService.list_installed_plugin_ids(tenant_id, req_data.category)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
|
||||
@@ -677,11 +678,11 @@ class PluginListLatestVersionsApi(Resource):
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
def post(self):
|
||||
args = ParserLatest.model_validate(console_ns.payload)
|
||||
@model_validate(ParserLatest)
|
||||
def post(self, req_data: ParserLatest):
|
||||
|
||||
try:
|
||||
versions = PluginService.list_latest_versions(args.plugin_ids)
|
||||
versions = PluginService.list_latest_versions(req_data.plugin_ids)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
|
||||
@@ -696,11 +697,11 @@ class PluginListInstallationsFromIdsApi(Resource):
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str):
|
||||
args = ParserLatest.model_validate(console_ns.payload)
|
||||
@model_validate(ParserLatest)
|
||||
def post(self, req_data: ParserLatest, tenant_id: str):
|
||||
|
||||
try:
|
||||
plugins = PluginService.list_installations_from_ids(tenant_id, args.plugin_ids)
|
||||
plugins = PluginService.list_installations_from_ids(tenant_id, req_data.plugin_ids)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
|
||||
@@ -712,11 +713,11 @@ class PluginIconApi(Resource):
|
||||
@console_ns.doc(params=query_params_from_model(ParserIcon))
|
||||
@console_ns.response(200, "Success", console_ns.models[BinaryFileResponse.__name__])
|
||||
@setup_required
|
||||
def get(self):
|
||||
args = ParserIcon.model_validate(request.args.to_dict(flat=True))
|
||||
@model_validate(ParserIcon)
|
||||
def get(self, req_data: ParserIcon):
|
||||
|
||||
try:
|
||||
icon_bytes, mimetype = PluginService.get_asset(args.tenant_id, args.filename)
|
||||
icon_bytes, mimetype = PluginService.get_asset(req_data.tenant_id, req_data.filename)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
|
||||
@@ -732,11 +733,11 @@ class PluginAssetApi(Resource):
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str):
|
||||
args = ParserAsset.model_validate(request.args.to_dict(flat=True))
|
||||
@model_validate(ParserAsset)
|
||||
def get(self, req_data: ParserAsset, tenant_id: str):
|
||||
|
||||
try:
|
||||
binary = PluginService.extract_asset(tenant_id, args.plugin_unique_identifier, args.file_name)
|
||||
binary = PluginService.extract_asset(tenant_id, req_data.plugin_unique_identifier, req_data.file_name)
|
||||
return send_file(io.BytesIO(binary), mimetype="application/octet-stream")
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
@@ -773,11 +774,13 @@ class PluginUploadFromGithubApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_INSTALL, resource_required=False)
|
||||
@plugin_permission_required(install_required=True)
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str):
|
||||
args = ParserGithubUpload.model_validate(console_ns.payload)
|
||||
@model_validate(ParserGithubUpload)
|
||||
def post(self, req_data: ParserGithubUpload, tenant_id: str):
|
||||
|
||||
try:
|
||||
response = PluginService.upload_pkg_from_github(tenant_id, args.repo, args.version, args.package)
|
||||
response = PluginService.upload_pkg_from_github(
|
||||
tenant_id, req_data.repo, req_data.version, req_data.package
|
||||
)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
|
||||
@@ -814,11 +817,11 @@ class PluginInstallFromPkgApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_INSTALL, resource_required=False)
|
||||
@plugin_permission_required(install_required=True)
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str):
|
||||
args = ParserPluginIdentifiers.model_validate(console_ns.payload)
|
||||
@model_validate(ParserPluginIdentifiers)
|
||||
def post(self, req_data: ParserPluginIdentifiers, tenant_id: str):
|
||||
|
||||
try:
|
||||
response = PluginService.install_from_local_pkg(tenant_id, args.plugin_unique_identifiers)
|
||||
response = PluginService.install_from_local_pkg(tenant_id, req_data.plugin_unique_identifiers)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
|
||||
@@ -835,16 +838,16 @@ class PluginInstallFromGithubApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_INSTALL, resource_required=False)
|
||||
@plugin_permission_required(install_required=True)
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str):
|
||||
args = ParserGithubInstall.model_validate(console_ns.payload)
|
||||
@model_validate(ParserGithubInstall)
|
||||
def post(self, req_data: ParserGithubInstall, tenant_id: str):
|
||||
|
||||
try:
|
||||
response = PluginService.install_from_github(
|
||||
tenant_id,
|
||||
args.plugin_unique_identifier,
|
||||
args.repo,
|
||||
args.version,
|
||||
args.package,
|
||||
req_data.plugin_unique_identifier,
|
||||
req_data.repo,
|
||||
req_data.version,
|
||||
req_data.package,
|
||||
)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
@@ -862,11 +865,11 @@ class PluginInstallFromMarketplaceApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_INSTALL, resource_required=False)
|
||||
@plugin_permission_required(install_required=True)
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str):
|
||||
args = ParserPluginIdentifiers.model_validate(console_ns.payload)
|
||||
@model_validate(ParserPluginIdentifiers)
|
||||
def post(self, req_data: ParserPluginIdentifiers, tenant_id: str):
|
||||
|
||||
try:
|
||||
response = PluginService.install_from_marketplace_pkg(tenant_id, args.plugin_unique_identifiers)
|
||||
response = PluginService.install_from_marketplace_pkg(tenant_id, req_data.plugin_unique_identifiers)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
|
||||
@@ -883,15 +886,15 @@ class PluginFetchMarketplacePkgApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_INSTALL, resource_required=False)
|
||||
@plugin_permission_required(install_required=True)
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str):
|
||||
args = ParserPluginIdentifierQuery.model_validate(request.args.to_dict(flat=True))
|
||||
@model_validate(ParserPluginIdentifierQuery)
|
||||
def get(self, req_data: ParserPluginIdentifierQuery, tenant_id: str):
|
||||
|
||||
try:
|
||||
return jsonable_encoder(
|
||||
{
|
||||
"manifest": PluginService.fetch_marketplace_pkg(
|
||||
tenant_id,
|
||||
args.plugin_unique_identifier,
|
||||
req_data.plugin_unique_identifier,
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -909,12 +912,16 @@ class PluginFetchManifestApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_INSTALL, resource_required=False)
|
||||
@plugin_permission_required(install_required=True)
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str):
|
||||
args = ParserPluginIdentifierQuery.model_validate(request.args.to_dict(flat=True))
|
||||
@model_validate(ParserPluginIdentifierQuery)
|
||||
def get(self, req_data: ParserPluginIdentifierQuery, tenant_id: str):
|
||||
|
||||
try:
|
||||
return jsonable_encoder(
|
||||
{"manifest": PluginService.fetch_plugin_manifest(tenant_id, args.plugin_unique_identifier).model_dump()}
|
||||
{
|
||||
"manifest": PluginService.fetch_plugin_manifest(
|
||||
tenant_id, req_data.plugin_unique_identifier
|
||||
).model_dump()
|
||||
},
|
||||
)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
@@ -929,11 +936,13 @@ class PluginFetchInstallTasksApi(Resource):
|
||||
@account_initialization_required
|
||||
@plugin_permission_required(install_required=True)
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str):
|
||||
args = ParserTasks.model_validate(request.args.to_dict(flat=True))
|
||||
@model_validate(ParserTasks)
|
||||
def get(self, req_data: ParserTasks, tenant_id: str):
|
||||
|
||||
try:
|
||||
return jsonable_encoder({"tasks": PluginService.fetch_install_tasks(tenant_id, args.page, args.page_size)})
|
||||
return jsonable_encoder(
|
||||
{"tasks": PluginService.fetch_install_tasks(tenant_id, req_data.page, req_data.page_size)}
|
||||
)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
|
||||
@@ -1008,13 +1017,13 @@ class PluginUpgradeFromMarketplaceApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_MODEL_CONFIG, resource_required=False)
|
||||
@plugin_permission_required(install_required=True)
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str):
|
||||
args = ParserMarketplaceUpgrade.model_validate(console_ns.payload)
|
||||
@model_validate(ParserMarketplaceUpgrade)
|
||||
def post(self, req_data: ParserMarketplaceUpgrade, tenant_id: str):
|
||||
|
||||
try:
|
||||
return jsonable_encoder(
|
||||
PluginService.upgrade_plugin_with_marketplace(
|
||||
tenant_id, args.original_plugin_unique_identifier, args.new_plugin_unique_identifier
|
||||
tenant_id, req_data.original_plugin_unique_identifier, req_data.new_plugin_unique_identifier
|
||||
)
|
||||
)
|
||||
except PluginDaemonClientSideError as e:
|
||||
@@ -1031,18 +1040,18 @@ class PluginUpgradeFromGithubApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_MODEL_CONFIG, resource_required=False)
|
||||
@plugin_permission_required(install_required=True)
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str):
|
||||
args = ParserGithubUpgrade.model_validate(console_ns.payload)
|
||||
@model_validate(ParserGithubUpgrade)
|
||||
def post(self, req_data: ParserGithubUpgrade, tenant_id: str):
|
||||
|
||||
try:
|
||||
return jsonable_encoder(
|
||||
PluginService.upgrade_plugin_with_github(
|
||||
tenant_id,
|
||||
args.original_plugin_unique_identifier,
|
||||
args.new_plugin_unique_identifier,
|
||||
args.repo,
|
||||
args.version,
|
||||
args.package,
|
||||
req_data.original_plugin_unique_identifier,
|
||||
req_data.new_plugin_unique_identifier,
|
||||
req_data.repo,
|
||||
req_data.version,
|
||||
req_data.package,
|
||||
)
|
||||
)
|
||||
except PluginDaemonClientSideError as e:
|
||||
@@ -1059,15 +1068,15 @@ class PluginUninstallApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_DELETE, resource_required=False)
|
||||
@plugin_permission_required(install_required=True)
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str):
|
||||
args = ParserUninstall.model_validate(console_ns.payload)
|
||||
@model_validate(ParserUninstall)
|
||||
def post(self, req_data: ParserUninstall, tenant_id: str):
|
||||
|
||||
try:
|
||||
return {
|
||||
"success": PluginService.uninstall(
|
||||
tenant_id,
|
||||
args.plugin_installation_id,
|
||||
preserve_credentials=args.preserve_credentials,
|
||||
req_data.plugin_installation_id,
|
||||
preserve_credentials=req_data.preserve_credentials,
|
||||
)
|
||||
}
|
||||
except PluginDaemonClientSideError as e:
|
||||
@@ -1083,14 +1092,13 @@ class PluginChangePermissionApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account):
|
||||
@model_validate(ParserPermissionChange)
|
||||
def post(self, req_data: ParserPermissionChange, tenant_id: str, user: Account):
|
||||
if not user.is_admin_or_owner:
|
||||
raise Forbidden()
|
||||
|
||||
args = ParserPermissionChange.model_validate(console_ns.payload)
|
||||
|
||||
set_permission_result = PluginPermissionService.change_permission(
|
||||
tenant_id, args.install_permission, args.debug_permission, session=db.session()
|
||||
tenant_id, req_data.install_permission, req_data.debug_permission, session=db.session()
|
||||
)
|
||||
if not set_permission_result:
|
||||
return jsonable_encoder({"success": False, "message": "Failed to set permission"})
|
||||
@@ -1134,19 +1142,19 @@ class PluginFetchDynamicSelectOptionsApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str, current_user: Account):
|
||||
args = ParserDynamicOptions.model_validate(request.args.to_dict(flat=True))
|
||||
@model_validate(ParserDynamicOptions)
|
||||
def get(self, req_data: ParserDynamicOptions, tenant_id: str, current_user: Account):
|
||||
|
||||
try:
|
||||
options = PluginParameterService.get_dynamic_select_options(
|
||||
tenant_id=tenant_id,
|
||||
user_id=current_user.id,
|
||||
plugin_id=args.plugin_id,
|
||||
provider=args.provider,
|
||||
action=args.action,
|
||||
parameter=args.parameter,
|
||||
credential_id=args.credential_id,
|
||||
provider_type=args.provider_type,
|
||||
plugin_id=req_data.plugin_id,
|
||||
provider=req_data.provider,
|
||||
action=req_data.action,
|
||||
parameter=req_data.parameter,
|
||||
credential_id=req_data.credential_id,
|
||||
provider_type=req_data.provider_type,
|
||||
)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
@@ -1165,20 +1173,20 @@ class PluginFetchDynamicSelectOptionsWithCredentialsApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, current_user: Account):
|
||||
@model_validate(ParserDynamicOptionsWithCredentials)
|
||||
def post(self, req_data: ParserDynamicOptionsWithCredentials, tenant_id: str, current_user: Account):
|
||||
"""Fetch dynamic options using credentials directly (for edit mode)."""
|
||||
args = ParserDynamicOptionsWithCredentials.model_validate(console_ns.payload)
|
||||
|
||||
try:
|
||||
options = PluginParameterService.get_dynamic_select_options_with_credentials(
|
||||
tenant_id=tenant_id,
|
||||
user_id=current_user.id,
|
||||
plugin_id=args.plugin_id,
|
||||
provider=args.provider,
|
||||
action=args.action,
|
||||
parameter=args.parameter,
|
||||
credential_id=args.credential_id,
|
||||
credentials=args.credentials,
|
||||
plugin_id=req_data.plugin_id,
|
||||
provider=req_data.provider,
|
||||
action=req_data.action,
|
||||
parameter=req_data.parameter,
|
||||
credential_id=req_data.credential_id,
|
||||
credentials=req_data.credentials,
|
||||
)
|
||||
except PluginDaemonClientSideError as e:
|
||||
return {"code": "plugin_error", "message": e.description}, 400
|
||||
@@ -1196,13 +1204,12 @@ class PluginChangeAutoUpgradeApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_PREFERENCES, resource_required=False)
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account):
|
||||
@model_validate(ParserAutoUpgradeChange)
|
||||
def post(self, req_data: ParserAutoUpgradeChange, tenant_id: str, user: Account):
|
||||
if not dify_config.RBAC_ENABLED and not user.is_admin_or_owner:
|
||||
raise Forbidden()
|
||||
|
||||
args = ParserAutoUpgradeChange.model_validate(console_ns.payload)
|
||||
|
||||
auto_upgrade = args.auto_upgrade
|
||||
auto_upgrade = req_data.auto_upgrade
|
||||
set_auto_upgrade_strategy_result = PluginAutoUpgradeService.change_strategy(
|
||||
tenant_id,
|
||||
auto_upgrade.strategy_setting,
|
||||
@@ -1210,7 +1217,7 @@ class PluginChangeAutoUpgradeApi(Resource):
|
||||
auto_upgrade.upgrade_mode,
|
||||
auto_upgrade.exclude_plugins,
|
||||
auto_upgrade.include_plugins,
|
||||
category=args.category,
|
||||
category=req_data.category,
|
||||
session=db.session(),
|
||||
)
|
||||
if not set_auto_upgrade_strategy_result:
|
||||
@@ -1227,16 +1234,16 @@ class PluginFetchAutoUpgradeApi(Resource):
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str):
|
||||
args = ParserAutoUpgradeFetch.model_validate(request.args.to_dict(flat=True))
|
||||
auto_upgrade = PluginAutoUpgradeService.get_strategy(tenant_id, args.category, session=db.session())
|
||||
@model_validate(ParserAutoUpgradeFetch)
|
||||
def get(self, req_data: ParserAutoUpgradeFetch, tenant_id: str):
|
||||
auto_upgrade = PluginAutoUpgradeService.get_strategy(tenant_id, req_data.category, session=db.session())
|
||||
auto_upgrade_dict = (
|
||||
_auto_upgrade_settings_to_dict(auto_upgrade) if auto_upgrade else _missing_auto_upgrade_settings(tenant_id)
|
||||
)
|
||||
|
||||
return jsonable_encoder(
|
||||
{
|
||||
"category": args.category,
|
||||
"category": req_data.category,
|
||||
"auto_upgrade": auto_upgrade_dict,
|
||||
}
|
||||
)
|
||||
@@ -1251,14 +1258,14 @@ class PluginAutoUpgradeExcludePluginApi(Resource):
|
||||
@account_initialization_required
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.PLUGIN_PREFERENCES, resource_required=False)
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str):
|
||||
@model_validate(ParserExcludePlugin)
|
||||
def post(self, req_data: ParserExcludePlugin, tenant_id: str):
|
||||
# exclude one single plugin
|
||||
args = ParserExcludePlugin.model_validate(console_ns.payload)
|
||||
|
||||
return jsonable_encoder(
|
||||
{
|
||||
"success": PluginAutoUpgradeService.exclude_plugin(
|
||||
tenant_id, args.plugin_id, args.category, session=db.session()
|
||||
tenant_id, req_data.plugin_id, req_data.category, session=db.session()
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -1272,8 +1279,12 @@ class PluginReadmeApi(Resource):
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def get(self, tenant_id: str):
|
||||
args = ParserReadme.model_validate(request.args.to_dict(flat=True))
|
||||
@model_validate(ParserReadme)
|
||||
def get(self, req_data: ParserReadme, tenant_id: str):
|
||||
return jsonable_encoder(
|
||||
{"readme": PluginService.fetch_plugin_readme(tenant_id, args.plugin_unique_identifier, args.language)}
|
||||
{
|
||||
"readme": PluginService.fetch_plugin_readme(
|
||||
tenant_id, req_data.plugin_unique_identifier, req_data.language
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -33,6 +33,7 @@ from controllers.console.wraps import (
|
||||
account_initialization_required,
|
||||
enterprise_license_required,
|
||||
is_admin_or_owner_required,
|
||||
model_validate,
|
||||
rbac_permission_required,
|
||||
setup_required,
|
||||
with_current_tenant_id,
|
||||
@@ -555,16 +556,15 @@ class ToolBuiltinProviderDeleteApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.CREDENTIAL_MANAGE, resource_required=False)
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, provider: str):
|
||||
|
||||
payload = BuiltinToolCredentialDeletePayload.model_validate(console_ns.payload or {})
|
||||
@model_validate(BuiltinToolCredentialDeletePayload)
|
||||
def post(self, req_data: BuiltinToolCredentialDeletePayload, tenant_id: str, provider: str):
|
||||
|
||||
return dump_response(
|
||||
SimpleResultResponse,
|
||||
BuiltinToolManageService.delete_builtin_tool_provider(
|
||||
tenant_id,
|
||||
provider,
|
||||
payload.credential_id,
|
||||
req_data.credential_id,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -582,19 +582,18 @@ class ToolBuiltinProviderAddApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account, provider: str):
|
||||
payload = BuiltinToolAddPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
@model_validate(BuiltinToolAddPayload)
|
||||
def post(self, req_data: BuiltinToolAddPayload, tenant_id: str, user: Account, provider: str):
|
||||
return dump_response(
|
||||
SimpleResultResponse,
|
||||
BuiltinToolManageService.add_builtin_tool_provider(
|
||||
user_id=user.id,
|
||||
tenant_id=tenant_id,
|
||||
provider=provider,
|
||||
credentials=payload.credentials,
|
||||
name=payload.name,
|
||||
api_type=CredentialType.of(payload.type),
|
||||
visibility=payload.visibility,
|
||||
credentials=req_data.credentials,
|
||||
name=req_data.name,
|
||||
api_type=CredentialType.of(req_data.type),
|
||||
visibility=req_data.visibility,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -614,16 +613,15 @@ class ToolBuiltinProviderUpdateApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account, provider: str):
|
||||
payload = BuiltinToolUpdatePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
@model_validate(BuiltinToolUpdatePayload)
|
||||
def post(self, req_data: BuiltinToolUpdatePayload, tenant_id: str, user: Account, provider: str):
|
||||
result = BuiltinToolManageService.update_builtin_tool_provider(
|
||||
user_id=user.id,
|
||||
tenant_id=tenant_id,
|
||||
provider=provider,
|
||||
credential_id=payload.credential_id,
|
||||
credentials=payload.credentials,
|
||||
name=payload.name or "",
|
||||
credential_id=req_data.credential_id,
|
||||
credentials=req_data.credentials,
|
||||
name=req_data.name or "",
|
||||
)
|
||||
return dump_response(SimpleResultResponse, result)
|
||||
|
||||
@@ -683,22 +681,21 @@ class ToolApiProviderAddApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account):
|
||||
payload = ApiToolProviderAddPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
@model_validate(ApiToolProviderAddPayload)
|
||||
def post(self, req_data: ApiToolProviderAddPayload, tenant_id: str, user: Account):
|
||||
return dump_response(
|
||||
SimpleResultResponse,
|
||||
ApiToolManageService.create_api_tool_provider(
|
||||
user.id,
|
||||
tenant_id,
|
||||
payload.provider,
|
||||
payload.icon.model_dump(mode="json"),
|
||||
payload.credentials,
|
||||
payload.schema_type,
|
||||
payload.schema_,
|
||||
payload.privacy_policy or "",
|
||||
payload.custom_disclaimer or "",
|
||||
payload.labels or [],
|
||||
req_data.provider,
|
||||
req_data.icon.model_dump(mode="json"),
|
||||
req_data.credentials,
|
||||
req_data.schema_type,
|
||||
req_data.schema_,
|
||||
req_data.privacy_policy or "",
|
||||
req_data.custom_disclaimer or "",
|
||||
req_data.labels or [],
|
||||
),
|
||||
)
|
||||
|
||||
@@ -764,23 +761,22 @@ class ToolApiProviderUpdateApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account):
|
||||
payload = ApiToolProviderUpdatePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
@model_validate(ApiToolProviderUpdatePayload)
|
||||
def post(self, req_data: ApiToolProviderUpdatePayload, tenant_id: str, user: Account):
|
||||
return dump_response(
|
||||
SimpleResultResponse,
|
||||
ApiToolManageService.update_api_tool_provider(
|
||||
user.id,
|
||||
tenant_id,
|
||||
payload.provider,
|
||||
payload.original_provider,
|
||||
payload.icon.model_dump(mode="json"),
|
||||
payload.credentials,
|
||||
payload.schema_type,
|
||||
payload.schema_,
|
||||
payload.privacy_policy,
|
||||
payload.custom_disclaimer,
|
||||
payload.labels or [],
|
||||
req_data.provider,
|
||||
req_data.original_provider,
|
||||
req_data.icon.model_dump(mode="json"),
|
||||
req_data.credentials,
|
||||
req_data.schema_type,
|
||||
req_data.schema_,
|
||||
req_data.privacy_policy,
|
||||
req_data.custom_disclaimer,
|
||||
req_data.labels or [],
|
||||
),
|
||||
)
|
||||
|
||||
@@ -796,15 +792,14 @@ class ToolApiProviderDeleteApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account):
|
||||
payload = ApiToolProviderDeletePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
@model_validate(ApiToolProviderDeletePayload)
|
||||
def post(self, req_data: ApiToolProviderDeletePayload, tenant_id: str, user: Account):
|
||||
return dump_response(
|
||||
SimpleResultResponse,
|
||||
ApiToolManageService.delete_api_tool_provider(
|
||||
user.id,
|
||||
tenant_id,
|
||||
payload.provider,
|
||||
req_data.provider,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -861,10 +856,9 @@ class ToolApiProviderSchemaApi(Resource):
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
def post(self):
|
||||
payload = ApiToolSchemaPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
return dump_response(ApiSchemaParseResponse, ApiToolManageService.parser_api_schema(schema=payload.schema_))
|
||||
@model_validate(ApiToolSchemaPayload)
|
||||
def post(self, req_data: ApiToolSchemaPayload):
|
||||
return dump_response(ApiSchemaParseResponse, ApiToolManageService.parser_api_schema(schema=req_data.schema_))
|
||||
|
||||
|
||||
@console_ns.route("/workspaces/current/tool-provider/api/test/pre")
|
||||
@@ -879,18 +873,18 @@ class ToolApiProviderPreviousTestApi(Resource):
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def post(self, current_tenant_id: str):
|
||||
payload = ApiToolTestPayload.model_validate(console_ns.payload or {})
|
||||
@model_validate(ApiToolTestPayload)
|
||||
def post(self, req_data: ApiToolTestPayload, current_tenant_id: str):
|
||||
return dump_response(
|
||||
ApiToolPreviewResponse,
|
||||
ApiToolManageService.test_api_tool_preview(
|
||||
current_tenant_id,
|
||||
payload.provider_name or "",
|
||||
payload.tool_name,
|
||||
payload.credentials,
|
||||
payload.parameters,
|
||||
payload.schema_type,
|
||||
payload.schema_,
|
||||
req_data.provider_name or "",
|
||||
req_data.tool_name,
|
||||
req_data.credentials,
|
||||
req_data.parameters,
|
||||
req_data.schema_type,
|
||||
req_data.schema_,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -906,22 +900,21 @@ class ToolWorkflowProviderCreateApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account):
|
||||
payload = WorkflowToolCreatePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
@model_validate(WorkflowToolCreatePayload)
|
||||
def post(self, req_data: WorkflowToolCreatePayload, tenant_id: str, user: Account):
|
||||
return dump_response(
|
||||
SimpleResultResponse,
|
||||
WorkflowToolManageService.create_workflow_tool(
|
||||
user_id=user.id,
|
||||
tenant_id=tenant_id,
|
||||
workflow_app_id=payload.workflow_app_id,
|
||||
name=payload.name,
|
||||
label=payload.label,
|
||||
icon=payload.icon.model_dump(mode="json"),
|
||||
description=payload.description,
|
||||
parameters=payload.parameters,
|
||||
privacy_policy=payload.privacy_policy or "",
|
||||
labels=payload.labels or [],
|
||||
workflow_app_id=req_data.workflow_app_id,
|
||||
name=req_data.name,
|
||||
label=req_data.label,
|
||||
icon=req_data.icon.model_dump(mode="json"),
|
||||
description=req_data.description,
|
||||
parameters=req_data.parameters,
|
||||
privacy_policy=req_data.privacy_policy or "",
|
||||
labels=req_data.labels or [],
|
||||
),
|
||||
)
|
||||
|
||||
@@ -937,22 +930,21 @@ class ToolWorkflowProviderUpdateApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account):
|
||||
payload = WorkflowToolUpdatePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
@model_validate(WorkflowToolUpdatePayload)
|
||||
def post(self, req_data: WorkflowToolUpdatePayload, tenant_id: str, user: Account):
|
||||
return dump_response(
|
||||
SimpleResultResponse,
|
||||
WorkflowToolManageService.update_workflow_tool(
|
||||
user.id,
|
||||
tenant_id,
|
||||
payload.workflow_tool_id,
|
||||
payload.name,
|
||||
payload.label,
|
||||
payload.icon.model_dump(mode="json"),
|
||||
payload.description,
|
||||
payload.parameters,
|
||||
payload.privacy_policy or "",
|
||||
payload.labels or [],
|
||||
req_data.workflow_tool_id,
|
||||
req_data.name,
|
||||
req_data.label,
|
||||
req_data.icon.model_dump(mode="json"),
|
||||
req_data.description,
|
||||
req_data.parameters,
|
||||
req_data.privacy_policy or "",
|
||||
req_data.labels or [],
|
||||
),
|
||||
)
|
||||
|
||||
@@ -968,15 +960,14 @@ class ToolWorkflowProviderDeleteApi(Resource):
|
||||
@account_initialization_required
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account):
|
||||
payload = WorkflowToolDeletePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
@model_validate(WorkflowToolDeletePayload)
|
||||
def post(self, req_data: WorkflowToolDeletePayload, tenant_id: str, user: Account):
|
||||
return dump_response(
|
||||
SimpleResultResponse,
|
||||
WorkflowToolManageService.delete_workflow_tool(
|
||||
user.id,
|
||||
tenant_id,
|
||||
payload.workflow_tool_id,
|
||||
req_data.workflow_tool_id,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1224,12 +1215,12 @@ class ToolBuiltinProviderSetDefaultApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.CREDENTIAL_USE, resource_required=False)
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def post(self, current_tenant_id: str, provider: str):
|
||||
payload = BuiltinProviderDefaultCredentialPayload.model_validate(console_ns.payload or {})
|
||||
@model_validate(BuiltinProviderDefaultCredentialPayload)
|
||||
def post(self, req_data: BuiltinProviderDefaultCredentialPayload, current_tenant_id: str, provider: str):
|
||||
return dump_response(
|
||||
SimpleResultResponse,
|
||||
BuiltinToolManageService.set_default_provider(
|
||||
tenant_id=current_tenant_id, provider=provider, id=payload.id
|
||||
tenant_id=current_tenant_id, provider=provider, id=req_data.id
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1246,17 +1237,16 @@ class ToolOAuthCustomClient(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.CREDENTIAL_MANAGE, resource_required=False)
|
||||
@account_initialization_required
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, provider: str):
|
||||
payload = ToolOAuthCustomClientPayload.model_validate(console_ns.payload or {})
|
||||
|
||||
@model_validate(ToolOAuthCustomClientPayload)
|
||||
def post(self, req_data: ToolOAuthCustomClientPayload, tenant_id: str, provider: str):
|
||||
return dump_response(
|
||||
SimpleResultResponse,
|
||||
BuiltinToolManageService.save_custom_oauth_client_params(
|
||||
tenant_id=tenant_id,
|
||||
provider=provider,
|
||||
client_params=payload.client_params or {},
|
||||
enable_oauth_custom_client=payload.enable_oauth_custom_client
|
||||
if payload.enable_oauth_custom_client is not None
|
||||
client_params=req_data.client_params or {},
|
||||
enable_oauth_custom_client=req_data.enable_oauth_custom_client
|
||||
if req_data.enable_oauth_custom_client is not None
|
||||
else True,
|
||||
),
|
||||
)
|
||||
@@ -1349,11 +1339,10 @@ class ToolProviderMCPApi(Resource):
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.MCP_MANAGE, resource_required=False)
|
||||
@with_current_user
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, user: Account):
|
||||
payload = MCPProviderCreatePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
configuration = payload.configuration or MCPConfiguration()
|
||||
authentication = payload.authentication
|
||||
@model_validate(MCPProviderCreatePayload)
|
||||
def post(self, req_data: MCPProviderCreatePayload, tenant_id: str, user: Account):
|
||||
configuration = req_data.configuration or MCPConfiguration()
|
||||
authentication = req_data.authentication
|
||||
|
||||
# 1) Create provider in a short transaction (no network I/O inside)
|
||||
with session_factory.create_session() as session, session.begin():
|
||||
@@ -1361,24 +1350,24 @@ class ToolProviderMCPApi(Resource):
|
||||
result = service.create_provider(
|
||||
tenant_id=tenant_id,
|
||||
user_id=user.id,
|
||||
server_url=payload.server_url,
|
||||
name=payload.name,
|
||||
icon=payload.icon,
|
||||
icon_type=payload.icon_type,
|
||||
icon_background=payload.icon_background,
|
||||
server_identifier=payload.server_identifier,
|
||||
headers=payload.headers or {},
|
||||
server_url=req_data.server_url,
|
||||
name=req_data.name,
|
||||
icon=req_data.icon,
|
||||
icon_type=req_data.icon_type,
|
||||
icon_background=req_data.icon_background,
|
||||
server_identifier=req_data.server_identifier,
|
||||
headers=req_data.headers or {},
|
||||
configuration=configuration,
|
||||
authentication=authentication,
|
||||
identity_mode=_resolve_identity_mode(payload.identity_mode, current=IdentityMode.OFF),
|
||||
identity_mode=_resolve_identity_mode(req_data.identity_mode, current=IdentityMode.OFF),
|
||||
)
|
||||
|
||||
# 2) Try to fetch tools immediately after creation so they appear without a second save.
|
||||
# Perform network I/O outside any DB session to avoid holding locks.
|
||||
try:
|
||||
reconnect = MCPToolManageService.reconnect_with_url(
|
||||
server_url=payload.server_url,
|
||||
headers=payload.headers or {},
|
||||
server_url=req_data.server_url,
|
||||
headers=req_data.headers or {},
|
||||
timeout=configuration.timeout,
|
||||
sse_read_timeout=configuration.sse_read_timeout,
|
||||
)
|
||||
@@ -1403,24 +1392,24 @@ class ToolProviderMCPApi(Resource):
|
||||
@account_initialization_required
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.MCP_MANAGE, resource_required=False)
|
||||
@with_current_tenant_id
|
||||
def put(self, current_tenant_id: str):
|
||||
payload = MCPProviderUpdatePayload.model_validate(console_ns.payload or {})
|
||||
configuration = payload.configuration or MCPConfiguration()
|
||||
authentication = payload.authentication
|
||||
@model_validate(MCPProviderUpdatePayload)
|
||||
def put(self, req_data: MCPProviderUpdatePayload, current_tenant_id: str):
|
||||
configuration = req_data.configuration or MCPConfiguration()
|
||||
authentication = req_data.authentication
|
||||
|
||||
# Step 1: Get provider data for URL validation (short-lived session, no network I/O)
|
||||
validation_data = None
|
||||
with sessionmaker(db.engine).begin() as session:
|
||||
service = MCPToolManageService(session=session)
|
||||
validation_data = service.get_provider_for_url_validation(
|
||||
tenant_id=current_tenant_id, provider_id=payload.provider_id
|
||||
tenant_id=current_tenant_id, provider_id=req_data.provider_id
|
||||
)
|
||||
|
||||
# Step 2: Perform URL validation with network I/O OUTSIDE of any database session
|
||||
# This prevents holding database locks during potentially slow network operations
|
||||
validation_result = MCPToolManageService.validate_server_url_standalone(
|
||||
tenant_id=current_tenant_id,
|
||||
new_server_url=payload.server_url,
|
||||
new_server_url=req_data.server_url,
|
||||
validation_data=validation_data,
|
||||
)
|
||||
|
||||
@@ -1430,18 +1419,18 @@ class ToolProviderMCPApi(Resource):
|
||||
# Resolve "leave unchanged" (None) against the stored value, and gate
|
||||
# the result on ENTERPRISE_ENABLED — both are API-layer concerns, so
|
||||
# the service receives a concrete IdentityMode.
|
||||
existing = service.get_provider(provider_id=payload.provider_id, tenant_id=current_tenant_id)
|
||||
identity_mode = _resolve_identity_mode(payload.identity_mode, current=IdentityMode(existing.identity_mode))
|
||||
existing = service.get_provider(provider_id=req_data.provider_id, tenant_id=current_tenant_id)
|
||||
identity_mode = _resolve_identity_mode(req_data.identity_mode, current=IdentityMode(existing.identity_mode))
|
||||
service.update_provider(
|
||||
tenant_id=current_tenant_id,
|
||||
provider_id=payload.provider_id,
|
||||
server_url=payload.server_url,
|
||||
name=payload.name,
|
||||
icon=payload.icon,
|
||||
icon_type=payload.icon_type,
|
||||
icon_background=payload.icon_background,
|
||||
server_identifier=payload.server_identifier,
|
||||
headers=payload.headers or {},
|
||||
provider_id=req_data.provider_id,
|
||||
server_url=req_data.server_url,
|
||||
name=req_data.name,
|
||||
icon=req_data.icon,
|
||||
icon_type=req_data.icon_type,
|
||||
icon_background=req_data.icon_background,
|
||||
server_identifier=req_data.server_identifier,
|
||||
headers=req_data.headers or {},
|
||||
configuration=configuration,
|
||||
authentication=authentication,
|
||||
validation_result=validation_result,
|
||||
@@ -1457,12 +1446,11 @@ class ToolProviderMCPApi(Resource):
|
||||
@account_initialization_required
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.MCP_MANAGE, resource_required=False)
|
||||
@with_current_tenant_id
|
||||
def delete(self, current_tenant_id: str):
|
||||
payload = MCPProviderDeletePayload.model_validate(console_ns.payload or {})
|
||||
|
||||
@model_validate(MCPProviderDeletePayload)
|
||||
def delete(self, req_data: MCPProviderDeletePayload, current_tenant_id: str):
|
||||
with sessionmaker(db.engine).begin() as session:
|
||||
service = MCPToolManageService(session=session)
|
||||
service.delete_provider(tenant_id=current_tenant_id, provider_id=payload.provider_id)
|
||||
service.delete_provider(tenant_id=current_tenant_id, provider_id=req_data.provider_id)
|
||||
|
||||
return SimpleResultResponse(result="success").model_dump(mode="json")
|
||||
|
||||
@@ -1476,9 +1464,9 @@ class ToolMCPAuthApi(Resource):
|
||||
@account_initialization_required
|
||||
@rbac_permission_required(RBACResourceScope.WORKSPACE, RBACPermission.MCP_MANAGE, resource_required=False)
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str):
|
||||
payload = MCPAuthPayload.model_validate(console_ns.payload or {})
|
||||
provider_id = payload.provider_id
|
||||
@model_validate(MCPAuthPayload)
|
||||
def post(self, req_data: MCPAuthPayload, tenant_id: str):
|
||||
provider_id = req_data.provider_id
|
||||
|
||||
with sessionmaker(db.engine).begin() as session:
|
||||
service = MCPToolManageService(session=session)
|
||||
@@ -1515,7 +1503,7 @@ class ToolMCPAuthApi(Resource):
|
||||
# Pass the extracted OAuth metadata hints to auth()
|
||||
auth_result = auth(
|
||||
provider_entity,
|
||||
payload.authorization_code,
|
||||
req_data.authorization_code,
|
||||
resource_metadata_url=e.resource_metadata_url,
|
||||
scope_hint=e.scope_hint,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user