Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions backend/.env.example
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
# 数据库配置
# ==================== 安全配置(必须设置) ====================
# JWT密钥:用于令牌签名,生产环境必须使用强密钥
# 建议使用: openssl rand -hex 32 生成
SECRET_KEY=your_generated_secret_key_here
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

# ==================== 数据库配置(必须设置) ====================
POSTGRES_SERVER=localhost
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_password
# 数据库密码:必须设置强密码,不能使用默认值
POSTGRES_PASSWORD=your_secure_database_password
POSTGRES_DB=GradNote
POSTGRES_PORT=5432

# Redis配置(可选)
# ==================== 初始管理员配置(必须设置) ====================
# 初始管理员账户配置,首次启动时创建
FIRST_SUPERUSER=admin
# 管理员密码:必须设置强密码,不能使用默认值
FIRST_SUPERUSER_PASSWORD=your_secure_admin_password
FIRST_SUPERUSER_EMAIL=admin@example.com

# ==================== Redis配置(可选) ====================
REDIS_HOST=localhost
REDIS_PORT=6379

# 安全配置
SECRET_KEY=your_generated_secret_key_here
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30

# LANGFUSE配置
# ==================== LLM服务配置(可选) ====================
LANGFUSE_PUBLIC_KEY='your_langfuse_public_key'
LANGFUSE_SECRET_KEY='your_langfuse_secret_key'

Expand Down
41 changes: 37 additions & 4 deletions backend/app/core/config.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,51 @@
import os
import sys
from typing import Optional, Dict, Any, List
from pydantic import PostgresDsn, field_validator, ValidationInfo
from pydantic_settings import BaseSettings

def validate_required_env_vars() -> None:
"""
验证必需的环境变量是否存在
如果缺少关键的环境变量,应用将无法启动
"""
required_vars = {
"SECRET_KEY": "JWT密钥,用于令牌签名",
"POSTGRES_PASSWORD": "PostgreSQL数据库密码",
"FIRST_SUPERUSER": "初始管理员用户名",
"FIRST_SUPERUSER_PASSWORD": "初始管理员密码",
"FIRST_SUPERUSER_EMAIL": "初始管理员邮箱"
}

missing_vars = []
for var_name, description in required_vars.items():
if not os.getenv(var_name):
missing_vars.append(f" - {var_name}: {description}")

if missing_vars:
error_msg = (
"❌ 安全错误:缺少必需的环境变量\n\n"
"以下环境变量是必需的,但未设置:\n"
+ "\n".join(missing_vars) + "\n\n"
"请设置这些环境变量后重新启动应用。\n"
"参考 .env.example 文件了解如何配置。\n"
)
print(error_msg, file=sys.stderr)
sys.exit(1)


class Settings(BaseSettings):
API_V1_STR: str = "/api/v1"

# JWT相关配置
SECRET_KEY: str = os.getenv("SECRET_KEY", "your-secret-key-for-development")
SECRET_KEY: str = os.getenv("SECRET_KEY", "")
ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 # 24小时

# 数据库配置
POSTGRES_SERVER: str = os.getenv("POSTGRES_SERVER", "localhost")
POSTGRES_USER: str = os.getenv("POSTGRES_USER", "postgres")
POSTGRES_PASSWORD: str = os.getenv("POSTGRES_PASSWORD", "123456")
POSTGRES_PASSWORD: str = os.getenv("POSTGRES_PASSWORD", "")
POSTGRES_DB: str = os.getenv("POSTGRES_DB", "GradNote")
POSTGRES_PORT: str = os.getenv("POSTGRES_PORT", "5432")
DATABASE_URI: Optional[str] = None
Expand All @@ -31,8 +62,7 @@ def assemble_db_connection(cls, v: Optional[str], info: ValidationInfo) -> Any:
required_keys = ["POSTGRES_USER", "POSTGRES_PASSWORD", "POSTGRES_SERVER", "POSTGRES_PORT", "POSTGRES_DB"]
for key in required_keys:
if key not in data or not data.get(key):
# 如果配置不完整,返回一个默认的本地开发URI
return "postgresql://postgres:123456@localhost:5432/GradNote"
raise ValueError(f"数据库配置不完整:缺少 {key} 环境变量")

# 使用字符串拼接而不是PostgresDsn.build,避免编码问题
return f"postgresql://{data.get('POSTGRES_USER')}:{data.get('POSTGRES_PASSWORD')}@{data.get('POSTGRES_SERVER')}:{data.get('POSTGRES_PORT')}/{data.get('POSTGRES_DB')}"
Expand Down Expand Up @@ -80,4 +110,7 @@ class Config:
env_file = ".env"
extra = "ignore" # 允许额外的字段,忽略不在模型中定义的字段

# 在创建settings实例前验证必需的环境变量
validate_required_env_vars()

settings = Settings()
14 changes: 10 additions & 4 deletions backend/app/db/init_db.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from sqlalchemy.orm import Session
import os
from app.core.config import settings
from app.services.user import create_user, get_user_by_username
from app.api.schemas.user import UserCreate
Expand All @@ -9,10 +10,10 @@
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 初始测试用户
FIRST_SUPERUSER = "admin"
FIRST_SUPERUSER_PASSWORD = "admin"
FIRST_SUPERUSER_EMAIL = "admin@example.com"
# 从环境变量获取初始用户配置
FIRST_SUPERUSER = os.getenv("FIRST_SUPERUSER", "")
FIRST_SUPERUSER_PASSWORD = os.getenv("FIRST_SUPERUSER_PASSWORD", "")
FIRST_SUPERUSER_EMAIL = os.getenv("FIRST_SUPERUSER_EMAIL", "")

# 初始知识点数据 - 简化并使用ASCII字符
INITIAL_KNOWLEDGE_POINTS = [
Expand Down Expand Up @@ -57,6 +58,11 @@ def init_db(db: Session) -> None:
"""
初始化数据库
"""
# 检查初始用户配置
if not all([FIRST_SUPERUSER, FIRST_SUPERUSER_PASSWORD, FIRST_SUPERUSER_EMAIL]):
logger.error("初始管理员用户配置不完整,请设置 FIRST_SUPERUSER、FIRST_SUPERUSER_PASSWORD 和 FIRST_SUPERUSER_EMAIL 环境变量")
return

# 创建初始管理员用户
user = get_user_by_username(db, FIRST_SUPERUSER)
if not user:
Expand Down