Spaces:
Running
Running
Upload router_users.py
Browse files- router_users.py +41 -15
router_users.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
# router_users.py
|
| 2 |
-
from fastapi import APIRouter, HTTPException, BackgroundTasks
|
| 3 |
import time
|
| 4 |
import re
|
| 5 |
import random
|
|
@@ -261,38 +261,64 @@ async def update_user_profile(account: str, update_data: UserUpdate):
|
|
| 261 |
db.save_data("users.json", users_db)
|
| 262 |
return {"status": "success", "data": {k: v for k, v in user.items() if k != "password"}}
|
| 263 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 264 |
@router.post("/api/users/reset_password")
|
| 265 |
-
async def reset_password(
|
| 266 |
-
# 1.
|
| 267 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 269 |
users_db = db.load_data("users.json", default_data={})
|
| 270 |
-
if account not in users_db: raise HTTPException(status_code=404, detail="用户不存在")
|
| 271 |
user = users_db[account]
|
| 272 |
|
| 273 |
-
|
| 274 |
-
if pwd_data.verifyType == "email" and user.get("email") != pwd_data.verifyContact:
|
| 275 |
raise HTTPException(status_code=400, detail="填写的邮箱与该账号绑定的邮箱不匹配")
|
| 276 |
-
if
|
| 277 |
raise HTTPException(status_code=400, detail="填写的手机号与该账号绑定的手机号不匹配")
|
| 278 |
|
| 279 |
-
cache_key = f"{
|
| 280 |
cached = VERIFY_CODES.get(cache_key)
|
| 281 |
-
|
| 282 |
-
# 安全获取过期时间防崩
|
| 283 |
expire_time = cached.get("expires_at", cached.get("expires", 0)) if cached else 0
|
| 284 |
-
|
|
|
|
| 285 |
raise HTTPException(status_code=400, detail="验证码不正确或已过期")
|
| 286 |
|
| 287 |
-
if len(
|
| 288 |
-
if not re.match(r'^[a-zA-Z0-9!@#$%^&*()_+\-=\[\]{};\':"\\|,.<>\/?]{6,}$',
|
| 289 |
|
| 290 |
VERIFY_CODES.pop(cache_key, None)
|
| 291 |
-
user["password"] =
|
| 292 |
db.save_data("users.json", users_db)
|
| 293 |
|
| 294 |
return {"status": "success", "message": "密码修改成功"}
|
| 295 |
|
|
|
|
| 296 |
@router.post("/api/users/follow")
|
| 297 |
async def toggle_follow(follow: FollowToggle):
|
| 298 |
users_db = db.load_data("users.json", default_data={})
|
|
|
|
| 1 |
# router_users.py
|
| 2 |
+
from fastapi import APIRouter, HTTPException, BackgroundTasks, Request
|
| 3 |
import time
|
| 4 |
import re
|
| 5 |
import random
|
|
|
|
| 261 |
db.save_data("users.json", users_db)
|
| 262 |
return {"status": "success", "data": {k: v for k, v in user.items() if k != "password"}}
|
| 263 |
|
| 264 |
+
|
| 265 |
+
# ==========================================
|
| 266 |
+
# 🚀 万能重置密码接口:杜绝所有前端数据格式 422 报错
|
| 267 |
+
# ==========================================
|
| 268 |
@router.post("/api/users/reset_password")
|
| 269 |
+
async def reset_password(request: Request):
|
| 270 |
+
# 1. 万能解析器:兼容 JSON、双重字符串化、以及 FormData
|
| 271 |
+
try:
|
| 272 |
+
data = await request.json()
|
| 273 |
+
if isinstance(data, str): # 核心:拦截前端可能造成的"双重字符串化"
|
| 274 |
+
data = json.loads(data)
|
| 275 |
+
except:
|
| 276 |
+
try:
|
| 277 |
+
form = await request.form()
|
| 278 |
+
data = dict(form)
|
| 279 |
+
except:
|
| 280 |
+
raise HTTPException(status_code=400, detail="请求数据解析失败,请检查网络")
|
| 281 |
+
|
| 282 |
+
if not isinstance(data, dict):
|
| 283 |
+
raise HTTPException(status_code=400, detail=f"前端数据格式异常,收到的是: {type(data).__name__}")
|
| 284 |
+
|
| 285 |
+
# 2. 万能提取器:同时兼容前端的命名习惯误差
|
| 286 |
+
account = data.get("account")
|
| 287 |
+
new_password = data.get("new_password") or data.get("password")
|
| 288 |
+
verify_contact = data.get("verifyContact") or data.get("verify_contact") or data.get("email") or data.get("phone")
|
| 289 |
+
verify_type = data.get("verifyType") or data.get("verify_type") or data.get("contact_type")
|
| 290 |
+
code = data.get("code")
|
| 291 |
|
| 292 |
+
if not all([account, new_password, verify_contact, verify_type, code]):
|
| 293 |
+
raise HTTPException(status_code=400, detail="缺失必要参数 (账号/密码/验证码/联系方式),请检查表单")
|
| 294 |
+
|
| 295 |
+
# 3. 核心业务逻辑
|
| 296 |
users_db = db.load_data("users.json", default_data={})
|
| 297 |
+
if account not in users_db: raise HTTPException(status_code=404, detail="该用户不存在")
|
| 298 |
user = users_db[account]
|
| 299 |
|
| 300 |
+
if verify_type == "email" and user.get("email") != verify_contact:
|
|
|
|
| 301 |
raise HTTPException(status_code=400, detail="填写的邮箱与该账号绑定的邮箱不匹配")
|
| 302 |
+
if verify_type == "phone" and user.get("phone") != verify_contact:
|
| 303 |
raise HTTPException(status_code=400, detail="填写的手机号与该账号绑定的手机号不匹配")
|
| 304 |
|
| 305 |
+
cache_key = f"{verify_contact}_reset"
|
| 306 |
cached = VERIFY_CODES.get(cache_key)
|
|
|
|
|
|
|
| 307 |
expire_time = cached.get("expires_at", cached.get("expires", 0)) if cached else 0
|
| 308 |
+
|
| 309 |
+
if not cached or cached["code"] != code or time.time() > expire_time:
|
| 310 |
raise HTTPException(status_code=400, detail="验证码不正确或已过期")
|
| 311 |
|
| 312 |
+
if len(new_password) < 6: raise HTTPException(status_code=400, detail="新密码必须大于等于6个字符")
|
| 313 |
+
if not re.match(r'^[a-zA-Z0-9!@#$%^&*()_+\-=\[\]{};\':"\\|,.<>\/?]{6,}$', new_password): raise HTTPException(status_code=400, detail="新密码包含不支持的特殊字符")
|
| 314 |
|
| 315 |
VERIFY_CODES.pop(cache_key, None)
|
| 316 |
+
user["password"] = new_password
|
| 317 |
db.save_data("users.json", users_db)
|
| 318 |
|
| 319 |
return {"status": "success", "message": "密码修改成功"}
|
| 320 |
|
| 321 |
+
|
| 322 |
@router.post("/api/users/follow")
|
| 323 |
async def toggle_follow(follow: FollowToggle):
|
| 324 |
users_db = db.load_data("users.json", default_data={})
|