from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.api.deps import get_current_user from app.database import get_db from app.models.user import User from app.schemas.auth import ( ChangePasswordRequest, ForgotPasswordRequest, ResetPasswordRequest, TokenResponse, UpdateProfileRequest, UserLogin, UserRegister, UserResponse, VerifyEmailRequest, ) from app.services.auth import ( authenticate_user, change_password as change_password_service, create_access_token, register_user, reset_password as reset_password_service, send_reset_link, send_verification_code, update_profile as update_profile_service, verify_email as verify_email_service, ) router = APIRouter() @router.post("/register", response_model=UserResponse, status_code=status.HTTP_201_CREATED) async def register(user_data: UserRegister, db: AsyncSession = Depends(get_db)): try: user = await register_user(db, user_data) except ValueError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e) if str(e) else "邮箱已被注册") return user @router.post("/login", response_model=TokenResponse) async def login(user_data: UserLogin, db: AsyncSession = Depends(get_db)): user = await authenticate_user(db, user_data.email, user_data.password) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="邮箱或密码错误", headers={"WWW-Authenticate": "Bearer"}, ) access_token = create_access_token(data={"sub": str(user.id)}) return { "access_token": access_token, "token_type": "bearer", "user": user, } @router.get("/me", response_model=UserResponse) async def read_current_user(current_user: User = Depends(get_current_user)): return current_user @router.post("/forgot-password") async def forgot_password(req: ForgotPasswordRequest, db: AsyncSession = Depends(get_db)): await send_reset_link(db, req.email) return {"message": "如果该邮箱已注册,重置链接已发送"} @router.post("/reset-password") async def reset_password(req: ResetPasswordRequest, db: AsyncSession = Depends(get_db)): success = await reset_password_service(db, req.token, req.new_password) if not success: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="无效的令牌或令牌已过期") return {"message": "密码重置成功"} @router.post("/verify-email") async def verify_email(req: VerifyEmailRequest, db: AsyncSession = Depends(get_db)): success = await verify_email_service(db, req.email, req.code) if not success: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="验证码无效或已过期") return {"message": "邮箱验证成功"} @router.post("/resend-verification") async def resend_verification(req: ForgotPasswordRequest, db: AsyncSession = Depends(get_db)): await send_verification_code(db, req.email) return {"message": "验证码已重新发送"} @router.put("/change-password") async def change_password( req: ChangePasswordRequest, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): success = await change_password_service(db, user.id, req.old_password, req.new_password) if not success: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="旧密码错误") return {"message": "密码修改成功"} @router.put("/profile", response_model=UserResponse) async def update_profile( req: UpdateProfileRequest, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): updated_user = await update_profile_service(db, user.id, req) if not updated_user: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="用户不存在") return updated_user