diff --git a/api/configs/app_config.py b/api/configs/app_config.py index e5edc86bc3..38921affd9 100644 --- a/api/configs/app_config.py +++ b/api/configs/app_config.py @@ -1,3 +1,4 @@ +from pydantic import computed_field from pydantic_settings import BaseSettings, SettingsConfigDict from configs.deploy import DeploymentConfig @@ -43,3 +44,28 @@ class DifyConfig( # ignore extra attributes extra='ignore', ) + + CODE_MAX_NUMBER: int = 9223372036854775807 + CODE_MIN_NUMBER: int = -9223372036854775808 + CODE_MAX_STRING_LENGTH: int = 80000 + CODE_MAX_STRING_ARRAY_LENGTH: int = 30 + CODE_MAX_OBJECT_ARRAY_LENGTH: int = 30 + CODE_MAX_NUMBER_ARRAY_LENGTH: int = 1000 + + HTTP_REQUEST_MAX_CONNECT_TIMEOUT: int = 300 + HTTP_REQUEST_MAX_READ_TIMEOUT: int = 600 + HTTP_REQUEST_MAX_WRITE_TIMEOUT: int = 600 + HTTP_REQUEST_NODE_MAX_BINARY_SIZE: int = 1024 * 1024 * 10 + + @computed_field + def HTTP_REQUEST_NODE_READABLE_MAX_BINARY_SIZE(self) -> str: + return f'{self.HTTP_REQUEST_NODE_MAX_BINARY_SIZE / 1024 / 1024:.2f}MB' + + HTTP_REQUEST_NODE_MAX_TEXT_SIZE: int = 1024 * 1024 + + @computed_field + def HTTP_REQUEST_NODE_READABLE_MAX_TEXT_SIZE(self) -> str: + return f'{self.HTTP_REQUEST_NODE_MAX_TEXT_SIZE / 1024 / 1024:.2f}MB' + + SSRF_PROXY_HTTP_URL: str | None = None + SSRF_PROXY_HTTPS_URL: str | None = None \ No newline at end of file diff --git a/api/controllers/console/auth/data_source_oauth.py b/api/controllers/console/auth/data_source_oauth.py index 293ec1c4d3..6268347244 100644 --- a/api/controllers/console/auth/data_source_oauth.py +++ b/api/controllers/console/auth/data_source_oauth.py @@ -6,6 +6,7 @@ from flask_login import current_user from flask_restful import Resource from werkzeug.exceptions import Forbidden +from configs import dify_config from controllers.console import api from libs.login import login_required from libs.oauth_data_source import NotionOAuth @@ -16,11 +17,11 @@ from ..wraps import account_initialization_required def get_oauth_providers(): with current_app.app_context(): - notion_oauth = NotionOAuth(client_id=current_app.config.get('NOTION_CLIENT_ID'), - client_secret=current_app.config.get( - 'NOTION_CLIENT_SECRET'), - redirect_uri=current_app.config.get( - 'CONSOLE_API_URL') + '/console/api/oauth/data-source/callback/notion') + if not dify_config.NOTION_CLIENT_ID or not dify_config.NOTION_CLIENT_SECRET: + return {} + notion_oauth = NotionOAuth(client_id=dify_config.NOTION_CLIENT_ID, + client_secret=dify_config.NOTION_CLIENT_SECRET, + redirect_uri=dify_config.CONSOLE_API_URL + '/console/api/oauth/data-source/callback/notion') OAUTH_PROVIDERS = { 'notion': notion_oauth @@ -39,8 +40,10 @@ class OAuthDataSource(Resource): print(vars(oauth_provider)) if not oauth_provider: return {'error': 'Invalid provider'}, 400 - if current_app.config.get('NOTION_INTEGRATION_TYPE') == 'internal': - internal_secret = current_app.config.get('NOTION_INTERNAL_SECRET') + if dify_config.NOTION_INTEGRATION_TYPE == 'internal': + internal_secret = dify_config.NOTION_INTERNAL_SECRET + if not internal_secret: + return {'error': 'Internal secret is not set'}, oauth_provider.save_internal_access_token(internal_secret) return { 'data': '' } else: @@ -60,13 +63,13 @@ class OAuthDataSourceCallback(Resource): if 'code' in request.args: code = request.args.get('code') - return redirect(f'{current_app.config.get("CONSOLE_WEB_URL")}?type=notion&code={code}') + return redirect(f'{dify_config.CONSOLE_WEB_URL}?type=notion&code={code}') elif 'error' in request.args: error = request.args.get('error') - return redirect(f'{current_app.config.get("CONSOLE_WEB_URL")}?type=notion&error={error}') + return redirect(f'{dify_config.CONSOLE_WEB_URL}?type=notion&error={error}') else: - return redirect(f'{current_app.config.get("CONSOLE_WEB_URL")}?type=notion&error=Access denied') + return redirect(f'{dify_config.CONSOLE_WEB_URL}?type=notion&error=Access denied') class OAuthDataSourceBinding(Resource): diff --git a/api/controllers/console/auth/login.py b/api/controllers/console/auth/login.py index 67d6dc8e95..3a0e5ea94d 100644 --- a/api/controllers/console/auth/login.py +++ b/api/controllers/console/auth/login.py @@ -1,7 +1,7 @@ from typing import cast import flask_login -from flask import current_app, request +from flask import request from flask_restful import Resource, reqparse import services @@ -56,14 +56,14 @@ class LogoutApi(Resource): class ResetPasswordApi(Resource): @setup_required def get(self): - parser = reqparse.RequestParser() - parser.add_argument('email', type=email, required=True, location='json') - args = parser.parse_args() + # parser = reqparse.RequestParser() + # parser.add_argument('email', type=email, required=True, location='json') + # args = parser.parse_args() # import mailchimp_transactional as MailchimpTransactional # from mailchimp_transactional.api_client import ApiClientError - account = {'email': args['email']} + # account = {'email': args['email']} # account = AccountService.get_by_email(args['email']) # if account is None: # raise ValueError('Email not found') @@ -71,22 +71,22 @@ class ResetPasswordApi(Resource): # AccountService.update_password(account, new_password) # todo: Send email - MAILCHIMP_API_KEY = current_app.config['MAILCHIMP_TRANSACTIONAL_API_KEY'] + # MAILCHIMP_API_KEY = current_app.config['MAILCHIMP_TRANSACTIONAL_API_KEY'] # mailchimp = MailchimpTransactional(MAILCHIMP_API_KEY) - message = { - 'from_email': 'noreply@example.com', - 'to': [{'email': account.email}], - 'subject': 'Reset your Dify password', - 'html': """ -

Dear User,

-

The Dify team has generated a new password for you, details as follows:

-

{new_password}

-

Please change your password to log in as soon as possible.

-

Regards,

-

The Dify Team

- """ - } + # message = { + # 'from_email': 'noreply@example.com', + # 'to': [{'email': account['email']}], + # 'subject': 'Reset your Dify password', + # 'html': """ + #

Dear User,

+ #

The Dify team has generated a new password for you, details as follows:

+ #

{new_password}

+ #

Please change your password to log in as soon as possible.

+ #

Regards,

+ #

The Dify Team

+ # """ + # } # response = mailchimp.messages.send({ # 'message': message, diff --git a/api/controllers/console/auth/oauth.py b/api/controllers/console/auth/oauth.py index 2e4a627e06..4a651bfe7b 100644 --- a/api/controllers/console/auth/oauth.py +++ b/api/controllers/console/auth/oauth.py @@ -6,6 +6,7 @@ import requests from flask import current_app, redirect, request from flask_restful import Resource +from configs import dify_config from constants.languages import languages from extensions.ext_database import db from libs.helper import get_remote_ip @@ -18,22 +19,24 @@ from .. import api def get_oauth_providers(): with current_app.app_context(): - github_oauth = GitHubOAuth(client_id=current_app.config.get('GITHUB_CLIENT_ID'), - client_secret=current_app.config.get( - 'GITHUB_CLIENT_SECRET'), - redirect_uri=current_app.config.get( - 'CONSOLE_API_URL') + '/console/api/oauth/authorize/github') + if not dify_config.GITHUB_CLIENT_ID or not dify_config.GITHUB_CLIENT_SECRET: + github_oauth = None + else: + github_oauth = GitHubOAuth( + client_id=dify_config.GITHUB_CLIENT_ID, + client_secret=dify_config.GITHUB_CLIENT_SECRET, + redirect_uri=dify_config.CONSOLE_API_URL + '/console/api/oauth/authorize/github', + ) + if not dify_config.GOOGLE_CLIENT_ID or not dify_config.GOOGLE_CLIENT_SECRET: + google_oauth = None + else: + google_oauth = GoogleOAuth( + client_id=dify_config.GOOGLE_CLIENT_ID, + client_secret=dify_config.GOOGLE_CLIENT_SECRET, + redirect_uri=dify_config.CONSOLE_API_URL + '/console/api/oauth/authorize/google', + ) - google_oauth = GoogleOAuth(client_id=current_app.config.get('GOOGLE_CLIENT_ID'), - client_secret=current_app.config.get( - 'GOOGLE_CLIENT_SECRET'), - redirect_uri=current_app.config.get( - 'CONSOLE_API_URL') + '/console/api/oauth/authorize/google') - - OAUTH_PROVIDERS = { - 'github': github_oauth, - 'google': google_oauth - } + OAUTH_PROVIDERS = {'github': github_oauth, 'google': google_oauth} return OAUTH_PROVIDERS @@ -63,8 +66,7 @@ class OAuthCallback(Resource): token = oauth_provider.get_access_token(code) user_info = oauth_provider.get_user_info(token) except requests.exceptions.HTTPError as e: - logging.exception( - f"An error occurred during the OAuth process with {provider}: {e.response.text}") + logging.exception(f'An error occurred during the OAuth process with {provider}: {e.response.text}') return {'error': 'OAuth process failed'}, 400 account = _generate_account(provider, user_info) @@ -81,7 +83,7 @@ class OAuthCallback(Resource): token = AccountService.login(account, ip_address=get_remote_ip(request)) - return redirect(f'{current_app.config.get("CONSOLE_WEB_URL")}?console_token={token}') + return redirect(f'{dify_config.CONSOLE_WEB_URL}?console_token={token}') def _get_account_by_openid_or_email(provider: str, user_info: OAuthUserInfo) -> Optional[Account]: @@ -101,11 +103,7 @@ def _generate_account(provider: str, user_info: OAuthUserInfo): # Create account account_name = user_info.name if user_info.name else 'Dify' account = RegisterService.register( - email=user_info.email, - name=account_name, - password=None, - open_id=user_info.id, - provider=provider + email=user_info.email, name=account_name, password=None, open_id=user_info.id, provider=provider ) # Set interface language diff --git a/api/core/extension/api_based_extension_requestor.py b/api/core/extension/api_based_extension_requestor.py index 40e60687b2..4db7a99973 100644 --- a/api/core/extension/api_based_extension_requestor.py +++ b/api/core/extension/api_based_extension_requestor.py @@ -1,7 +1,6 @@ -import os - import requests +from configs import dify_config from models.api_based_extension import APIBasedExtensionPoint @@ -31,10 +30,10 @@ class APIBasedExtensionRequestor: try: # proxy support for security proxies = None - if os.environ.get("SSRF_PROXY_HTTP_URL") and os.environ.get("SSRF_PROXY_HTTPS_URL"): + if dify_config.SSRF_PROXY_HTTP_URL and dify_config.SSRF_PROXY_HTTPS_URL: proxies = { - 'http': os.environ.get("SSRF_PROXY_HTTP_URL"), - 'https': os.environ.get("SSRF_PROXY_HTTPS_URL"), + 'http': dify_config.SSRF_PROXY_HTTP_URL, + 'https': dify_config.SSRF_PROXY_HTTPS_URL, } response = requests.request( diff --git a/api/core/helper/code_executor/code_executor.py b/api/core/helper/code_executor/code_executor.py index ec731693b6..f094f7d79b 100644 --- a/api/core/helper/code_executor/code_executor.py +++ b/api/core/helper/code_executor/code_executor.py @@ -1,5 +1,4 @@ import logging -import os import time from enum import Enum from threading import Lock @@ -9,6 +8,7 @@ from httpx import get, post from pydantic import BaseModel from yarl import URL +from configs import dify_config from core.helper.code_executor.entities import CodeDependency from core.helper.code_executor.javascript.javascript_transformer import NodeJsTemplateTransformer from core.helper.code_executor.jinja2.jinja2_transformer import Jinja2TemplateTransformer @@ -18,8 +18,8 @@ from core.helper.code_executor.template_transformer import TemplateTransformer logger = logging.getLogger(__name__) # Code Executor -CODE_EXECUTION_ENDPOINT = os.environ.get('CODE_EXECUTION_ENDPOINT', 'http://sandbox:8194') -CODE_EXECUTION_API_KEY = os.environ.get('CODE_EXECUTION_API_KEY', 'dify-sandbox') +CODE_EXECUTION_ENDPOINT = dify_config.CODE_EXECUTION_ENDPOINT +CODE_EXECUTION_API_KEY = dify_config.CODE_EXECUTION_API_KEY CODE_EXECUTION_TIMEOUT= (10, 60) diff --git a/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/_client.py b/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/_client.py index 29b1746351..6588d1dd68 100644 --- a/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/_client.py +++ b/api/core/model_runtime/model_providers/zhipuai/zhipuai_sdk/_client.py @@ -29,10 +29,8 @@ class ZhipuAI(HttpClient): http_client: httpx.Client | None = None, custom_headers: Mapping[str, str] | None = None ) -> None: - # if api_key is None: - # api_key = os.environ.get("ZHIPUAI_API_KEY") if api_key is None: - raise ZhipuAIError("未提供api_key,请通过参数或环境变量提供") + raise ZhipuAIError("No api_key provided, please provide it through parameters or environment variables") self.api_key = api_key if base_url is None: diff --git a/api/core/workflow/nodes/code/code_node.py b/api/core/workflow/nodes/code/code_node.py index 610a23e704..e15c1c6f87 100644 --- a/api/core/workflow/nodes/code/code_node.py +++ b/api/core/workflow/nodes/code/code_node.py @@ -1,6 +1,6 @@ -import os from typing import Optional, Union, cast +from configs import dify_config from core.helper.code_executor.code_executor import CodeExecutionException, CodeExecutor, CodeLanguage from core.helper.code_executor.code_node_provider import CodeNodeProvider from core.helper.code_executor.javascript.javascript_code_provider import JavascriptCodeProvider @@ -11,14 +11,14 @@ from core.workflow.nodes.base_node import BaseNode from core.workflow.nodes.code.entities import CodeNodeData from models.workflow import WorkflowNodeExecutionStatus -MAX_NUMBER = int(os.environ.get('CODE_MAX_NUMBER', '9223372036854775807')) -MIN_NUMBER = int(os.environ.get('CODE_MIN_NUMBER', '-9223372036854775808')) +MAX_NUMBER = dify_config.CODE_MAX_NUMBER +MIN_NUMBER = dify_config.CODE_MIN_NUMBER MAX_PRECISION = 20 MAX_DEPTH = 5 -MAX_STRING_LENGTH = int(os.environ.get('CODE_MAX_STRING_LENGTH', '80000')) -MAX_STRING_ARRAY_LENGTH = int(os.environ.get('CODE_MAX_STRING_ARRAY_LENGTH', '30')) -MAX_OBJECT_ARRAY_LENGTH = int(os.environ.get('CODE_MAX_OBJECT_ARRAY_LENGTH', '30')) -MAX_NUMBER_ARRAY_LENGTH = int(os.environ.get('CODE_MAX_NUMBER_ARRAY_LENGTH', '1000')) +MAX_STRING_LENGTH = dify_config.CODE_MAX_STRING_LENGTH +MAX_STRING_ARRAY_LENGTH = dify_config.CODE_MAX_STRING_ARRAY_LENGTH +MAX_OBJECT_ARRAY_LENGTH = dify_config.CODE_MAX_OBJECT_ARRAY_LENGTH +MAX_NUMBER_ARRAY_LENGTH = dify_config.CODE_MAX_NUMBER_ARRAY_LENGTH class CodeNode(BaseNode): diff --git a/api/core/workflow/nodes/http_request/entities.py b/api/core/workflow/nodes/http_request/entities.py index f4d6afa6ed..65451452c8 100644 --- a/api/core/workflow/nodes/http_request/entities.py +++ b/api/core/workflow/nodes/http_request/entities.py @@ -1,13 +1,13 @@ -import os from typing import Literal, Optional, Union from pydantic import BaseModel, ValidationInfo, field_validator +from configs import dify_config from core.workflow.entities.base_node_data_entities import BaseNodeData -MAX_CONNECT_TIMEOUT = int(os.environ.get('HTTP_REQUEST_MAX_CONNECT_TIMEOUT', '300')) -MAX_READ_TIMEOUT = int(os.environ.get('HTTP_REQUEST_MAX_READ_TIMEOUT', '600')) -MAX_WRITE_TIMEOUT = int(os.environ.get('HTTP_REQUEST_MAX_WRITE_TIMEOUT', '600')) +MAX_CONNECT_TIMEOUT = dify_config.HTTP_REQUEST_MAX_CONNECT_TIMEOUT +MAX_READ_TIMEOUT = dify_config.HTTP_REQUEST_MAX_READ_TIMEOUT +MAX_WRITE_TIMEOUT = dify_config.HTTP_REQUEST_MAX_WRITE_TIMEOUT class HttpRequestNodeAuthorizationConfig(BaseModel): diff --git a/api/core/workflow/nodes/http_request/http_executor.py b/api/core/workflow/nodes/http_request/http_executor.py index d69b323bbb..902d821e40 100644 --- a/api/core/workflow/nodes/http_request/http_executor.py +++ b/api/core/workflow/nodes/http_request/http_executor.py @@ -1,5 +1,4 @@ import json -import os from copy import deepcopy from random import randint from typing import Any, Optional, Union @@ -8,6 +7,7 @@ from urllib.parse import urlencode import httpx import core.helper.ssrf_proxy as ssrf_proxy +from configs import dify_config from core.workflow.entities.variable_entities import VariableSelector from core.workflow.entities.variable_pool import ValueType, VariablePool from core.workflow.nodes.http_request.entities import ( @@ -18,10 +18,10 @@ from core.workflow.nodes.http_request.entities import ( ) from core.workflow.utils.variable_template_parser import VariableTemplateParser -MAX_BINARY_SIZE = int(os.environ.get('HTTP_REQUEST_NODE_MAX_BINARY_SIZE', 1024 * 1024 * 10)) # 10MB -READABLE_MAX_BINARY_SIZE = f'{MAX_BINARY_SIZE / 1024 / 1024:.2f}MB' -MAX_TEXT_SIZE = int(os.environ.get('HTTP_REQUEST_NODE_MAX_TEXT_SIZE', 1024 * 1024)) # 1MB -READABLE_MAX_TEXT_SIZE = f'{MAX_TEXT_SIZE / 1024 / 1024:.2f}MB' +MAX_BINARY_SIZE = dify_config.HTTP_REQUEST_NODE_MAX_BINARY_SIZE +READABLE_MAX_BINARY_SIZE = dify_config.HTTP_REQUEST_NODE_READABLE_MAX_BINARY_SIZE +MAX_TEXT_SIZE = dify_config.HTTP_REQUEST_NODE_MAX_TEXT_SIZE +READABLE_MAX_TEXT_SIZE = dify_config.HTTP_REQUEST_NODE_READABLE_MAX_TEXT_SIZE class HttpExecutorResponse: