ZHIWEI666 commited on
Commit
40a5561
·
verified ·
1 Parent(s): 3ff2ccf

Upload router_users.py

Browse files
Files changed (1) hide show
  1. router_users.py +25 -15
router_users.py CHANGED
@@ -161,13 +161,28 @@ async def send_verify_code(req: SendCodeRequest, bg_tasks: BackgroundTasks):
161
 
162
  return {"status": "success", "message": "验证码发送请求已提交"}
163
 
 
164
  @router.post("/api/users/register")
165
  async def register_user(user: UserRegister):
166
  users_db = db.load_data("users.json", default_data={})
167
 
 
 
 
 
 
 
 
 
 
 
168
  cache_key = f"{user.email}_register" if user.email else f"{user.phone}_register"
169
  cached = VERIFY_CODES.get(cache_key)
170
- if not cached or cached["code"] != user.code or int(time.time()) > cached["expires_at"]:
 
 
 
 
171
  raise HTTPException(status_code=400, detail="验证码不正确或已过期")
172
 
173
  if len(user.account) <= 5: raise HTTPException(status_code=400, detail="账号必须大于5个字符")
@@ -175,10 +190,6 @@ async def register_user(user: UserRegister):
175
  if len(user.password) < 6: raise HTTPException(status_code=400, detail="密码必须大于等于6个字符")
176
  if not re.match(r'^[a-zA-Z0-9!@#$%^&*()_+\-=\[\]{};\':"\\|,.<>\/?]{6,}$', user.password): raise HTTPException(status_code=400, detail="密码包含不支持的特殊字符")
177
  if user.intro and len(user.intro) > 100: raise HTTPException(status_code=400, detail="个人介绍不能超过100个字符")
178
- if user.account in users_db: raise HTTPException(status_code=400, detail="该账号已被注册")
179
- for existing_user in users_db.values():
180
- if user.email and existing_user.get("email") == user.email: raise HTTPException(status_code=400, detail="该邮箱已被绑定")
181
- if user.phone and existing_user.get("phone") == user.phone: raise HTTPException(status_code=400, detail="该手机号已被绑定")
182
 
183
  VERIFY_CODES.pop(cache_key, None)
184
 
@@ -189,6 +200,7 @@ async def register_user(user: UserRegister):
189
  db.save_data("users.json", users_db)
190
  return {"status": "success", "message": "注册成功", "data": {k: v for k, v in new_user.items() if k != "password"}}
191
 
 
192
  @router.post("/api/users/login")
193
  async def login_user(user: UserLogin):
194
  users_db = db.load_data("users.json", default_data={})
@@ -197,40 +209,35 @@ async def login_user(user: UserLogin):
197
  if user_data.get("password") != user.password: raise HTTPException(status_code=401, detail="密码错误")
198
  return {"status": "success", "token": f"mock_token_{user.account}", "account": user.account, "name": user_data["name"], "avatar": user_data.get("avatarDataUrl", "https://via.placeholder.com/150")}
199
 
 
200
  # ==========================================
201
  # 补充:发送验证码的 API 接口
202
  # ==========================================
203
  @router.post("/api/users/send_code")
204
  async def send_code_api(req: SendCodeRequest):
205
- # 1. 生成 6 位随机数字验证码
206
  code = str(random.randint(100000, 999999))
207
-
208
- # 2. 生成缓存 Key (格式: 邮箱地址_动作)
209
- # 例如: test@qq.com_register 或 test@qq.com_reset
210
  key = f"{req.contact}_{req.action_type}"
211
 
212
- # 3. 存入全局内存字典 (设置有效期为 10 分钟 = 600 秒)
213
  VERIFY_CODES[key] = {
214
  "code": code,
215
- "expires": time.time() + 600
216
  }
217
 
218
- # 4. 触发发送逻辑
219
  if req.contact_type == "email":
220
  try:
221
- # 调用你文件里已经写好的通过 Make.com Webhook 发邮件的函数
222
  send_email_code(req.contact, code, req.action_type)
223
  return {"status": "success", "message": "验证码已成功发送至邮箱"}
224
  except Exception as e:
225
  raise HTTPException(status_code=500, detail=f"邮件发送失败: {str(e)}")
226
 
227
  elif req.contact_type == "phone":
228
- # 预留的短信通道
229
  return {"status": "success", "message": "验证码已成功发送至手机"}
230
 
231
  else:
232
  raise HTTPException(status_code=400, detail="不支持的验证方式")
233
 
 
234
  @router.get("/api/users/{account}")
235
  async def get_user_profile(account: str):
236
  users_db = db.load_data("users.json", default_data={})
@@ -267,7 +274,10 @@ async def reset_password(account: str, pwd_data: PasswordReset):
267
 
268
  cache_key = f"{pwd_data.verify_contact}_reset"
269
  cached = VERIFY_CODES.get(cache_key)
270
- if not cached or cached["code"] != pwd_data.code or int(time.time()) > cached["expires_at"]:
 
 
 
