Files

100 lines
2.5 KiB
Python

"""API 公共函数模块
包含跨 API 模块共享的通用函数和工具。
"""
from fastapi import HTTPException, Request
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from typing import Optional
from app.models.project import Project
from app.logger import get_logger
logger = get_logger(__name__)
async def verify_project_access(
project_id: str,
user_id: Optional[str],
db: AsyncSession
) -> Project:
"""
验证用户是否有权访问指定项目
统一的项目访问验证函数,确保:
1. 用户已登录
2. 项目存在
3. 用户有权访问该项目
Args:
project_id: 项目ID
user_id: 用户ID(从 request.state.user_id 获取)
db: 数据库会话
Returns:
Project: 验证通过后返回项目对象
Raises:
HTTPException:
- 401: 用户未登录
- 404: 项目不存在或用户无权访问
"""
if not user_id:
raise HTTPException(status_code=401, detail="未登录")
result = await db.execute(
select(Project).where(
Project.id == project_id,
Project.user_id == user_id
)
)
project = result.scalar_one_or_none()
if not project:
logger.warning(f"项目访问被拒绝: project_id={project_id}, user_id={user_id}")
raise HTTPException(status_code=404, detail="项目不存在或无权访问")
return project
def get_user_id(request: Request) -> Optional[str]:
"""
从请求中获取用户ID
这是一个便捷函数,用于从 request.state 中提取 user_id。
Args:
request: FastAPI 请求对象
Returns:
用户ID,如果未登录则返回 None
"""
return getattr(request.state, 'user_id', None)
async def verify_project_access_from_request(
project_id: str,
request: Request,
db: AsyncSession
) -> Project:
"""
从请求中验证项目访问权限(便捷函数)
结合 get_user_id 和 verify_project_access,简化调用。
Args:
project_id: 项目ID
request: FastAPI 请求对象
db: 数据库会话
Returns:
Project: 验证通过后返回项目对象
Raises:
HTTPException: 401/404
Usage:
project = await verify_project_access_from_request(project_id, request, db)
"""
user_id = get_user_id(request)
return await verify_project_access(project_id, user_id, db)