Skip to content

Commit a210bf0

Browse files
committed
Merge remote-tracking branch 'origin/develop' into hs/dev_0910_bugfix
# Conflicts: # frontend/services/mcpService.ts # frontend/services/uploadService.ts # frontend/services/userConfigService.ts # frontend/types/auth.ts # frontend/types/avatar.ts
2 parents 08de8aa + b783b24 commit a210bf0

File tree

88 files changed

+1656
-1521
lines changed

Some content is hidden

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

88 files changed

+1656
-1521
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Run Auto Web Type Check
2+
3+
concurrency:
4+
group: auto-web-type-check-${{ github.ref }}
5+
cancel-in-progress: true
6+
7+
on:
8+
workflow_dispatch:
9+
inputs:
10+
runner_label_json:
11+
description: 'runner array in json format (e.g. ["ubuntu-latest"] or ["self-hosted"])'
12+
default: '["ubuntu-latest"]'
13+
pull_request:
14+
branches: [develop]
15+
paths:
16+
- 'frontend/**'
17+
- '.github/workflows/**'
18+
push:
19+
branches: [develop]
20+
paths:
21+
- 'frontend/**'
22+
- '.github/workflows/**'
23+
24+
jobs:
25+
type-check:
26+
runs-on: ${{ fromJson(github.event.inputs.runner_label_json || '["ubuntu-latest"]') }}
27+
steps:
28+
- name: Checkout code
29+
uses: actions/checkout@v4
30+
31+
- name: Set up Node.js
32+
uses: actions/setup-node@v4
33+
with:
34+
node-version: '18'
35+
36+
- name: Install dependencies
37+
run: |
38+
cd frontend
39+
npm install
40+
41+
- name: Run TypeScript type check
42+
run: |
43+
cd frontend
44+
npm run type-check
45+
TYPE_CHECK_EXIT_CODE=$?
46+
47+
# Check if type check actually passed
48+
if [ $TYPE_CHECK_EXIT_CODE -ne 0 ]; then
49+
echo "❌ Type check failed with exit code $TYPE_CHECK_EXIT_CODE"
50+
exit $TYPE_CHECK_EXIT_CODE
51+
else
52+
echo "✅ Type check passed successfully."
53+
fi