271
  raise HTTPException(status_code=400, detail="验证码不正确或已过期")
272
 
273
  if len(pwd_data.new_password) < 6: raise HTTPException(status_code=400, detail="新密码必须大于等于6个字符")
 
161
 
162
  return {"status": "success", "message": "验证码发送请求已提交"}
163
 
164
+
165
  @router.post("/api/users/register")
166
  async def register_user(user: UserRegister):
167
  users_db = db.load_data("users.json", default_data={})
168
 
169
+ # 🚀 核心修复 1:将查重逻辑移到最前面!一旦重复直接拦截,绝不会发生 500 崩溃
170
+ if user.account in users_db:
171
+ raise HTTPException(status_code=400, detail="该账号已被注册,请更换一个")
172
+ for existing_user in users_db.values():
173
+ if user.email and existing_user.get("email") == user.email:
174
+ raise HTTPException(status_code=400, detail="此邮箱已注册,请直接登录或找回密码")
175
+ if user.phone and existing_user.get("phone") == user.phone:
176
+ raise HTTPException(status_code=400, detail="该手机号已被绑定")
177
+
178
+ # 获取验证码缓存记录
179
  cache_key = f"{user.email}_register" if user.email else f"{user.phone}_register"
180
  cached = VERIFY_CODES.get(cache_key)
181
+
182
+ # 🚀 核心修复 2:安全地获取过期时间,兼容新老写法,彻底消灭 KeyError 导致的 500
183
+ expire_time = cached.get("expires_at", cached.get("expires", 0)) if cached else 0
184
+
185
+ if not cached or cached["code"] != user.code or time.time() > expire_time:
186
  raise HTTPException(status_code=400, detail="验证码不正确或已过期")
187
 
188
  if len(user.account) <= 5: raise HTTPException(status_code=400, detail="账号必须大于5个字符")
 
190
  if len(user.password) < 6: raise HTTPException(status_code=400, detail="密码必须大于等于6个字符")
191
  if not re.match(r'^[a-zA-Z0-9!@#$%^&*()_+\-=\[\]{};\':"\\|,.<>\/?]{6,}$', user.password): raise HTTPException(status_code=400, detail="密码包含不支持的特殊字符")
192
  if user.intro and len(user.intro) > 100: raise HTTPException(status_code=400, detail="个人介绍不能超过100个字符")
 
 
 
 
193
 
194
  VERIFY_CODES.pop(cache_key, None)
195
 
 
200
  db.save_data("users.json", users_db)
201
  return {"status": "success", "message": "注册成功", "data": {k: v for k, v in new_user.items() if k != "password"}}
202
 
203
+
204
  @router.post("/api/users/login")
205
  async def login_user(user: UserLogin):
206
  users_db = db.load_data("users.json", default_data={})
 
209
  if user_data.get("password") != user.password: raise HTTPException(status_code=401, detail="密码错误")
210
  return {"status": "success", "token": f"mock_token_{user.account}", "account": user.account, "name": user_data["name"], "avatar": user_data.get("avatarDataUrl", "https://via.placeholder.com/150")}
211
 
212
+
213
  # ==========================================
214
  # 补充:发送验证码的 API 接口
215
  # ==========================================
216
  @router.post("/api/users/send_code")
217
  async def send_code_api(req: SendCodeRequest):
 
218
  code = str(random.randint(100000, 999999))
 
 
 
219
  key = f"{req.contact}_{req.action_type}"
220
 
221
+ # 🚀 核心修复 3:统一改成 expires_at,与全局校验逻辑完美对齐
222
  VERIFY_CODES[key] = {
223
  "code": code,
224
+ "expires_at": time.time() + 600
225
  }
226
 
 
227
  if req.contact_type == "email":
228
  try:
 
229
  send_email_code(req.contact, code, req.action_type)
230
  return {"status": "success", "message": "验证码已成功发送至邮箱"}
231
  except Exception as e:
232
  raise HTTPException(status_code=500, detail=f"邮件发送失败: {str(e)}")
233
 
234
  elif req.contact_type == "phone":
 
235
  return {"status": "success", "message": "验证码已成功发送至手机"}
236
 
237
  else:
238
  raise HTTPException(status_code=400, detail="不支持的验证方式")
239
 
240
+
241
  @router.get("/api/users/{account}")
242
  async def get_user_profile(account: str):
243
  users_db = db.load_data("users.json", default_data={})
 
274
 
275
  cache_key = f"{pwd_data.verify_contact}_reset"
276
  cached = VERIFY_CODES.get(cache_key)
277
+
278
+ # 这里同样加上安全获取策略防崩
279
+ expire_time = cached.get("expires_at", cached.get("expires", 0)) if cached else 0
280
+ if not cached or cached["code"] != pwd_data.code or time.time() > expire_time:
281
  raise HTTPException(status_code=400, detail="验证码不正确或已过期")
282
 
283
  if len(pwd_data.new_password) < 6: raise HTTPException(status_code=400, detail="新密码必须大于等于6个字符")