feat: 新增 API Token 和离线 API 文档

This commit is contained in:
2026-05-23 03:00:34 +08:00
parent 211f87e65e
commit 4784ed36ca
14 changed files with 1160 additions and 14 deletions
+64
View File
@@ -4,8 +4,11 @@ import hashlib
import hmac
import json
import time
from dataclasses import dataclass
from typing import Optional
from starlette.requests import Request
from app.config import BASE_DIR
@@ -15,6 +18,12 @@ DEFAULT_USERNAME = "root"
DEFAULT_PASSWORD = "Capacity"
@dataclass(frozen=True)
class AuthContext:
kind: str
payload: dict
def _ensure_auth_ini() -> None:
if AUTH_INI_PATH.exists():
return
@@ -68,6 +77,61 @@ def verify_jwt_token(token: str) -> Optional[dict]:
return None
def extract_login_token(request: Request) -> str | None:
auth_header = request.headers.get("Authorization", "").strip()
if auth_header.startswith("Bearer "):
token = auth_header.split(" ", 1)[1].strip()
if token:
return token
cookie_token = request.cookies.get("token", "").strip()
return cookie_token or None
def extract_access_token(request: Request) -> str | None:
auth_header = request.headers.get("Authorization", "").strip()
if auth_header.startswith("Bearer "):
token = auth_header.split(" ", 1)[1].strip()
if token:
return token
api_token = request.headers.get("X-API-Token", "").strip()
if api_token:
return api_token
cookie_token = request.cookies.get("token", "").strip()
return cookie_token or None
def resolve_login_context(request: Request) -> AuthContext | None:
token = extract_login_token(request)
if not token:
return None
payload = verify_jwt_token(token)
if not payload:
return None
return AuthContext(kind="jwt", payload=payload)
def resolve_access_context(request: Request) -> AuthContext | None:
token = extract_access_token(request)
if not token:
return None
payload = verify_jwt_token(token)
if payload:
return AuthContext(kind="jwt", payload=payload)
from app.services.api_tokens import verify_api_token
api_payload = verify_api_token(token)
if api_payload:
return AuthContext(kind="api_token", payload=api_payload)
return None
def _encode_json(data: dict) -> str:
raw = json.dumps(data, separators=(",", ":")).encode()
return base64.urlsafe_b64encode(raw).decode().rstrip("=")