diff --git a/backend/app/config.py b/backend/app/config.py new file mode 100644 index 0000000..c9faa9a --- /dev/null +++ b/backend/app/config.py @@ -0,0 +1,43 @@ +import os +from pathlib import Path +from typing import Literal +from pydantic_settings import BaseSettings, SettingsConfigDict + + +class Settings(BaseSettings): + """应用配置,从环境变量加载.""" + + # 安全配置 + encrypt_key: str # AES-256 密钥 (base64) + api_token: str # API 认证 Token + + # 路径配置 + data_dir: Path = Path('./data') + + # 服务器配置 + host: str = '0.0.0.0' + port: int = 8000 + + model_config = SettingsConfigDict( + env_prefix='GM_', + env_file='.env', + env_file_encoding='utf-8', + ) + + @property + def db_path(self) -> Path: + """SQLite 数据库路径.""" + return self.data_dir / 'git_manager.db' + + @property + def ssh_keys_dir(self) -> Path: + """SSH 密钥存储目录.""" + return self.data_dir / 'ssh_keys' + + @property + def repos_dir(self) -> Path: + """仓库镜像存储目录.""" + return self.data_dir / 'repos' + + +settings = Settings() diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py index e69de29..e0974f3 100644 --- a/backend/app/models/__init__.py +++ b/backend/app/models/__init__.py @@ -0,0 +1,11 @@ +"""ORM Models. + +NOTE: This module is a placeholder until Task 2.1. +The Base class is needed by conftest.py for database fixtures. +""" + +from sqlalchemy.orm import DeclarativeBase + +class Base(DeclarativeBase): + """Base class for all ORM models.""" + pass diff --git a/backend/tests/test_config.py b/backend/tests/test_config.py new file mode 100644 index 0000000..e140641 --- /dev/null +++ b/backend/tests/test_config.py @@ -0,0 +1,32 @@ +import os +import pytest +import base64 +from pathlib import Path + +def test_config_defaults(test_env_vars, monkeypatch): + """测试配置默认值.""" + # Clear GM_DATA_DIR to test default value + monkeypatch.delenv("GM_DATA_DIR", raising=False) + + # Reload config to pick up the change + from app.config import Settings + settings = Settings() + + assert settings.data_dir == Path('./data') + assert settings.host == '0.0.0.0' + assert settings.port == 8000 + +def test_config_from_env(monkeypatch): + """测试从环境变量读取配置.""" + # Set required security fields + monkeypatch.setenv("GM_ENCRYPT_KEY", base64.b64encode(b'test-key-32-bytes-long-1234567890').decode()) + monkeypatch.setenv("GM_API_TOKEN", "test-token") + monkeypatch.setenv("GM_DATA_DIR", "/custom/data") + monkeypatch.setenv("GM_PORT", "9000") + + # 重新加载配置 + from app.config import Settings + settings = Settings() + + assert settings.data_dir == Path('/custom/data') + assert settings.port == 9000