62 lines
2.0 KiB
Python
62 lines
2.0 KiB
Python
|
|
"""Internal evaluation API:共享密钥鉴权,不依赖终端用户 JWT。"""
|
|||
|
|
|
|||
|
|
from typing import Annotated
|
|||
|
|
|
|||
|
|
from fastapi import Depends, Header, HTTPException, status
|
|||
|
|
|
|||
|
|
from app.core.config import settings
|
|||
|
|
from app.core.logging import get_logger
|
|||
|
|
|
|||
|
|
logger = get_logger(__name__)
|
|||
|
|
|
|||
|
|
INTERNAL_HEADER = "X-Internal-Eval-Key"
|
|||
|
|
|
|||
|
|
|
|||
|
|
class InternalEvalPrincipal:
|
|||
|
|
"""已通过内部密钥校验的调用方(占位,便于后续扩展多密钥/审计)。"""
|
|||
|
|
|
|||
|
|
def __init__(self, *, key_id: str = "default") -> None:
|
|||
|
|
self.key_id = key_id
|
|||
|
|
|
|||
|
|
|
|||
|
|
def require_internal_eval_enabled() -> None:
|
|||
|
|
if not (settings.internal_eval_api_key or "").strip():
|
|||
|
|
logger.warning("internal_eval_api_key 未配置,内部评测 API 拒绝访问")
|
|||
|
|
raise HTTPException(
|
|||
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|||
|
|
detail="内部评测服务未启用(缺少 INTERNAL_EVAL_API_KEY)",
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def verify_internal_eval_key(
|
|||
|
|
*,
|
|||
|
|
header_value: str | None = None,
|
|||
|
|
query_value: str | None = None,
|
|||
|
|
) -> InternalEvalPrincipal:
|
|||
|
|
"""Header 或 query(供 EventSource 等无法带头场景)。"""
|
|||
|
|
require_internal_eval_enabled()
|
|||
|
|
expected = (settings.internal_eval_api_key or "").strip()
|
|||
|
|
if not expected:
|
|||
|
|
raise HTTPException(
|
|||
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|||
|
|
detail="内部评测服务未启用",
|
|||
|
|
)
|
|||
|
|
provided = (header_value or query_value or "").strip()
|
|||
|
|
if not provided or provided != expected:
|
|||
|
|
raise HTTPException(
|
|||
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|||
|
|
detail="无效的内部评测密钥",
|
|||
|
|
)
|
|||
|
|
return InternalEvalPrincipal()
|
|||
|
|
|
|||
|
|
|
|||
|
|
async def get_internal_eval_principal(
|
|||
|
|
x_internal_eval_key: Annotated[str | None, Header(alias=INTERNAL_HEADER)] = None,
|
|||
|
|
) -> InternalEvalPrincipal:
|
|||
|
|
return verify_internal_eval_key(header_value=x_internal_eval_key)
|
|||
|
|
|
|||
|
|
|
|||
|
|
InternalEvalAuth = Annotated[
|
|||
|
|
InternalEvalPrincipal, Depends(get_internal_eval_principal)
|
|||
|
|
]
|