AI 配置改为按用户独立存储
每个用户 AI 配置存 data/user_data/ai_settings/{username}.json,
读配置时用户级优先,无则回退到全局 secrets.json。
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -94,3 +94,53 @@ def mask(key: str, prefix: int = 4, suffix: int = 4) -> str:
|
||||
if len(key) <= prefix + suffix:
|
||||
return "•" * len(key)
|
||||
return f"{key[:prefix]}{'•' * 6}{key[-suffix:]}"
|
||||
|
||||
|
||||
# ================================================================
|
||||
# 按用户 AI 配置 (data/user_data/ai_settings/{username}.json)
|
||||
# ================================================================
|
||||
|
||||
def _ai_config_path(username: str) -> Path:
|
||||
from app.config import settings
|
||||
p = settings.data_dir / "user_data" / "ai_settings" / f"{username}.json"
|
||||
p.parent.mkdir(parents=True, exist_ok=True)
|
||||
return p
|
||||
|
||||
|
||||
def load_ai_config(username: str) -> dict:
|
||||
"""加载指定用户的 AI 配置。用户不存在时返回空 dict。"""
|
||||
p = _ai_config_path(username)
|
||||
if p.exists():
|
||||
try:
|
||||
return json.loads(p.read_text(encoding="utf-8"))
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.warning("ai_settings/%s.json malformed: %s", username, e)
|
||||
return {}
|
||||
|
||||
|
||||
def save_ai_config(username: str, updates: dict) -> dict:
|
||||
"""合并写入指定用户的 AI 配置。返回新内容。"""
|
||||
current = load_ai_config(username)
|
||||
current.update({k: v for k, v in updates.items() if v is not None})
|
||||
p = _ai_config_path(username)
|
||||
p.write_text(json.dumps(current, indent=2, ensure_ascii=False), encoding="utf-8")
|
||||
try:
|
||||
os.chmod(p, 0o600)
|
||||
except OSError:
|
||||
pass
|
||||
return current
|
||||
|
||||
|
||||
def clear_ai_config(username: str, *keys: str) -> dict:
|
||||
"""清掉指定用户的 AI 配置字段。不传 keys 则删除整个文件。"""
|
||||
p = _ai_config_path(username)
|
||||
if not p.exists():
|
||||
return {}
|
||||
if not keys:
|
||||
p.unlink()
|
||||
return {}
|
||||
current = load_ai_config(username)
|
||||
for k in keys:
|
||||
current.pop(k, None)
|
||||
p.write_text(json.dumps(current, indent=2, ensure_ascii=False), encoding="utf-8")
|
||||
return current
|
||||
|
||||
Reference in New Issue
Block a user