You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
buffer_platform/buffer_platform_v2/app/api/auth.py

130 lines
3.6 KiB

"""认证 API 路由 - 登录/登出/令牌验证/用户信息"""
import logging
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from sqlalchemy.ext.asyncio import AsyncSession
from app import auth_service
from app.database import get_db
from app.schemas import LoginRequest, LoginResponse
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/auth", tags=["用户认证"])
security = HTTPBearer()
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: AsyncSession = Depends(get_db),
) -> object:
"""依赖注入 - 获取当前已登录用户。"""
user = await auth_service.verify_token(credentials.credentials, db)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="请先登录",
)
return user
async def require_admin(
current_user=Depends(get_current_user),
) -> object:
"""依赖注入 - 验证管理员权限。"""
if current_user.role != "admin":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="需要管理员权限",
)
return current_user
@router.post("/login", response_model=LoginResponse)
async def login(
request: LoginRequest,
db: AsyncSession = Depends(get_db),
):
"""用户登录。"""
user = await auth_service.authenticate_user(db, request.username, request.password)
if not user:
return LoginResponse(success=False, message="用户名或密码错误")
token = await auth_service.create_token(user.id, db)
await auth_service.update_last_login(user, db)
return LoginResponse(
success=True,
token=token,
user={
"id": user.id,
"username": user.username,
"role": user.role,
"email": user.email,
},
message="登录成功",
)
@router.post("/logout")
async def logout(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: AsyncSession = Depends(get_db),
):
"""用户登出。"""
await auth_service.invalidate_session(credentials.credentials, db)
return {"success": True, "message": "已登出"}
@router.get("/verify")
async def verify_token(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: AsyncSession = Depends(get_db),
):
"""验证用户令牌。"""
user = await auth_service.verify_token(credentials.credentials, db)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="无效的会话令牌",
)
return {
"success": True,
"user": {
"id": user.id,
"username": user.username,
"role": user.role,
"email": user.email,
"last_login": user.last_login.isoformat() if user.last_login else None,
},
}
@router.get("/me")
async def get_me(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: AsyncSession = Depends(get_db),
):
"""获取当前用户信息。"""
user = await auth_service.verify_token(credentials.credentials, db)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="无效的会话令牌",
)
return {
"id": user.id,
"username": user.username,
"role": user.role,
"email": user.email,
"is_active": user.is_active,
"created_at": user.created_at.isoformat(),
"last_login": user.last_login.isoformat() if user.last_login else None,
}