init: 从 /root/zikai 根目录迁入

把原本散落在 /root/zikai 的 FastAPI 服务整理到 server/ 子目录,
开启独立 git 与 venv。运行时数据(config.yaml / keys / uploads)
按 .gitignore 留在工作目录但不入仓。
This commit is contained in:
zikai
2026-06-23 16:17:31 +00:00
commit 80b96d236f
31 changed files with 1491 additions and 0 deletions

49
app/security.py Normal file
View File

@@ -0,0 +1,49 @@
"""文档接口(/docs、/redoc、/openapi.json的 HTTP Basic Auth 依赖。
凭据明文存放于 config.yaml 的 docs 段;该文件仅在本机以 root 持有,比较使用
secrets.compare_digest 以保证常量时间。
"""
from __future__ import annotations
import secrets
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from .config import get_settings
_security = HTTPBasic(auto_error=False)
def require_docs_auth(
credentials: HTTPBasicCredentials | None = Depends(_security),
) -> str:
cfg = get_settings().docs
realm = f'Basic realm="{cfg.realm}"'
if not cfg.enabled:
raise HTTPException(status.HTTP_404_NOT_FOUND, "docs 已禁用")
if not cfg.password:
raise HTTPException(
status.HTTP_503_SERVICE_UNAVAILABLE,
"docs 鉴权未配置:请在 config.yaml 的 docs.password 填密码后重启",
)
if credentials is None:
raise HTTPException(
status.HTTP_401_UNAUTHORIZED,
"需要认证",
headers={"WWW-Authenticate": realm},
)
user_ok = secrets.compare_digest(credentials.username, cfg.username)
pw_ok = secrets.compare_digest(credentials.password, cfg.password)
if not (user_ok and pw_ok):
raise HTTPException(
status.HTTP_401_UNAUTHORIZED,
"用户名或密码错误",
headers={"WWW-Authenticate": realm},
)
return credentials.username