backend/apps/model_managment_app.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ async def create_provider_model(request: ProviderModelRequest, authorization: Op
115115
model_list = await get_provider_models(model_data)
116116

117117
# Merge existing model's max_tokens attribute
118-
model_list = merge_existing_model_tokens(model_list, tenant_id, request.provider, request.model_type)
118+
model_list = merge_existing_model_tokens(
119+
model_list, tenant_id, request.provider, request.model_type)
119120

120121
# Sort model list by ID
121122
model_list = sort_models_by_id(model_list)
@@ -164,7 +165,8 @@ async def batch_create_models(request: BatchCreateModelsRequest, authorization:
164165
existing_max_tokens = existing_model_by_display["max_tokens"]
165166
new_max_tokens = model["max_tokens"]
166167
if existing_max_tokens != new_max_tokens:
167-
update_model_record(existing_model_by_display["model_id"], {"max_tokens": new_max_tokens}, user_id)
168+
update_model_record(existing_model_by_display["model_id"], {
169+
"max_tokens": new_max_tokens}, user_id)
168170
continue
169171

170172
model_dict = await prepare_model_dict(
@@ -267,7 +269,7 @@ async def delete_model(display_name: str = Query(..., embed=True), authorization
267269
If the model is an embedding or multi_embedding type, both types will be deleted
268270
269271
Args:
270-
display_name: Display name of the model to delete (唯一键)
272+
display_name: Display name of the model to delete (unique key)
271273
authorization: Authorization header
272274
"""
273275
try:
@@ -282,10 +284,10 @@ async def delete_model(display_name: str = Query(..., embed=True), authorization
282284
message=f"Model not found: {display_name}",
283285
data=None
284286
)
285-
# 支持 embedding/multi_embedding 互删
287+
# Support mutual deletion of embedding/multi_embedding
286288
deleted_types = []
287289
if model["model_type"] in ["embedding", "multi_embedding"]:
288-
# 查找所有 embedding/multi_embedding 且 display_name 相同的模型
290+
# Find all embedding/multi_embedding models with the same display_name
289291
for t in ["embedding", "multi_embedding"]:
290292
m = get_model_by_display_name(display_name, tenant_id)
291293
if m and m["model_type"] == t:

backend/apps/user_management_app.py

Lines changed: 59 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,16 @@
2424
async def service_health():
2525
"""Service health check"""
2626
try:
27-
is_available = await check_auth_service_health()
27+
await check_auth_service_health()
2828

29-
if is_available:
30-
return JSONResponse(status_code=HTTPStatus.OK, content={"message": "Auth service is available"})
31-
else:
32-
return JSONResponse(status_code=HTTPStatus.SERVICE_UNAVAILABLE, content={"message": "Auth service is unavailable"})
29+
return JSONResponse(status_code=HTTPStatus.OK,
30+
content={"message": "Auth service is available"})
31+
except ConnectionError as e:
32+
logging.error(f"Auth service health check failed: {str(e)}")
33+
raise HTTPException(status_code=HTTPStatus.SERVICE_UNAVAILABLE, detail="Auth service is unavailable")
3334
except Exception as e:
3435
logging.error(f"Auth service health check failed: {str(e)}")
35-
return HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Auth service is unavailable")
36+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Auth service is unavailable")
3637

3738

3839
@router.post("/signup")
@@ -50,63 +51,29 @@ async def signup(request: UserSignUpRequest):
5051
return JSONResponse(status_code=HTTPStatus.OK,
5152
content={"message":success_message, "data":user_data})
5253
except NoInviteCodeException as e:
53-
message = "Admin registration feature is not available, please contact the system administrator to configure the invite code"
54-
data = {
55-
"error_type": "INVITE_CODE_NOT_CONFIGURED",
56-
"details": "The system has not configured the admin invite code, please contact technical support"
57-
}
5854
logging.error(f"User registration failed by invite code: {str(e)}")
59-
return JSONResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
60-
content={"message": message, "data": data})
55+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
56+
detail="INVITE_CODE_NOT_CONFIGURED")
6157
except IncorrectInviteCodeException as e:
62-
message = "Admin invite code error, please check and re-enter"
63-
data = {
64-
"error_type": "INVITE_CODE_INVALID",
65-
"field": "inviteCode",
66-
"hint": "Please confirm that the invite code is entered correctly, case-sensitive"
67-
}
6858
logging.error(f"User registration failed by invite code: {str(e)}")
69-
return JSONResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
70-
content={"message": message, "data": data})
59+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
60+
detail="INVITE_CODE_INVALID")
7161
except UserRegistrationException as e:
72-
message = "Registration service is temporarily unavailable, please try again later"
73-
data = {
74-
"error_type": "REGISTRATION_SERVICE_ERROR",
75-
"details": "Authentication service response exception"
76-
}
7762
logging.error(f"User registration failed by registration service: {str(e)}")
78-
return JSONResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
79-
content={"message": message, "data": data})
63+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
64+
detail="REGISTRATION_SERVICE_ERROR")
8065
except AuthApiError as e:
81-
message = f"Email {request.email} has already been registered"
82-
data = {
83-
"error_type": "EMAIL_ALREADY_EXISTS",
84-
"field": "email",
85-
"suggestion": "Please use a different email address or try logging in to an existing account"
86-
}
8766
logging.error(f"User registration failed by email already exists: {str(e)}")
88-
return JSONResponse(status_code=HTTPStatus.CONFLICT,
89-
content={"message": message, "data": data})
67+
raise HTTPException(status_code=HTTPStatus.CONFLICT,
68+
detail="EMAIL_ALREADY_EXISTS")
9069
except AuthWeakPasswordError as e:
91-
message = "Password strength is not enough, please set a stronger password"
92-
data = {
93-
"error_type": "WEAK_PASSWORD",
94-
"field": "password",
95-
"requirements": "Password must be at least 6 characters long, including letters, numbers, and special symbols"
96-
}
9770
logging.error(f"User registration failed by weak password: {str(e)}")
98-
return JSONResponse(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
99-
content={"message": message, "data": data})
71+
raise HTTPException(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
72+
detail="WEAK_PASSWORD")
10073
except Exception as e:
101-
message = "Registration failed, please try again later"
102-
data = {
103-
"error_type": "UNKNOWN_ERROR",
104-
"details": f"System error: {str(e)[:100]}",
105-
"suggestion": "If the problem persists, please contact technical support"
106-
}
10774
logging.error(f"User registration failed, unknown error: {str(e)}")
108-
return JSONResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
109-
content={"message": message, "data": data})
75+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
76+
detail="UNKNOWN_ERROR")
11077

11178

11279
@router.post("/signin")
@@ -119,88 +86,88 @@ async def signin(request: UserSignInRequest):
11986
content=signin_content)
12087
except AuthApiError as e:
12188
logging.error(f"User login failed: {str(e)}")
122-
return JSONResponse(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
123-
content={"message": "Email or password error"})
89+
raise HTTPException(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
90+
detail="Email or password error")
12491
except Exception as e:
12592
logging.error(f"User login failed, unknown error: {str(e)}")
126-
return JSONResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
127-
content={"message": "Login failed"})
93+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
94+
detail="Login failed")
12895

12996

13097
@router.post("/refresh_token")
13198
async def user_refresh_token(request: Request):
13299
"""Refresh token"""
100+
authorization = request.headers.get("Authorization")
101+
if not authorization:
102+
raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED,
103+
detail="No authorization token provided")
133104
try:
134-
authorization = request.headers.get("Authorization")
135-
if not authorization:
136-
return JSONResponse(status_code=HTTPStatus.UNAUTHORIZED,
137-
content={"message": "No authorization token provided"})
138105
session_data = await request.json()
139106
refresh_token = session_data.get("refresh_token")
140107
if not refresh_token:
141-
return JSONResponse(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
142-
content={"message": "No refresh token provided"})
108+
raise ValueError("No refresh token provided")
143109
session_info = await refresh_user_token(authorization, refresh_token)
144110
return JSONResponse(status_code=HTTPStatus.OK,
145111
content={"message":"Token refresh successful", "data":{"session": session_info}})
112+
except ValueError as e:
113+
logging.error(f"Refresh token failed: {str(e)}")
114+
raise HTTPException(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
115+
detail="No refresh token provided")
146116
except Exception as e:
147117
logging.error(f"Refresh token failed: {str(e)}")
148-
return JSONResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
149-
content={"message": "Refresh token failed"})
118+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
119+
detail="Refresh token failed")
150120

151121

152122
@router.post("/logout")
153123
async def logout(request: Request):
154124
"""User logout"""
125+
authorization = request.headers.get("Authorization")
126+
if not authorization:
127+
raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED,
128+
detail="User not logged in")
155129
try:
156-
authorization = request.headers.get("Authorization")
157-
if not authorization:
158-
return JSONResponse(status_code=HTTPStatus.UNAUTHORIZED,
159-
content={"message": "User not logged in"})
160-
161130
client = get_authorized_client(authorization)
162131
client.auth.sign_out()
163132
return JSONResponse(status_code=HTTPStatus.OK,
164133
content={"message":"Logout successful"})
165134

166135
except Exception as e:
167136
logging.error(f"User logout failed: {str(e)}")
168-
return JSONResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
169-
content={"message": "Logout failed!"})
137+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
138+
detail="Logout failed!")
170139

171140

172141
@router.get("/session")
173142
async def get_session(request: Request):
174143
"""Get current user session"""
144+
authorization = request.headers.get("Authorization")
145+
if not authorization:
146+
raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED,
147+
detail="User not logged in")
175148
try:
176-
authorization = request.headers.get("Authorization")
177-
if not authorization:
178-
return JSONResponse(status_code=HTTPStatus.UNAUTHORIZED,
179-
content={"message": "No authorization token provided"})
180-
181149
data = await get_session_by_authorization(authorization)
182150
return JSONResponse(status_code=HTTPStatus.OK,
183151
content={"message": "Session is valid",
184152
"data": data})
185153
except ValueError as e:
186154
logging.error(f"Get user session failed: {str(e)}")
187-
return JSONResponse(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
188-
content={"message": "Session is invalid"})
155+
raise HTTPException(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
156+
detail="Session is invalid")
189157
except Exception as e:
190158
logging.error(f"error in get user session, {str(e)}")
191-
return JSONResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
192-
content={"message": "Get user session failed"})
159+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
160+
detail="Get user session failed")
193161

194162

195163
@router.get("/current_user_id")
196164
async def get_user_id(request: Request):
197165
"""Get current user ID, return None if not logged in"""
166+
authorization = request.headers.get("Authorization")
167+
if not authorization:
168+
raise HTTPException(status_code=HTTPStatus.UNAUTHORIZED,
169+
detail="User not logged in")
198170
try:
199-
authorization = request.headers.get("Authorization")
200-
if not authorization:
201-
return JSONResponse(status_code=HTTPStatus.UNAUTHORIZED,
202-
content={"message": "No authorization token provided"})
203-
204171
# Use the unified token validation function
205172
is_valid, user = validate_token(authorization)
206173
if is_valid and user:
@@ -214,11 +181,13 @@ async def get_user_id(request: Request):
214181
return JSONResponse(status_code=HTTPStatus.OK,
215182
content={"message": "Successfully parsed user ID from token",
216183
"data": {"user_id": user_id}})
184+
raise ValueError("User not logged in or session invalid")
217185

218-
# If all methods fail, return the session invalid information
219-
return JSONResponse(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
220-
content={"message": "User not logged in or session invalid"})
186+
except ValueError as e:
187+
logging.error(f"Get user ID failed: {str(e)}")
188+
raise HTTPException(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,
189+
detail="User not logged in or session invalid")
221190
except Exception as e:
222191
logging.error(f"Get user ID failed: {str(e)}")
223-
return JSONResponse(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
224-
content={"message": "Get user ID failed"})
192+
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
193+
detail="Get user ID failed")

backend/consts/model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def get_value(cls, status: Optional[str]) -> str:
2525
return status
2626

2727

28-
# 用户认证相关请求模型
28+
# User authentication related request models
2929
class UserSignUpRequest(BaseModel):
3030
"""User registration request model"""
3131
email: EmailStr

backend/database/utils.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
from typing import Any, Dict
22

33

4-
# 全局追踪字段管理方法
4+
# Global tracking field management methods
55
def add_creation_tracking(data: Dict[str, Any], user_id: str) -> Dict[str, Any]:
66
"""
7-
添加创建追踪字段(created_by和updated_by)
7+
Add creation tracking fields (created_by and updated_by)
88
99
Args:
10-
data: 要添加字段的数据字典
11-
user_id: 当前用户ID
10+
data: Data dictionary to add fields to
11+
user_id: Current user ID
1212
1313
Returns:
14-
Dict[str, Any]: 添加追踪字段后的数据字典
14+
Dict[str, Any]: Data dictionary with tracking fields added
1515
"""
1616
data_copy = data.copy()
1717
data_copy["created_by"] = user_id
@@ -21,14 +21,14 @@ def add_creation_tracking(data: Dict[str, Any], user_id: str) -> Dict[str, Any]:
2121

2222
def add_update_tracking(data: Dict[str, Any], user_id: str) -> Dict[str, Any]:
2323
"""
24-
添加更新追踪字段(updated_by
24+
Add update tracking field (updated_by)
2525
2626
Args:
27-
data: 要添加字段的数据字典
28-
user_id: 当前用户ID
27+
data: Data dictionary to add field to
28+
user_id: Current user ID
2929
3030
Returns:
31-
Dict[str, Any]: 添加追踪字段后的数据字典
31+
Dict[str, Any]: Data dictionary with tracking field added
3232
"""
3333
data_copy = data.copy()
3434
data_copy["updated_by"] = user_id

0 commit comments

Comments
 (0)