ZHIWEI666 commited on
Commit
389fb25
·
verified ·
1 Parent(s): 6c3e64f

Upload 8 files

Browse files
router_posts.py CHANGED
@@ -515,14 +515,14 @@ async def tip_post(request: Request, post_id: str, amount: int, is_anon: bool =
515
  db_session.commit()
516
 
517
  # 📝 审计日志
518
- logger.info(f"POST_TIP | post={post_id}")
519
 
520
  except HTTPException:
521
  db_session.rollback()
522
  raise
523
  except Exception as e:
524
  db_session.rollback()
525
- logger.error(f"POST_TIP_ERROR | post={post_id} | error_type={type(e).__name__}")
526
  raise HTTPException(status_code=500, detail="打赏处理失败,请稍后重试")
527
 
528
  def notify_tip():
@@ -564,7 +564,7 @@ async def tip_post(request: Request, post_id: str, amount: int, is_anon: bool =
564
  try:
565
  db.atomic_update("posts.json", board_updater, default_data=[])
566
  except Exception as e:
567
- logger.error(f"POST_TIP_BOARD_ERROR | post={post_id} | error_type={type(e).__name__}")
568
 
569
  return {"status": "success", "message": f"成功打赏 {amount} 积分"}
570
 
 
515
  db_session.commit()
516
 
517
  # 📝 审计日志
518
+ logger.info("POST_TIP")
519
 
520
  except HTTPException:
521
  db_session.rollback()
522
  raise
523
  except Exception as e:
524
  db_session.rollback()
525
+ logger.error("POST_TIP_ERROR | error_type=%s", type(e).__name__)
526
  raise HTTPException(status_code=500, detail="打赏处理失败,请稍后重试")
527
 
528
  def notify_tip():
 
564
  try:
565
  db.atomic_update("posts.json", board_updater, default_data=[])
566
  except Exception as e:
567
+ logger.error("POST_TIP_BOARD_ERROR | error_type=%s", type(e).__name__)
568
 
569
  return {"status": "success", "message": f"成功打赏 {amount} 积分"}
570
 
router_prompts.py CHANGED
@@ -744,14 +744,14 @@ async def tip_prompt(request: Request, prompt_id: str, amount: int, is_anon: boo
744
  db_session.commit()
745
 
746
  # 📝 审计日志
747
- logger.info(f"PROMPT_TIP | prompt={prompt_id}")
748
 
749
  except HTTPException:
750
  db_session.rollback()
751
  raise
752
  except Exception as e:
753
  db_session.rollback()
754
- logger.error(f"PROMPT_TIP_ERROR | prompt={prompt_id} | error_type={type(e).__name__}")
755
  raise HTTPException(status_code=500, detail="打赏处理失败,请稍后重试")
756
 
757
  def notify_tip():
@@ -793,7 +793,7 @@ async def tip_prompt(request: Request, prompt_id: str, amount: int, is_anon: boo
793
  try:
794
  db.atomic_update("prompts.json", board_updater, default_data=[])
795
  except Exception as e:
796
- logger.error(f"PROMPT_TIP_BOARD_ERROR | prompt={prompt_id} | error_type={type(e).__name__}")
797
 
798
  return {"status": "success", "message": f"成功打赏 {amount} 积分"}
799
 
 
744
  db_session.commit()
745
 
746
  # 📝 审计日志
747
+ logger.info("PROMPT_TIP")
748
 
749
  except HTTPException:
750
  db_session.rollback()
751
  raise
752
  except Exception as e:
753
  db_session.rollback()
754
+ logger.error("PROMPT_TIP_ERROR | error_type=%s", type(e).__name__)
755
  raise HTTPException(status_code=500, detail="打赏处理失败,请稍后重试")
756
 
757
  def notify_tip():
 
793
  try:
794
  db.atomic_update("prompts.json", board_updater, default_data=[])
795
  except Exception as e:
796
+ logger.error("PROMPT_TIP_BOARD_ERROR | error_type=%s", type(e).__name__)
797
 
798
  return {"status": "success", "message": f"成功打赏 {amount} 积分"}
799
 
router_tasks.py CHANGED
@@ -93,7 +93,7 @@ def create_task_transaction(db_session: Session, account: str, tx_type: str, amo
93
  )
94
  db_session.add(new_tx)
95
 
96
- logger.info(f"TASK_TX | type={tx_type} | task={task_id} | tx={tx_id}")
97
  return tx_id
98
 
99
  # ==========================================
@@ -1029,14 +1029,14 @@ async def tip_task(request: Request, task_id: str, amount: int, is_anon: bool =
1029
  db_session.commit()
1030
 
1031
  # 📝 审计日志
1032
- logger.info(f"TASK_TIP | task={task_id}")
1033
 
1034
  except HTTPException:
1035
  db_session.rollback()
1036
  raise
1037
  except Exception as e:
1038
  db_session.rollback()
1039
- logger.error(f"TASK_TIP_ERROR | task={task_id} | error_type={type(e).__name__}")
1040
  raise HTTPException(status_code=500, detail="打赏处理失败,请稍后重试")
1041
 
1042
  def notify_tip():
@@ -1078,7 +1078,7 @@ async def tip_task(request: Request, task_id: str, amount: int, is_anon: bool =
1078
  try:
1079
  db.atomic_update("tasks.json", board_updater, default_data=[])
1080
  except Exception as e:
1081
- logger.error(f"TASK_TIP_BOARD_ERROR | task={task_id} | error_type={type(e).__name__}")
1082
 
1083
  return {"status": "success", "message": f"成功打赏 {amount} 积分"}
1084
 
 
93
  )
94
  db_session.add(new_tx)
95
 
96
+ logger.info("TASK_TX")
97
  return tx_id
98
 
99
  # ==========================================
 
1029
  db_session.commit()
1030
 
1031
  # 📝 审计日志
1032
+ logger.info("TASK_TIP")
1033
 
1034
  except HTTPException:
1035
  db_session.rollback()
1036
  raise
1037
  except Exception as e:
1038
  db_session.rollback()
1039
+ logger.error("TASK_TIP_ERROR | error_type=%s", type(e).__name__)
1040
  raise HTTPException(status_code=500, detail="打赏处理失败,请稍后重试")
1041
 
1042
  def notify_tip():
 
1078
  try:
1079
  db.atomic_update("tasks.json", board_updater, default_data=[])
1080
  except Exception as e:
1081
+ logger.error("TASK_TIP_BOARD_ERROR | error_type=%s", type(e).__name__)
1082
 
1083
  return {"status": "success", "message": f"成功打赏 {amount} 积分"}
1084
 
router_users_auth.py CHANGED
@@ -23,7 +23,7 @@ from models import UserRegister, UserLogin, SendCodeRequest
23
  from verify_code_engine import send_email_code, send_sms_code, cleanup_expired_codes, check_send_cooldown
24
 
25
  # 🔒 P0安全增强:导入密码哈希和 JWT 工具
26
- from 安全认证 import hash_password, verify_password, create_token, require_password_match
27
 
28
  from user_store import read_user, check_registration, create_user, finish_login, reset_user_password, get_password_version
29
 
@@ -52,7 +52,20 @@ def _find_contact_account(contact, contact_type):
52
  raise HTTPException(status_code=503, detail="用户数据暂不可用") from None
53
 
54
 
55
- async def _check_code_contact(req):
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  if req.action_type == "recover":
57
  account, _ = await asyncio.to_thread(_find_contact_account, req.contact, req.contact_type)
58
  return account is not None
@@ -83,7 +96,7 @@ async def send_verify_code(request: Request, req: SendCodeRequest, bg_tasks: Bac
83
  - action_type: "register" 注册 / "reset" 重置密码 / "recover" 找回账号
84
  - account: (仅重置密码时必填) 用户账号
85
  """
86
- if not await _check_code_contact(req):
87
  return {"status": "success", "message": "如果该联系方式已绑定账号,验证码已发送"}
88
 
89
  # 🔒 检查发送频率限制(同一联系方式60秒内只能发送1条)
@@ -121,7 +134,7 @@ async def send_verify_code(request: Request, req: SendCodeRequest, bg_tasks: Bac
121
  @shared_limit(5) # 🔒 安全限流:与异步版对齐,每分钟最多5次
122
  async def send_code_api(request: Request, req: SendCodeRequest):
123
  """发送验证码接口(同步版本,直接等待发送结果)"""
124
- if not await _check_code_contact(req):
125
  return {"status": "success", "message": "如果该联系方式已绑定账号,验证码已发送"}
126
 
127
  # 🔒 检查发送频率限制(同一联系方式60秒内只能发送1条)
 
23
  from verify_code_engine import send_email_code, send_sms_code, cleanup_expired_codes, check_send_cooldown
24
 
25
  # 🔒 P0安全增强:导入密码哈希和 JWT 工具
26
+ from 安全认证 import hash_password, verify_password, create_token, require_password_match, require_auth
27
 
28
  from user_store import read_user, check_registration, create_user, finish_login, reset_user_password, get_password_version
29
 
 
52
  raise HTTPException(status_code=503, detail="用户数据暂不可用") from None
53
 
54
 
55
+ async def _check_code_contact(req, request=None):
56
+ if req.action_type == "withdraw":
57
+ if request is None:
58
+ raise HTTPException(status_code=401, detail="请先登录")
59
+ account = await require_auth(request.headers.get("Authorization"))
60
+ if req.account is not None and req.account != account:
61
+ raise HTTPException(status_code=403, detail="无权为其他账号请求提现验证码")
62
+ user = await asyncio.to_thread(read_user, account)
63
+ contact = user.get("email") or user.get("phone", "")
64
+ contact_type = "email" if user.get("email") else "phone"
65
+ if (not isinstance(contact, str) or not contact.strip() or
66
+ req.contact_type != contact_type or req.contact != contact):
67
+ raise HTTPException(status_code=400, detail="联系方式与当前账号绑定信息不匹配")
68
+ return True
69
  if req.action_type == "recover":
70
  account, _ = await asyncio.to_thread(_find_contact_account, req.contact, req.contact_type)
71
  return account is not None
 
96
  - action_type: "register" 注册 / "reset" 重置密码 / "recover" 找回账号
97
  - account: (仅重置密码时必填) 用户账号
98
  """
99
+ if not await _check_code_contact(req, request):
100
  return {"status": "success", "message": "如果该联系方式已绑定账号,验证码已发送"}
101
 
102
  # 🔒 检查发送频率限制(同一联系方式60秒内只能发送1条)
 
134
  @shared_limit(5) # 🔒 安全限流:与异步版对齐,每分钟最多5次
135
  async def send_code_api(request: Request, req: SendCodeRequest):
136
  """发送验证码接口(同步版本,直接等待发送结果)"""
137
+ if not await _check_code_contact(req, request):
138
  return {"status": "success", "message": "如果该联系方式已绑定账号,验证码已发送"}
139
 
140
  # 🔒 检查发送频率限制(同一联系方式60秒内只能发送1条)
workflow_download_service.py CHANGED
@@ -40,7 +40,7 @@ async def prepare_workflow_download(item, item_id, *, store, source_authorizer,
40
  close_owned_resources = resources.close
41
 
42
  try:
43
- print(f"🔍 开始下载资源 [{item_id}]")
44
  for redirect_count in range(6):
45
  host = await validate_target(target_url)
46
  headers = {"User-Agent": "ComfyUI-Ranking-SaaS", "Accept-Encoding": "identity"}
@@ -107,5 +107,5 @@ async def prepare_workflow_download(item, item_id, *, store, source_authorizer,
107
  return error_response(content={"error": "下载超时,请稍后重试"}, status_code=504)
108
  except Exception as e:
109
  await close_owned_resources()
110
- print(f"❌ 代理下载异常 [{item_id}]: {type(e).__name__}")
111
  return error_response(content={"error": "代理下载失败,请检查资源链接后重试"}, status_code=502)
 
40
  close_owned_resources = resources.close
41
 
42
  try:
43
+ print("WORKFLOW_DOWNLOAD_STARTED")
44
  for redirect_count in range(6):
45
  host = await validate_target(target_url)
46
  headers = {"User-Agent": "ComfyUI-Ranking-SaaS", "Accept-Encoding": "identity"}
 
107
  return error_response(content={"error": "下载超时,请稍后重试"}, status_code=504)
108
  except Exception as e:
109
  await close_owned_resources()
110
+ print(f"WORKFLOW_DOWNLOAD_FAILED | error_type={type(e).__name__}")
111
  return error_response(content={"error": "代理下载失败,请检查资源链接后重试"}, status_code=502)
安全认证.py CHANGED
@@ -34,15 +34,21 @@ import bcrypt
34
  _DEFAULT_JWT_SECRET = "ComfyUI-Ranking-JWT-Secret-v2-beta-2026"
35
  _DEFAULT_PASSWORD_SALT = "ComfyUI-Ranking-Salt-v1"
36
 
37
- JWT_SECRET = os.environ.get("JWT_SECRET") or _DEFAULT_JWT_SECRET
 
38
  PASSWORD_SALT = os.environ.get("PASSWORD_SALT") or _DEFAULT_PASSWORD_SALT
39
 
40
  # 🔒 生产环境必须使用部署密钥:公开默认值只允许本地开发使用。
41
  # HF Spaces 或显式生产部署缺少密钥时拒绝启动,避免继续签发可伪造 Token。
42
- _IS_PRODUCTION = bool(os.environ.get("SPACE_ID")) or os.environ.get("APP_ENV", "").lower() == "production"
43
- if _IS_PRODUCTION and not os.environ.get("JWT_SECRET"):
44
- raise RuntimeError("生产环境必须配置随机 JWT_SECRET;拒绝使用源码内置默认密钥启动")
45
- if not os.environ.get("JWT_SECRET"):
 
 
 
 
 
46
  print("⚠️ [安全提示] 未设置 JWT_SECRET,当前使用仅供本地开发的默认密钥")
47
 
48
  # Token 有效期配置(单位:秒)
 
34
  _DEFAULT_JWT_SECRET = "ComfyUI-Ranking-JWT-Secret-v2-beta-2026"
35
  _DEFAULT_PASSWORD_SALT = "ComfyUI-Ranking-Salt-v1"
36
 
37
+ _CONFIGURED_JWT_SECRET = os.environ.get("JWT_SECRET")
38
+ JWT_SECRET = _CONFIGURED_JWT_SECRET or _DEFAULT_JWT_SECRET
39
  PASSWORD_SALT = os.environ.get("PASSWORD_SALT") or _DEFAULT_PASSWORD_SALT
40
 
41
  # 🔒 生产环境必须使用部署密钥:公开默认值只允许本地开发使用。
42
  # HF Spaces 或显式生产部署缺少密钥时拒绝启动,避免继续签发可伪造 Token。
43
+ _IS_PRODUCTION = bool(os.environ.get("SPACE_ID")) or os.environ.get("APP_ENV", "").strip().lower() == "production"
44
+ if _IS_PRODUCTION and (
45
+ not _CONFIGURED_JWT_SECRET
46
+ or not _CONFIGURED_JWT_SECRET.strip()
47
+ or _CONFIGURED_JWT_SECRET.strip() == _DEFAULT_JWT_SECRET
48
+ or len(_CONFIGURED_JWT_SECRET.encode("utf-8")) < 32
49
+ ):
50
+ raise RuntimeError("生产环境 JWT_SECRET 无效:必须使用至少32字节的独立随机密钥,禁止公开开发密钥或空白值")
51
+ if not _CONFIGURED_JWT_SECRET:
52
  print("⚠️ [安全提示] 未设置 JWT_SECRET,当前使用仅供本地开发的默认密钥")
53
 
54
  # Token 有效期配置(单位:秒)