refactor: optimize structure, stability and runtime performance
This commit is contained in:
@@ -10,12 +10,96 @@ from flask import Blueprint, jsonify, request
|
||||
from flask_login import current_user, login_required
|
||||
from routes.pages import render_app_spa_or_legacy
|
||||
from services.state import check_email_rate_limit, check_ip_request_rate, safe_iter_task_status_items
|
||||
from services.tasks import get_task_scheduler
|
||||
|
||||
logger = get_logger("app")
|
||||
|
||||
api_user_bp = Blueprint("api_user", __name__)
|
||||
|
||||
|
||||
def _get_current_user_record():
|
||||
return database.get_user_by_id(current_user.id)
|
||||
|
||||
|
||||
def _get_current_user_or_404():
|
||||
user = _get_current_user_record()
|
||||
if user:
|
||||
return user, None
|
||||
return None, (jsonify({"error": "用户不存在"}), 404)
|
||||
|
||||
|
||||
def _get_current_username(*, fallback: str) -> str:
|
||||
user = _get_current_user_record()
|
||||
username = (user or {}).get("username", "")
|
||||
return username if username else fallback
|
||||
|
||||
|
||||
def _coerce_binary_flag(value, *, field_label: str):
|
||||
if isinstance(value, bool):
|
||||
value = 1 if value else 0
|
||||
try:
|
||||
value = int(value)
|
||||
except Exception:
|
||||
return None, f"{field_label}必须是0或1"
|
||||
if value not in (0, 1):
|
||||
return None, f"{field_label}必须是0或1"
|
||||
return value, None
|
||||
|
||||
|
||||
def _check_bind_email_rate_limits(email: str):
|
||||
client_ip = get_rate_limit_ip()
|
||||
allowed, error_msg = check_ip_request_rate(client_ip, "email")
|
||||
if not allowed:
|
||||
return False, error_msg, 429
|
||||
allowed, error_msg = check_email_rate_limit(email, "bind_email")
|
||||
if not allowed:
|
||||
return False, error_msg, 429
|
||||
return True, "", 200
|
||||
|
||||
|
||||
def _render_verify_bind_failed(*, title: str, error_message: str):
|
||||
spa_initial_state = {
|
||||
"page": "verify_result",
|
||||
"success": False,
|
||||
"title": title,
|
||||
"error_message": error_message,
|
||||
"primary_label": "返回登录",
|
||||
"primary_url": "/login",
|
||||
}
|
||||
return render_app_spa_or_legacy(
|
||||
"verify_failed.html",
|
||||
legacy_context={"error_message": error_message},
|
||||
spa_initial_state=spa_initial_state,
|
||||
)
|
||||
|
||||
|
||||
def _render_verify_bind_success(email: str):
|
||||
spa_initial_state = {
|
||||
"page": "verify_result",
|
||||
"success": True,
|
||||
"title": "邮箱绑定成功",
|
||||
"message": f"邮箱 {email} 已成功绑定到您的账号!",
|
||||
"primary_label": "返回登录",
|
||||
"primary_url": "/login",
|
||||
"redirect_url": "/login",
|
||||
"redirect_seconds": 5,
|
||||
}
|
||||
return render_app_spa_or_legacy("verify_success.html", spa_initial_state=spa_initial_state)
|
||||
|
||||
|
||||
def _get_current_running_count(user_id: int) -> int:
|
||||
try:
|
||||
queue_snapshot = get_task_scheduler().get_queue_state_snapshot() or {}
|
||||
running_by_user = queue_snapshot.get("running_by_user") or {}
|
||||
return int(running_by_user.get(int(user_id), running_by_user.get(str(user_id), 0)) or 0)
|
||||
except Exception:
|
||||
current_running = 0
|
||||
for _, info in safe_iter_task_status_items():
|
||||
if info.get("user_id") == user_id and info.get("status") == "运行中":
|
||||
current_running += 1
|
||||
return current_running
|
||||
|
||||
|
||||
@api_user_bp.route("/api/announcements/active", methods=["GET"])
|
||||
@login_required
|
||||
def get_active_announcement():
|
||||
@@ -77,8 +161,7 @@ def submit_feedback():
|
||||
if len(description) > 2000:
|
||||
return jsonify({"error": "描述不能超过2000个字符"}), 400
|
||||
|
||||
user_info = database.get_user_by_id(current_user.id)
|
||||
username = user_info["username"] if user_info else f"用户{current_user.id}"
|
||||
username = _get_current_username(fallback=f"用户{current_user.id}")
|
||||
|
||||
feedback_id = database.create_bug_feedback(
|
||||
user_id=current_user.id,
|
||||
@@ -104,8 +187,7 @@ def get_my_feedbacks():
|
||||
def get_current_user_vip():
|
||||
"""获取当前用户VIP信息"""
|
||||
vip_info = database.get_user_vip_info(current_user.id)
|
||||
user_info = database.get_user_by_id(current_user.id)
|
||||
vip_info["username"] = user_info["username"] if user_info else "Unknown"
|
||||
vip_info["username"] = _get_current_username(fallback="Unknown")
|
||||
return jsonify(vip_info)
|
||||
|
||||
|
||||
@@ -124,9 +206,9 @@ def change_user_password():
|
||||
if not is_valid:
|
||||
return jsonify({"error": error_msg}), 400
|
||||
|
||||
user = database.get_user_by_id(current_user.id)
|
||||
if not user:
|
||||
return jsonify({"error": "用户不存在"}), 404
|
||||
user, error_response = _get_current_user_or_404()
|
||||
if error_response:
|
||||
return error_response
|
||||
|
||||
username = user.get("username", "")
|
||||
if not username or not database.verify_user(username, current_password):
|
||||
@@ -141,9 +223,9 @@ def change_user_password():
|
||||
@login_required
|
||||
def get_user_email():
|
||||
"""获取当前用户的邮箱信息"""
|
||||
user = database.get_user_by_id(current_user.id)
|
||||
if not user:
|
||||
return jsonify({"error": "用户不存在"}), 404
|
||||
user, error_response = _get_current_user_or_404()
|
||||
if error_response:
|
||||
return error_response
|
||||
|
||||
return jsonify({"email": user.get("email", ""), "email_verified": user.get("email_verified", False)})
|
||||
|
||||
@@ -172,14 +254,9 @@ def update_user_kdocs_settings():
|
||||
return jsonify({"error": "县区长度不能超过50"}), 400
|
||||
|
||||
if kdocs_auto_upload is not None:
|
||||
if isinstance(kdocs_auto_upload, bool):
|
||||
kdocs_auto_upload = 1 if kdocs_auto_upload else 0
|
||||
try:
|
||||
kdocs_auto_upload = int(kdocs_auto_upload)
|
||||
except Exception:
|
||||
return jsonify({"error": "自动上传开关必须是0或1"}), 400
|
||||
if kdocs_auto_upload not in (0, 1):
|
||||
return jsonify({"error": "自动上传开关必须是0或1"}), 400
|
||||
kdocs_auto_upload, parse_error = _coerce_binary_flag(kdocs_auto_upload, field_label="自动上传开关")
|
||||
if parse_error:
|
||||
return jsonify({"error": parse_error}), 400
|
||||
|
||||
if not database.update_user_kdocs_settings(
|
||||
current_user.id,
|
||||
@@ -207,13 +284,9 @@ def bind_user_email():
|
||||
if not is_valid:
|
||||
return jsonify({"error": error_msg}), 400
|
||||
|
||||
client_ip = get_rate_limit_ip()
|
||||
allowed, error_msg = check_ip_request_rate(client_ip, "email")
|
||||
allowed, error_msg, status_code = _check_bind_email_rate_limits(email)
|
||||
if not allowed:
|
||||
return jsonify({"error": error_msg}), 429
|
||||
allowed, error_msg = check_email_rate_limit(email, "bind_email")
|
||||
if not allowed:
|
||||
return jsonify({"error": error_msg}), 429
|
||||
return jsonify({"error": error_msg}), status_code
|
||||
|
||||
settings = email_service.get_email_settings()
|
||||
if not settings.get("enabled", False):
|
||||
@@ -223,9 +296,9 @@ def bind_user_email():
|
||||
if existing_user and existing_user["id"] != current_user.id:
|
||||
return jsonify({"error": "该邮箱已被其他用户绑定"}), 400
|
||||
|
||||
user = database.get_user_by_id(current_user.id)
|
||||
if not user:
|
||||
return jsonify({"error": "用户不存在"}), 404
|
||||
user, error_response = _get_current_user_or_404()
|
||||
if error_response:
|
||||
return error_response
|
||||
|
||||
if user.get("email") == email and user.get("email_verified"):
|
||||
return jsonify({"error": "该邮箱已绑定并验证"}), 400
|
||||
@@ -247,56 +320,20 @@ def verify_bind_email(token):
|
||||
email = result["email"]
|
||||
|
||||
if database.update_user_email(user_id, email, verified=True):
|
||||
spa_initial_state = {
|
||||
"page": "verify_result",
|
||||
"success": True,
|
||||
"title": "邮箱绑定成功",
|
||||
"message": f"邮箱 {email} 已成功绑定到您的账号!",
|
||||
"primary_label": "返回登录",
|
||||
"primary_url": "/login",
|
||||
"redirect_url": "/login",
|
||||
"redirect_seconds": 5,
|
||||
}
|
||||
return render_app_spa_or_legacy("verify_success.html", spa_initial_state=spa_initial_state)
|
||||
return _render_verify_bind_success(email)
|
||||
|
||||
error_message = "邮箱绑定失败,请重试"
|
||||
spa_initial_state = {
|
||||
"page": "verify_result",
|
||||
"success": False,
|
||||
"title": "绑定失败",
|
||||
"error_message": error_message,
|
||||
"primary_label": "返回登录",
|
||||
"primary_url": "/login",
|
||||
}
|
||||
return render_app_spa_or_legacy(
|
||||
"verify_failed.html",
|
||||
legacy_context={"error_message": error_message},
|
||||
spa_initial_state=spa_initial_state,
|
||||
)
|
||||
return _render_verify_bind_failed(title="绑定失败", error_message="邮箱绑定失败,请重试")
|
||||
|
||||
error_message = "验证链接已过期或无效,请重新发送验证邮件"
|
||||
spa_initial_state = {
|
||||
"page": "verify_result",
|
||||
"success": False,
|
||||
"title": "链接无效",
|
||||
"error_message": error_message,
|
||||
"primary_label": "返回登录",
|
||||
"primary_url": "/login",
|
||||
}
|
||||
return render_app_spa_or_legacy(
|
||||
"verify_failed.html",
|
||||
legacy_context={"error_message": error_message},
|
||||
spa_initial_state=spa_initial_state,
|
||||
)
|
||||
return _render_verify_bind_failed(title="链接无效", error_message="验证链接已过期或无效,请重新发送验证邮件")
|
||||
|
||||
|
||||
@api_user_bp.route("/api/user/unbind-email", methods=["POST"])
|
||||
@login_required
|
||||
def unbind_user_email():
|
||||
"""解绑用户邮箱"""
|
||||
user = database.get_user_by_id(current_user.id)
|
||||
if not user:
|
||||
return jsonify({"error": "用户不存在"}), 404
|
||||
user, error_response = _get_current_user_or_404()
|
||||
if error_response:
|
||||
return error_response
|
||||
|
||||
if not user.get("email"):
|
||||
return jsonify({"error": "当前未绑定邮箱"}), 400
|
||||
@@ -334,10 +371,7 @@ def get_run_stats():
|
||||
|
||||
stats = database.get_user_run_stats(user_id)
|
||||
|
||||
current_running = 0
|
||||
for _, info in safe_iter_task_status_items():
|
||||
if info.get("user_id") == user_id and info.get("status") == "运行中":
|
||||
current_running += 1
|
||||
current_running = _get_current_running_count(user_id)
|
||||
|
||||
return jsonify(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user