from fastapi import APIRouter, Depends, HTTPException, status, Request from sqlalchemy.orm import Session from datetime import datetime, timedelta from app.core.database import get_db from app.core.security import verify_token from app.core.token_blacklist import token_blacklist from app.services.user_service import UserService from app.schemas.auth import ( UserRegister, UserLogin, UserResponse, LoginResponse, TokenResponse, TokenRefresh, ApiResponse ) from app.dependencies.auth import get_current_user_response from app.models.user import User from app.exceptions.auth import UsernameAlreadyExistsException router = APIRouter() @router.post("/register", status_code=status.HTTP_201_CREATED) async def register(request: Request, user_data: UserRegister, db: Session = Depends(get_db)): """用户注册""" timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"[{timestamp}] INFO: === 注册接口 ===") print(f"[{timestamp}] INFO: 用户名: {user_data.username}") print(f"[{timestamp}] INFO: 邮箱: {user_data.email}") print(f"[{timestamp}] INFO: 密码长度: {len(user_data.password)}字符") print(f"[{timestamp}] INFO: 确认密码长度: {len(user_data.confirm_password)}字符") print(f"[{timestamp}] DEBUG: Starting registration process...") try: user_service = UserService(db) # 创建用户 print("[DEBUG] Creating user...") user = user_service.create_user(user_data) print(f"[DEBUG] User created successfully with ID: {user.id}") # 创建令牌 print("[DEBUG] Creating tokens...") tokens = user_service.create_user_tokens(user) print("[DEBUG] Tokens created successfully") # 转换为响应格式 print("[DEBUG] Converting to response format...") user_response = user_service.to_user_response(user) print("[DEBUG] Response conversion successful") response_data = { "user": user_response.dict(), "tokens": tokens } print("[DEBUG] Response data created successfully") return ApiResponse( success=True, message="注册成功", data=response_data ) except UsernameAlreadyExistsException as e: print(f"[DEBUG] UsernameAlreadyExistsException caught: {e}") raise e except HTTPException as e: print(f"[DEBUG] HTTPException caught: {e}") raise e except Exception as e: # 打印异常信息以便调试 import traceback print(f"[ERROR] Unexpected error in register: {e}") print(f"[ERROR] Exception type: {type(e)}") traceback.print_exc() raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail={ "code": "REGISTRATION_FAILED", "message": f"注册过程中发生错误: {str(e)}" } ) @router.post("/login", response_model=ApiResponse) async def login(request: Request, login_data: UserLogin, db: Session = Depends(get_db)): """用户登录""" timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"[{timestamp}] INFO: === 登录接口 ===") print(f"[{timestamp}] INFO: 用户名: {login_data.username}") print(f"[{timestamp}] INFO: 密码长度: {len(login_data.password)}字符") print(f"[{timestamp}] DEBUG: Starting authentication process...") try: user_service = UserService(db) # 验证用户 user = user_service.authenticate_user(login_data) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail={ "code": "INVALID_CREDENTIALS", "message": "用户名或密码错误" } ) # 创建令牌 tokens = user_service.create_user_tokens(user) # 转换为响应格式 user_response = user_service.to_user_response(user) return ApiResponse( success=True, message="登录成功", data={ "user": user_response.dict(), "tokens": tokens } ) except HTTPException as e: raise e except Exception as e: print("用户登录的异常:",e) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail={ "code": "LOGIN_FAILED", "message": "登录过程中发生错误" } ) @router.post("/refresh", response_model=ApiResponse) async def refresh_token(token_data: TokenRefresh, db: Session = Depends(get_db)): """刷新访问令牌""" try: # 验证刷新令牌 payload = verify_token(token_data.refresh_token, "refresh") if not payload: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail={ "code": "INVALID_REFRESH_TOKEN", "message": "无效的刷新令牌" } ) # 获取用户ID user_id = int(payload.get("sub")) user_service = UserService(db) user = user_service.get_user_by_id(user_id) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail={ "code": "USER_NOT_FOUND", "message": "用户不存在" } ) # 创建新的访问令牌 tokens = user_service.create_user_tokens(user) return ApiResponse( success=True, message="令牌刷新成功", data={ "tokens": tokens } ) except HTTPException as e: raise e except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail={ "code": "TOKEN_REFRESH_FAILED", "message": "令牌刷新过程中发生错误" } ) @router.get("/me", response_model=ApiResponse) async def get_current_user_info(current_user: UserResponse = Depends(get_current_user_response)): """获取当前用户信息""" return ApiResponse( success=True, message="获取用户信息成功", data={ "user": current_user.dict() } ) @router.post("/logout", response_model=ApiResponse) async def logout( request: Request, current_user: UserResponse = Depends(get_current_user_response) ): """用户登出""" try: # 从请求头中获取Authorization令牌 authorization = request.headers.get("Authorization") if authorization and authorization.startswith("Bearer "): token = authorization.split(" ")[1] # 将令牌加入黑名单 token_blacklist.add_token(token) return ApiResponse( success=True, message="登出成功", data={} ) except Exception as e: # 即使添加令牌到黑名单失败,也返回成功,因为登出操作主要目的是让客户端删除令牌 return ApiResponse( success=True, message="登出成功", data={} )