baseline: Clover 独立仓库首次基线提交
将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。 当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包), M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
49
backend/app/utils/fernet_utils.py
Normal file
49
backend/app/utils/fernet_utils.py
Normal file
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
app/utils/fernet_utils.py — Fernet 加解密工具(按 Lead 规范路径)
|
||||
FERNET_KEY 走环境变量,绝不进代码库(基石B)。
|
||||
此模块是 app/core/security.py 中 Fernet 功能的独立导出,
|
||||
供 AIE / worker 层直接 import,无需依赖 FastAPI 上下文。
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from cryptography.fernet import Fernet, InvalidToken
|
||||
|
||||
from app.core.config import get_settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_fernet_instance: Fernet | None = None
|
||||
|
||||
|
||||
def _get_fernet() -> Fernet:
|
||||
global _fernet_instance
|
||||
if _fernet_instance is None:
|
||||
settings = get_settings()
|
||||
_fernet_instance = Fernet(settings.FERNET_KEY.encode())
|
||||
return _fernet_instance
|
||||
|
||||
|
||||
def encrypt_key(plain_key: str) -> str:
|
||||
"""
|
||||
加密 API Key,返回密文字符串。
|
||||
调用方绝不打印 plain_key(基石B)。
|
||||
"""
|
||||
return _get_fernet().encrypt(plain_key.encode()).decode()
|
||||
|
||||
|
||||
def decrypt_key(encrypted_key: str) -> str:
|
||||
"""
|
||||
解密 API Key。只在 Celery worker 内部调用。
|
||||
解密结果只活在调用函数的局部变量,不落盘、不打日志。
|
||||
"""
|
||||
try:
|
||||
return _get_fernet().decrypt(encrypted_key.encode()).decode()
|
||||
except InvalidToken:
|
||||
logger.error("Fernet decryption failed: token invalid or key rotated")
|
||||
raise ValueError("API key decryption failed")
|
||||
|
||||
|
||||
def mask_key(plain_key: str) -> str:
|
||||
"""只返回后4位(展示用,不暴露完整 key)。"""
|
||||
return plain_key[-4:] if len(plain_key) >= 4 else "****"
|
||||
Reference in New Issue
Block a user