-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.py
More file actions
102 lines (83 loc) · 2.97 KB
/
config.py
File metadata and controls
102 lines (83 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
"""METTLE configuration management."""
from functools import lru_cache
from pydantic import Field, model_validator
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
# Environment
environment: str = Field(default="development", description="Runtime environment")
debug: bool = Field(default=False, description="Enable debug mode")
# API
api_title: str = Field(default="METTLE", description="API title")
api_version: str = Field(default="0.2.0", description="API version")
# CORS
allowed_origins: str = Field(
default="*",
description="Comma-separated list of allowed origins, or * for all",
)
# Rate Limiting
rate_limit_sessions: str = Field(
default="10/minute",
description="Rate limit for session creation",
)
rate_limit_answers: str = Field(
default="60/minute",
description="Rate limit for answer submission",
)
# Security
secret_key: str = Field(
default="",
description="Secret key for badge signing. Required in production.",
)
# Badge settings
badge_expiry_seconds: int = Field(
default=86400,
description="Badge expiry time in seconds (default: 24 hours)",
)
# API Key for admin operations
admin_api_key: str = Field(
default="",
description="Admin API key for tier management and admin operations",
)
# Database
database_url: str = Field(
default="sqlite:///mettle.db",
description="Database URL (sqlite:// or postgresql://)",
)
use_database: bool = Field(
default=False,
description="Enable database persistence (default: in-memory)",
)
# Logging
log_level: str = Field(default="INFO", description="Logging level")
model_config = {
"env_prefix": "METTLE_",
"env_file": ".env",
"extra": "ignore",
}
@property
def allowed_origins_list(self) -> list[str]:
"""Parse allowed origins into a list."""
if self.allowed_origins == "*":
return ["*"]
return [origin.strip() for origin in self.allowed_origins.split(",")]
@property
def is_production(self) -> bool:
"""Check if running in production."""
return self.environment.lower() == "production"
@model_validator(mode="after")
def validate_production_config(self) -> "Settings":
"""SECURITY: Validate security-critical settings in production."""
if self.is_production:
if self.allowed_origins == "*":
import warnings
warnings.warn(
"SECURITY WARNING: CORS allows all origins (*) in production. "
"Set METTLE_ALLOWED_ORIGINS to specific domains.",
stacklevel=2,
)
return self
@lru_cache
def get_settings() -> Settings:
"""Get cached settings instance."""
return Settings()