初次提交
This commit is contained in:
217
backend/app/api/v1/endpoints/auth.py
Normal file
217
backend/app/api/v1/endpoints/auth.py
Normal file
@@ -0,0 +1,217 @@
|
||||
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={}
|
||||
)
|
||||
Reference in New Issue
Block a user