From 60921d2587bd0db2e299149fd4e04e559471c31c Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Mon, 8 Dec 2025 21:43:05 +0900 Subject: [PATCH] based on gemini's advice --- .../console/workspace/tool_providers.py | 2 +- api/controllers/web/app.py | 7 +++- api/controllers/web/conversation.py | 8 ++++- api/controllers/web/forgot_password.py | 4 +++ api/controllers/web/login.py | 4 +++ api/controllers/web/message.py | 33 +++++++++++++++++-- api/controllers/web/remote_files.py | 9 +++-- api/controllers/web/saved_message.py | 4 +++ api/controllers/web/workflow.py | 3 ++ .../tools/api_tools_manage_service.py | 2 +- 10 files changed, 68 insertions(+), 8 deletions(-) diff --git a/api/controllers/console/workspace/tool_providers.py b/api/controllers/console/workspace/tool_providers.py index 8fa52608de..c462467c15 100644 --- a/api/controllers/console/workspace/tool_providers.py +++ b/api/controllers/console/workspace/tool_providers.py @@ -128,7 +128,7 @@ class WorkflowToolBasePayload(BaseModel): label: str description: str icon: dict[str, Any] - parameters: list[WorkflowToolParameterConfiguration] + parameters: list[WorkflowToolParameterConfiguration] = Field(default_factory=list) privacy_policy: str | None = "" labels: list[str] | None = None diff --git a/api/controllers/web/app.py b/api/controllers/web/app.py index b8eefcb1e0..db3b93a4dc 100644 --- a/api/controllers/web/app.py +++ b/api/controllers/web/app.py @@ -95,7 +95,12 @@ class AppMeta(WebApiResource): class AppAccessMode(Resource): @web_ns.doc("Get App Access Mode") @web_ns.doc(description="Retrieve the access mode for a web application (public or restricted).") - @web_ns.expect(web_ns.models[AppAccessModeQuery.__name__]) + @web_ns.doc( + params={ + "appId": {"description": "Application ID", "type": "string", "required": False}, + "appCode": {"description": "Application code", "type": "string", "required": False}, + } + ) @web_ns.doc( responses={ 200: "Success", diff --git a/api/controllers/web/conversation.py b/api/controllers/web/conversation.py index 21f48ebb36..bf197a6601 100644 --- a/api/controllers/web/conversation.py +++ b/api/controllers/web/conversation.py @@ -6,6 +6,7 @@ from pydantic import BaseModel, Field, field_validator from sqlalchemy.orm import Session from werkzeug.exceptions import NotFound +from controllers.common.schema import register_schema_models from controllers.web import web_ns from controllers.web.error import NotChatAppError from controllers.web.wraps import WebApiResource @@ -38,6 +39,9 @@ class ConversationRenamePayload(BaseModel): auto_generate: bool = False +register_schema_models(web_ns, ConversationListQuery, ConversationRenamePayload) + + @web_ns.route("/conversations") class ConversationListApi(WebApiResource): @web_ns.doc("Get Conversation List") @@ -171,7 +175,9 @@ class ConversationRenameApi(WebApiResource): payload = ConversationRenamePayload.model_validate(web_ns.payload or {}) try: - return ConversationService.rename(app_model, conversation_id, end_user, payload.name, payload.auto_generate) # type: ignore + return ConversationService.rename( + app_model, conversation_id, end_user, payload.name or "", payload.auto_generate + ) except ConversationNotExistsError: raise NotFound("Conversation Not Exists.") diff --git a/api/controllers/web/forgot_password.py b/api/controllers/web/forgot_password.py index 6f22171c67..2b16513dd9 100644 --- a/api/controllers/web/forgot_password.py +++ b/api/controllers/web/forgot_password.py @@ -7,6 +7,7 @@ from pydantic import BaseModel, Field, field_validator from sqlalchemy import select from sqlalchemy.orm import Session +from controllers.common.schema import register_schema_models from controllers.console.auth.error import ( AuthenticationFailedError, EmailCodeError, @@ -47,6 +48,9 @@ class ForgotPasswordResetPayload(BaseModel): return valid_password(value) +register_schema_models(web_ns, ForgotPasswordSendPayload, ForgotPasswordCheckPayload, ForgotPasswordResetPayload) + + @web_ns.route("/forgot-password") class ForgotPasswordSendEmailApi(Resource): @only_edition_enterprise diff --git a/api/controllers/web/login.py b/api/controllers/web/login.py index 861ca27fc9..9c0d1973a9 100644 --- a/api/controllers/web/login.py +++ b/api/controllers/web/login.py @@ -5,6 +5,7 @@ from pydantic import BaseModel, Field, field_validator import services from configs import dify_config +from controllers.common.schema import register_schema_models from controllers.console.auth.error import ( AuthenticationFailedError, EmailCodeError, @@ -47,6 +48,9 @@ class EmailCodeLoginVerifyPayload(BaseModel): token: str = Field(min_length=1) +register_schema_models(web_ns, LoginPayload, EmailCodeLoginSendPayload, EmailCodeLoginVerifyPayload) + + @web_ns.route("/login") class LoginApi(Resource): """Resource for web app email/password login.""" diff --git a/api/controllers/web/message.py b/api/controllers/web/message.py index 1a7327ef26..5c7ea9e69a 100644 --- a/api/controllers/web/message.py +++ b/api/controllers/web/message.py @@ -6,6 +6,7 @@ from flask_restx import fields, marshal_with from pydantic import BaseModel, Field, field_validator from werkzeug.exceptions import InternalServerError, NotFound +from controllers.common.schema import register_schema_models from controllers.web import web_ns from controllers.web.error import ( AppMoreLikeThisDisabledError, @@ -64,6 +65,9 @@ class MessageMoreLikeThisQuery(BaseModel): ) +register_schema_models(web_ns, MessageListQuery, MessageFeedbackPayload, MessageMoreLikeThisQuery) + + @web_ns.route("/messages") class MessageListApi(WebApiResource): message_fields = { @@ -91,7 +95,22 @@ class MessageListApi(WebApiResource): @web_ns.doc("Get Message List") @web_ns.doc(description="Retrieve paginated list of messages from a conversation in a chat application.") - @web_ns.expect(web_ns.models[MessageListQuery.__name__]) + @web_ns.doc( + params={ + "conversation_id": {"description": "Conversation UUID", "type": "string", "required": True}, + "first_id": { + "description": "First message ID for pagination", + "type": "string", + "required": False, + }, + "limit": { + "description": "Number of messages to return (1-100)", + "type": "integer", + "required": False, + "default": 20, + }, + } + ) @web_ns.doc( responses={ 200: "Success", @@ -130,7 +149,17 @@ class MessageFeedbackApi(WebApiResource): @web_ns.doc("Create Message Feedback") @web_ns.doc(description="Submit feedback (like/dislike) for a specific message.") @web_ns.doc(params={"message_id": {"description": "Message UUID", "type": "string", "required": True}}) - @web_ns.expect(web_ns.models[MessageFeedbackPayload.__name__]) + @web_ns.doc( + params={ + "rating": { + "description": "Feedback rating", + "type": "string", + "enum": ["like", "dislike"], + "required": False, + }, + "content": {"description": "Feedback content", "type": "string", "required": False}, + } + ) @web_ns.doc( responses={ 200: "Feedback submitted successfully", diff --git a/api/controllers/web/remote_files.py b/api/controllers/web/remote_files.py index fed8df40b0..c1f976829f 100644 --- a/api/controllers/web/remote_files.py +++ b/api/controllers/web/remote_files.py @@ -11,19 +11,24 @@ from controllers.common.errors import ( RemoteFileUploadError, UnsupportedFileTypeError, ) -from controllers.web import web_ns -from controllers.web.wraps import WebApiResource from core.file import helpers as file_helpers from core.helper import ssrf_proxy from extensions.ext_database import db from fields.file_fields import build_file_with_signed_url_model, build_remote_file_info_model from services.file_service import FileService +from ..common.schema import register_schema_models +from . import web_ns +from .wraps import WebApiResource + class RemoteFileUploadPayload(BaseModel): url: HttpUrl = Field(description="Remote file URL") +register_schema_models(web_ns, RemoteFileUploadPayload) + + @web_ns.route("/remote-files/") class RemoteFileInfoApi(WebApiResource): @web_ns.doc("get_remote_file_info") diff --git a/api/controllers/web/saved_message.py b/api/controllers/web/saved_message.py index 4d3b190f7c..f3fe7a0aca 100644 --- a/api/controllers/web/saved_message.py +++ b/api/controllers/web/saved_message.py @@ -3,6 +3,7 @@ from flask_restx import fields, marshal_with from pydantic import BaseModel, Field, field_validator from werkzeug.exceptions import NotFound +from controllers.common.schema import register_schema_models from controllers.web import web_ns from controllers.web.error import NotCompletionAppError from controllers.web.wraps import WebApiResource @@ -45,6 +46,9 @@ class SavedMessageCreatePayload(BaseModel): return uuid_value(value) +register_schema_models(web_ns, SavedMessageListQuery, SavedMessageCreatePayload) + + @web_ns.route("/saved-messages") class SavedMessageListApi(WebApiResource): saved_message_infinite_scroll_pagination_fields = { diff --git a/api/controllers/web/workflow.py b/api/controllers/web/workflow.py index 136f93c574..a62c27a033 100644 --- a/api/controllers/web/workflow.py +++ b/api/controllers/web/workflow.py @@ -4,6 +4,7 @@ from typing import Any from pydantic import BaseModel from werkzeug.exceptions import InternalServerError +from controllers.common.schema import register_schema_models from controllers.web import web_ns from controllers.web.error import ( CompletionRequestError, @@ -36,6 +37,8 @@ class WorkflowRunPayload(BaseModel): logger = logging.getLogger(__name__) +register_schema_models(web_ns, WorkflowRunPayload) + @web_ns.route("/workflows/run") class WorkflowRunApi(WebApiResource): diff --git a/api/services/tools/api_tools_manage_service.py b/api/services/tools/api_tools_manage_service.py index 82570afca1..73d9095580 100644 --- a/api/services/tools/api_tools_manage_service.py +++ b/api/services/tools/api_tools_manage_service.py @@ -254,7 +254,7 @@ class ApiToolManageService: """ update api tool provider """ - if schema_type not in list(ApiProviderSchemaType): + if schema_type not in ApiProviderSchemaType: raise ValueError(f"invalid schema type {schema}") provider_name = provider_name.strip()