82 lines
2.5 KiB
Python
82 lines
2.5 KiB
Python
"""读取与更新 .env 配置"""
|
|
import os
|
|
import re
|
|
from pathlib import Path
|
|
|
|
from cryptography.fernet import Fernet
|
|
from dotenv import load_dotenv, set_key
|
|
from werkzeug.security import check_password_hash, generate_password_hash
|
|
|
|
BASE_DIR = Path(__file__).resolve().parent
|
|
ENV_FILE = BASE_DIR / ".env"
|
|
|
|
|
|
def _valid_fernet_key(value: str) -> bool:
|
|
if not value or "请" in value or len(value) < 40:
|
|
return False
|
|
try:
|
|
Fernet(value.encode())
|
|
return True
|
|
except (ValueError, Exception):
|
|
return False
|
|
|
|
|
|
def ensure_env():
|
|
if not ENV_FILE.exists():
|
|
example = BASE_DIR / ".env.example"
|
|
if example.exists():
|
|
ENV_FILE.write_text(example.read_text(encoding="utf-8"), encoding="utf-8")
|
|
else:
|
|
ENV_FILE.write_text("", encoding="utf-8")
|
|
load_dotenv(ENV_FILE, override=True)
|
|
changed = False
|
|
if not os.getenv("SECRET_KEY") or "请" in os.getenv("SECRET_KEY", ""):
|
|
set_key(str(ENV_FILE), "SECRET_KEY", os.urandom(32).hex())
|
|
changed = True
|
|
if not _valid_fernet_key(os.getenv("DATA_ENCRYPTION_KEY", "")):
|
|
set_key(str(ENV_FILE), "DATA_ENCRYPTION_KEY", Fernet.generate_key().decode())
|
|
changed = True
|
|
if not os.getenv("AUTH_USERNAME"):
|
|
set_key(str(ENV_FILE), "AUTH_USERNAME", "admin")
|
|
changed = True
|
|
if not os.getenv("AUTH_PASSWORD"):
|
|
set_key(str(ENV_FILE), "AUTH_PASSWORD", generate_password_hash("admin123"))
|
|
changed = True
|
|
if changed:
|
|
load_dotenv(ENV_FILE, override=True)
|
|
|
|
|
|
def reload_env():
|
|
load_dotenv(ENV_FILE, override=True)
|
|
|
|
|
|
def get_secret_key():
|
|
return os.getenv("SECRET_KEY", "dev-insecure-key")
|
|
|
|
|
|
def get_encryption_key():
|
|
raw = os.getenv("DATA_ENCRYPTION_KEY", "")
|
|
if not raw:
|
|
raise ValueError("缺少 DATA_ENCRYPTION_KEY,请检查 .env")
|
|
return raw.encode() if isinstance(raw, str) else raw
|
|
|
|
|
|
def get_auth_username():
|
|
return os.getenv("AUTH_USERNAME", "admin")
|
|
|
|
|
|
def verify_password(plain: str) -> bool:
|
|
stored = os.getenv("AUTH_PASSWORD", "")
|
|
if not stored:
|
|
return False
|
|
if stored.startswith("pbkdf2:") or stored.startswith("scrypt:"):
|
|
return check_password_hash(stored, plain)
|
|
return stored == plain
|
|
|
|
|
|
def update_auth(username: str, password: str):
|
|
ensure_env()
|
|
set_key(str(ENV_FILE), "AUTH_USERNAME", username)
|
|
set_key(str(ENV_FILE), "AUTH_PASSWORD", generate_password_hash(password))
|
|
reload_env()
|