Files
sneakyklaus/src/config.py
Phil Skentelbery b077112aba chore: initial project setup
Initialize Sneaky Klaus project with:
- uv package management and pyproject.toml
- Flask application structure (app.py, config.py)
- SQLAlchemy models for Admin and Exchange
- Alembic database migrations
- Pre-commit hooks configuration
- Development tooling (pytest, ruff, mypy)

Initial structure follows design documents in docs/:
- src/app.py: Application factory with Flask extensions
- src/config.py: Environment-based configuration
- src/models/: Admin and Exchange models
- migrations/: Alembic migration setup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-22 11:28:15 -07:00

121 lines
3.2 KiB
Python

"""Configuration management for Sneaky Klaus application.
This module defines configuration classes for different environments
(development, production, testing) with environment variable support.
"""
import os
from datetime import timedelta
from pathlib import Path
class Config:
"""Base configuration class with common settings."""
# Base paths
BASE_DIR = Path(__file__).parent.parent
DATA_DIR = BASE_DIR / "data"
# Security
SECRET_KEY = os.environ.get("SECRET_KEY") or "dev-secret-key-change-in-production"
# Database
SQLALCHEMY_DATABASE_URI = os.environ.get(
"DATABASE_URL", f"sqlite:///{DATA_DIR / 'sneaky-klaus.db'}"
)
SQLALCHEMY_TRACK_MODIFICATIONS = False
# Session management
SESSION_TYPE = "sqlalchemy"
SESSION_PERMANENT = True
SESSION_USE_SIGNER = True
SESSION_KEY_PREFIX = "sk:"
PERMANENT_SESSION_LIFETIME = timedelta(days=7)
SESSION_COOKIE_SECURE = True # HTTPS only
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = "Lax"
# Flask-WTF CSRF Protection
WTF_CSRF_ENABLED = True
WTF_CSRF_TIME_LIMIT = None # No time limit for CSRF tokens
# Email service (Resend)
RESEND_API_KEY = os.environ.get("RESEND_API_KEY")
# Application URLs
APP_URL = os.environ.get("APP_URL", "http://localhost:5000")
# Timezone
TIMEZONE = os.environ.get("TZ", "UTC")
# Password requirements
MIN_PASSWORD_LENGTH = 12
class DevelopmentConfig(Config):
"""Development environment configuration."""
DEBUG = True
TESTING = False
SESSION_COOKIE_SECURE = False # Allow HTTP in development
SQLALCHEMY_ECHO = True # Log SQL queries
class ProductionConfig(Config):
"""Production environment configuration."""
DEBUG = False
TESTING = False
# Ensure critical environment variables are set
@classmethod
def validate(cls):
"""Validate that required production configuration is present."""
required_vars = ["SECRET_KEY", "RESEND_API_KEY", "APP_URL"]
missing_vars = [var for var in required_vars if not os.environ.get(var)]
if missing_vars:
raise ValueError(
f"Missing required environment variables: {', '.join(missing_vars)}"
)
class TestConfig(Config):
"""Test environment configuration."""
TESTING = True
DEBUG = True
SESSION_COOKIE_SECURE = False
# Use in-memory database for tests
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
# Disable CSRF for easier testing
WTF_CSRF_ENABLED = False
# Use a predictable secret key for tests
SECRET_KEY = "test-secret-key"
# Configuration dictionary for easy access
config = {
"development": DevelopmentConfig,
"production": ProductionConfig,
"testing": TestConfig,
"default": DevelopmentConfig,
}
def get_config(env: str | None = None) -> type[Config]:
"""Get configuration class based on environment.
Args:
env: Environment name (development, production, testing).
If None, uses FLASK_ENV environment variable.
Returns:
Configuration class for the specified environment.
"""
if env is None:
env = os.environ.get("FLASK_ENV", "development")
return config.get(env, config["default"])