Skip to content

Commit 2263446

Browse files
authored
Merge branch 'main' into issue-34557
2 parents da84e74 + e83a409 commit 2263446

1,933 files changed

Lines changed: 39441 additions & 16845 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ api/.vscode
212212

213213
# pnpm
214214
/.pnpm-store
215-
/node_modules
215+
node_modules
216216
.vite-hooks/_
217217

218218
# plugin migrate

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
save-exact=true

.vite-hooks/pre-commit

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ if $web_modified; then
8989
echo "No staged TypeScript changes detected, skipping type-check:tsgo"
9090
fi
9191

92+
echo "Running knip"
93+
if ! pnpm run knip; then
94+
echo "Knip check failed. Please run 'pnpm run knip' to fix the errors."
95+
exit 1
96+
fi
97+
9298
echo "Running unit tests check"
9399
modified_files=$(git diff --cached --name-only -- utils | grep -v '\.spec\.ts$' || true)
94100

api/celery_healthcheck.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# This module provides a lightweight Celery instance for use in Docker health checks.
2+
# Unlike celery_entrypoint.py, this does NOT import app.py and therefore avoids
3+
# initializing all Flask extensions (DB, Redis, storage, blueprints, etc.).
4+
# Using this module keeps the health check fast and low-cost.
5+
from celery import Celery
6+
7+
from configs import dify_config
8+
from extensions.ext_celery import get_celery_broker_transport_options, get_celery_ssl_options
9+
10+
celery = Celery(broker=dify_config.CELERY_BROKER_URL)
11+
12+
broker_transport_options = get_celery_broker_transport_options()
13+
if broker_transport_options:
14+
celery.conf.update(broker_transport_options=broker_transport_options)
15+
16+
ssl_options = get_celery_ssl_options()
17+
if ssl_options:
18+
celery.conf.update(broker_use_ssl=ssl_options)

api/controllers/console/app/app_import.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from flask_restx import Resource, fields, marshal_with
22
from pydantic import BaseModel, Field
3-
from sqlalchemy.orm import sessionmaker
3+
from sqlalchemy.orm import Session, sessionmaker
44

