""" 密码重置管理接口 """ from fastapi import APIRouter, Depends, HTTPException from fastapi.responses import JSONResponse from redis.asyncio import Redis from app.dependencies.database import get_redis from app.service.password_reset_service import password_reset_service from app.log import logger router = APIRouter(prefix="/admin/password-reset", tags=["密码重置管理"]) @router.get( "/status/{email}", name="查询重置状态", description="查询指定邮箱的密码重置状态" ) async def get_password_reset_status( email: str, redis: Redis = Depends(get_redis), ): """查询密码重置状态""" try: info = await password_reset_service.get_reset_code_info(email, redis) return JSONResponse( status_code=200, content={ "success": True, "data": info } ) except Exception as e: logger.error(f"[Admin] Failed to get password reset status for {email}: {e}") return JSONResponse( status_code=500, content={ "success": False, "error": "获取状态失败" } ) @router.delete( "/cleanup/{email}", name="清理重置数据", description="强制清理指定邮箱的密码重置数据" ) async def force_cleanup_reset( email: str, redis: Redis = Depends(get_redis), ): """强制清理密码重置数据""" try: success = await password_reset_service.force_cleanup_user_reset(email, redis) if success: return JSONResponse( status_code=200, content={ "success": True, "message": f"已清理邮箱 {email} 的重置数据" } ) else: return JSONResponse( status_code=500, content={ "success": False, "error": "清理失败" } ) except Exception as e: logger.error(f"[Admin] Failed to cleanup password reset for {email}: {e}") return JSONResponse( status_code=500, content={ "success": False, "error": "清理操作失败" } ) @router.post( "/cleanup/expired", name="清理过期验证码", description="清理所有过期的密码重置验证码" ) async def cleanup_expired_codes( redis: Redis = Depends(get_redis), ): """清理过期验证码""" try: count = await password_reset_service.cleanup_expired_codes(redis) return JSONResponse( status_code=200, content={ "success": True, "message": f"已清理 {count} 个过期的验证码", "cleaned_count": count } ) except Exception as e: logger.error(f"[Admin] Failed to cleanup expired codes: {e}") return JSONResponse( status_code=500, content={ "success": False, "error": "清理操作失败" } ) @router.get( "/stats", name="重置统计", description="获取密码重置的统计信息" ) async def get_reset_statistics( redis: Redis = Depends(get_redis), ): """获取重置统计信息""" try: # 获取所有重置相关的键 reset_keys = await redis.keys("password_reset:code:*") rate_limit_keys = await redis.keys("password_reset:rate_limit:*") active_resets = 0 used_resets = 0 active_rate_limits = 0 # 统计活跃重置 for key in reset_keys: data_str = await redis.get(key) if data_str: try: import json data = json.loads(data_str) if data.get("used", False): used_resets += 1 else: active_resets += 1 except: pass # 统计频率限制 for key in rate_limit_keys: ttl = await redis.ttl(key) if ttl > 0: active_rate_limits += 1 stats = { "total_reset_codes": len(reset_keys), "active_resets": active_resets, "used_resets": used_resets, "active_rate_limits": active_rate_limits, "total_rate_limit_keys": len(rate_limit_keys) } return JSONResponse( status_code=200, content={ "success": True, "data": stats } ) except Exception as e: logger.error(f"[Admin] Failed to get reset statistics: {e}") return JSONResponse( status_code=500, content={ "success": False, "error": "获取统计信息失败" } )