feat: add email-based authentication
This commit is contained in:
@@ -4,6 +4,8 @@ import os
|
||||
import secrets
|
||||
from pathlib import Path
|
||||
|
||||
from dotenv import dotenv_values
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
DATA_DIR = BASE_DIR / "data"
|
||||
STATIC_DIR = BASE_DIR / "static"
|
||||
@@ -11,6 +13,20 @@ UPLOAD_DIR = BASE_DIR / "uploads"
|
||||
IMAGE_DIR = STATIC_DIR / "images"
|
||||
|
||||
|
||||
def load_local_environment() -> None:
|
||||
"""加载本地配置,优先级为系统环境变量 > .env.local > .env。"""
|
||||
values = dotenv_values(BASE_DIR / ".env")
|
||||
overrides = dotenv_values(BASE_DIR / ".env.local")
|
||||
# .env.local 中的空值表示“沿用 .env”,避免本机模板清空密钥。
|
||||
values.update({key: value for key, value in overrides.items() if value})
|
||||
for key, value in values.items():
|
||||
if value:
|
||||
os.environ.setdefault(key, value)
|
||||
|
||||
|
||||
load_local_environment()
|
||||
|
||||
|
||||
def env_int(name: str, default: int) -> int:
|
||||
try:
|
||||
return int(os.environ.get(name, str(default)))
|
||||
@@ -42,6 +58,7 @@ class Config:
|
||||
MAX_CONTENT_LENGTH = env_int("MAX_UPLOAD_BYTES", 16 * 1024 * 1024)
|
||||
SESSION_COOKIE_HTTPONLY = True
|
||||
SESSION_COOKIE_SAMESITE = "Lax"
|
||||
SESSION_COOKIE_SECURE = env_bool("SESSION_COOKIE_SECURE", APP_ENV == "production")
|
||||
FUSION_MODEL_CORE_DIR = os.environ.get(
|
||||
"FUSION_MODEL_CORE_DIR",
|
||||
str(BASE_DIR / "model_core"),
|
||||
@@ -49,8 +66,15 @@ class Config:
|
||||
ALLOW_REGISTRATION = env_bool("ALLOW_REGISTRATION", False)
|
||||
ADMIN_USERNAME = os.environ.get("ADMIN_USERNAME", "admin").strip() or "admin"
|
||||
ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD")
|
||||
ADMIN_EMAIL = os.environ.get("ADMIN_EMAIL", "").strip().lower()
|
||||
APP_TIMEZONE = os.environ.get("APP_TIMEZONE", "Asia/Shanghai").strip() or "Asia/Shanghai"
|
||||
PASSWORD_RESET_TOKEN_MINUTES = env_int("PASSWORD_RESET_TOKEN_MINUTES", 30)
|
||||
RESEND_API_KEY = os.environ.get("RESEND_API_KEY", "").strip()
|
||||
RESEND_FROM_EMAIL = os.environ.get("RESEND_FROM_EMAIL", "").strip()
|
||||
EMAIL_CODE_MINUTES = env_int("EMAIL_CODE_MINUTES", 10)
|
||||
EMAIL_CODE_RESEND_SECONDS = env_int("EMAIL_CODE_RESEND_SECONDS", 60)
|
||||
EMAIL_CODE_MAX_ATTEMPTS = env_int("EMAIL_CODE_MAX_ATTEMPTS", 5)
|
||||
TRUSTED_DEVICE_DAYS = env_int("TRUSTED_DEVICE_DAYS", 30)
|
||||
|
||||
|
||||
def ensure_dirs() -> None:
|
||||
|
||||
Reference in New Issue
Block a user