- New User model (username, argon2id password_hash, totp fields, lockout) - New UserSession model (DB-backed revocation, replaces in-memory set) - New services/auth.py: Argon2id hashing, bcrypt→Argon2id upgrade path, URLSafeTimedSerializer session/MFA tokens - New schemas/auth.py: SetupRequest, LoginRequest, ChangePasswordRequest with OWASP password strength validation - Full rewrite of routers/auth.py: setup/login/logout/status/change-password with account lockout (10 failures → 30-min, HTTP 423), IP rate limiting retained as outer layer, get_current_user + get_current_settings dependencies replacing get_current_session - Settings model: drop pin_hash, add user_id FK (nullable for migration) - Schemas/settings.py: remove SettingsCreate, ChangePinRequest, _validate_pin_length - Settings router: rewrite to use get_current_user + get_current_settings, preserve ntfy test endpoint - All 11 consumer routers updated: auth-gate-only routers use get_current_user, routers reading Settings fields use get_current_settings - config.py: add SESSION_MAX_AGE_DAYS, MFA_TOKEN_MAX_AGE_SECONDS, TOTP_ISSUER - main.py: import User and UserSession models for Alembic discovery - requirements.txt: add argon2-cffi>=23.1.0 - Migration 023: create users + user_sessions tables, migrate pin_hash → User row (admin), backfill settings.user_id, drop pin_hash Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
43 lines
1.3 KiB
Python
43 lines
1.3 KiB
Python
import sys
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
DATABASE_URL: str = "postgresql+asyncpg://postgres:postgres@localhost:5432/umbra"
|
|
SECRET_KEY: str = "your-secret-key-change-in-production"
|
|
ENVIRONMENT: str = "development"
|
|
COOKIE_SECURE: bool = False
|
|
OPENWEATHERMAP_API_KEY: str = ""
|
|
|
|
# Session config
|
|
SESSION_MAX_AGE_DAYS: int = 30
|
|
|
|
# MFA token config (short-lived token bridging password OK → TOTP verification)
|
|
MFA_TOKEN_MAX_AGE_SECONDS: int = 300 # 5 minutes
|
|
|
|
# TOTP issuer name shown in authenticator apps
|
|
TOTP_ISSUER: str = "UMBRA"
|
|
|
|
model_config = SettingsConfigDict(
|
|
env_file=".env",
|
|
env_file_encoding="utf-8",
|
|
case_sensitive=True
|
|
)
|
|
|
|
|
|
settings = Settings()
|
|
|
|
if settings.SECRET_KEY == "your-secret-key-change-in-production":
|
|
if settings.ENVIRONMENT != "development":
|
|
print(
|
|
"FATAL: Default SECRET_KEY detected in non-development environment. "
|
|
"Set a unique SECRET_KEY in .env immediately.",
|
|
file=sys.stderr,
|
|
)
|
|
sys.exit(1)
|
|
else:
|
|
print(
|
|
"WARNING: Using default SECRET_KEY. Set SECRET_KEY in .env for production.",
|
|
file=sys.stderr,
|
|
)
|