55
from controllers.console.app.wraps import get_app_model
66
from controllers.console.wraps import (
@@ -71,7 +71,7 @@ def post(self):
7171
args = AppImportPayload.model_validate(console_ns.payload)
7272

7373
# Create service with session
74-
with sessionmaker(db.engine).begin() as session:
74+
with Session(db.engine) as session:
7575
import_service = AppDslService(session)
7676
# Import app
7777
account = current_user

api/controllers/console/app/workflow_draft_variable.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def _get_items(var_list: WorkflowDraftVariableList) -> list[WorkflowDraftVariabl
193193
)
194194

195195

196-
def _api_prerequisite(f: Callable[..., Any]) -> Callable[..., Any]:
196+
def _api_prerequisite[**P, R](f: Callable[P, R]) -> Callable[P, R | Response]:
197197
"""Common prerequisites for all draft workflow variable APIs.
198198
199199
It ensures the following conditions are satisfied:
@@ -210,7 +210,7 @@ def _api_prerequisite(f: Callable[..., Any]) -> Callable[..., Any]:
210210
@edit_permission_required
211211
@get_app_model(mode=[AppMode.ADVANCED_CHAT, AppMode.WORKFLOW])
212212
@wraps(f)
213-
def wrapper(*args: Any, **kwargs: Any):
213+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R | Response:
214214
return f(*args, **kwargs)
215215

216216
return wrapper

api/controllers/console/app/wraps.py

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from collections.abc import Callable
22
from functools import wraps
3-
from typing import Any
3+
from typing import overload
44

55
from sqlalchemy import select
66

@@ -23,14 +23,30 @@ def _load_app_model_with_trial(app_id: str) -> App | None:
2323
return app_model
2424

2525

26-
def get_app_model(
27-
view: Callable[..., Any] | None = None,
26+
@overload
27+
def get_app_model[**P, R](
28+
view: Callable[P, R],
2829
*,
2930
mode: AppMode | list[AppMode] | None = None,
30-
) -> Callable[..., Any] | Callable[[Callable[..., Any]], Callable[..., Any]]:
31-
def decorator(view_func: Callable[..., Any]) -> Callable[..., Any]:
31+
) -> Callable[P, R]: ...
32+
33+
34+
@overload
35+
def get_app_model[**P, R](
36+
view: None = None,
37+
*,
38+
mode: AppMode | list[AppMode] | None = None,
39+
) -> Callable[[Callable[P, R]], Callable[P, R]]: ...
40+
41+
42+
def get_app_model[**P, R](
43+
view: Callable[P, R] | None = None,
44+
*,
45+
mode: AppMode | list[AppMode] | None = None,
46+
) -> Callable[P, R] | Callable[[Callable[P, R]], Callable[P, R]]:
47+
def decorator(view_func: Callable[P, R]) -> Callable[P, R]:
3248
@wraps(view_func)
33-
def decorated_view(*args: Any, **kwargs: Any):
49+
def decorated_view(*args: P.args, **kwargs: P.kwargs) -> R:
3450
if not kwargs.get("app_id"):
3551
raise ValueError("missing app_id in path parameters")
3652

@@ -68,14 +84,30 @@ def decorated_view(*args: Any, **kwargs: Any):
6884
return decorator(view)
6985

7086

71-
def get_app_model_with_trial(
72-
view: Callable[..., Any] | None = None,
87+
@overload
88+
def get_app_model_with_trial[**P, R](
89+
view: Callable[P, R],
90+
*,
91+
mode: AppMode | list[AppMode] | None = None,
92+
) -> Callable[P, R]: ...
93+
94+
95+
@overload
96+
def get_app_model_with_trial[**P, R](
97+
view: None = None,
98+
*,
99+
mode: AppMode | list[AppMode] | None = None,
100+
) -> Callable[[Callable[P, R]], Callable[P, R]]: ...
101+
102+
103+
def get_app_model_with_trial[**P, R](
104+
view: Callable[P, R] | None = None,
73105
*,
74106
mode: AppMode | list[AppMode] | None = None,
75-
) -> Callable[..., Any] | Callable[[Callable[..., Any]], Callable[..., Any]]:
76-
def decorator(view_func: Callable[..., Any]) -> Callable[..., Any]:
107+
) -> Callable[P, R] | Callable[[Callable[P, R]], Callable[P, R]]:
108+
def decorator(view_func: Callable[P, R]) -> Callable[P, R]:
77109
@wraps(view_func)
78-
def decorated_view(*args: Any, **kwargs: Any):
110+
def decorated_view(*args: P.args, **kwargs: P.kwargs) -> R:
79111
if not kwargs.get("app_id"):
80112
raise ValueError("missing app_id in path parameters")
81113

api/controllers/console/datasets/data_source.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,11 @@ def get(self):
158158
@login_required
159159
@account_initialization_required
160160
def patch(self, binding_id, action: Literal["enable", "disable"]):
161+
_, current_tenant_id = current_account_with_tenant()
161162
binding_id = str(binding_id)
162163
with sessionmaker(db.engine, expire_on_commit=False).begin() as session:
163164
data_source_binding = session.execute(
164-
select(DataSourceOauthBinding).filter_by(id=binding_id)
165+
select(DataSourceOauthBinding).filter_by(id=binding_id, tenant_id=current_tenant_id)
165166
).scalar_one_or_none()
166167
if data_source_binding is None:
167168
raise NotFound("Data source binding not found.")

api/controllers/console/datasets/external.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,11 @@ class ExternalApiTemplateApi(Resource):
173173
@login_required
174174
@account_initialization_required
175175
def get(self, external_knowledge_api_id):
176+
_, current_tenant_id = current_account_with_tenant()
176177
external_knowledge_api_id = str(external_knowledge_api_id)
177-
external_knowledge_api = ExternalDatasetService.get_external_knowledge_api(external_knowledge_api_id)
178+
external_knowledge_api = ExternalDatasetService.get_external_knowledge_api(
179+
external_knowledge_api_id, current_tenant_id
180+
)
178181
if external_knowledge_api is None:
179182
raise NotFound("API template not found.")
180183

api/controllers/console/datasets/rag_pipeline/rag_pipeline_draft_variable.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
from collections.abc import Callable
23
from typing import Any, NoReturn
34

45
from flask import Response, request
@@ -55,7 +56,7 @@ class WorkflowDraftVariablePatchPayload(BaseModel):
5556
register_schema_models(console_ns, WorkflowDraftVariablePatchPayload)
5657

5758

58-
def _api_prerequisite(f):
59+
def _api_prerequisite[**P, R](f: Callable[P, R]) -> Callable[P, R | Response]:
5960
"""Common prerequisites for all draft workflow variable APIs.
6061
6162
It ensures the following conditions are satisfied:
@@ -70,7 +71,7 @@ def _api_prerequisite(f):
7071
@login_required
7172
@account_initialization_required
7273
@get_rag_pipeline
73-
def wrapper(*args, **kwargs):
74+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R | Response:
7475
if not isinstance(current_user, Account) or not current_user.has_edit_permission:
7576
raise Forbidden()
7677
return f(*args, **kwargs)

0 commit comments

Comments
 (0)