99 lines
3.6 KiB
Python
99 lines
3.6 KiB
Python
"""
|
|
config.py
|
|
Configuration classes for Development, Production, and Testing.
|
|
Loaded by both app factories via: from config import config
|
|
"""
|
|
|
|
import os
|
|
from datetime import timedelta
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
|
|
class Config:
|
|
SECRET_KEY = os.environ.get("SECRET_KEY", "dev-fallback-secret-change-me")
|
|
SQLALCHEMY_DATABASE_URI = os.environ.get(
|
|
"DATABASE_URL", "mysql+pymysql://root:password@localhost/salon_pos"
|
|
)
|
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
|
SQLALCHEMY_ENGINE_OPTIONS = {"pool_recycle": 280, "pool_pre_ping": True}
|
|
MAIL_SERVER = os.environ.get("MAIL_SERVER", "localhost")
|
|
MAIL_PORT = int(os.environ.get("MAIL_PORT", 587))
|
|
MAIL_USE_TLS = os.environ.get("MAIL_USE_TLS", "true").lower() == "true"
|
|
MAIL_USERNAME = os.environ.get("MAIL_USERNAME")
|
|
MAIL_PASSWORD = os.environ.get("MAIL_PASSWORD")
|
|
MAIL_DEFAULT_SENDER = os.environ.get("MAIL_USERNAME", "noreply@mydomain.com")
|
|
JWT_ACCESS_TOKEN_EXPIRES = timedelta(seconds=int(os.environ.get("JWT_ACCESS_TOKEN_EXPIRES", 900)))
|
|
JWT_REFRESH_TOKEN_EXPIRES = timedelta(seconds=int(os.environ.get("JWT_REFRESH_TOKEN_EXPIRES", 604800)))
|
|
JWT_TOKEN_LOCATION = ["cookies"]
|
|
JWT_COOKIE_SECURE = True
|
|
JWT_COOKIE_SAMESITE = "Lax"
|
|
JWT_COOKIE_CSRF_PROTECT = True
|
|
SESSION_COOKIE_SECURE = True
|
|
SESSION_COOKIE_HTTPONLY = True
|
|
SESSION_COOKIE_SAMESITE = "Lax"
|
|
RATELIMIT_STORAGE_URI = os.environ.get("RATELIMIT_STORAGE_URI", "memory://")
|
|
RATELIMIT_DEFAULT = "200 per minute"
|
|
RATELIMIT_ENABLED = True
|
|
ADMIN_DOMAIN = os.environ.get("ADMIN_DOMAIN", "admin.mydomain.com")
|
|
TENANT_DOMAIN = os.environ.get("TENANT_DOMAIN", "mydomain.com")
|
|
DEMO_TENANT_SLUG = os.environ.get("DEMO_TENANT_SLUG", "demo")
|
|
ADMIN_IP_ALLOWLIST = os.environ.get("ADMIN_IP_ALLOWLIST", "")
|
|
MAX_LOGIN_ATTEMPTS = int(os.environ.get("MAX_LOGIN_ATTEMPTS", 5))
|
|
LOGIN_LOCKOUT_MINUTES = int(os.environ.get("LOGIN_LOCKOUT_MINUTES", 15))
|
|
STAFF_PASSCODE_MIN_LENGTH = int(os.environ.get("STAFF_PASSCODE_MIN_LENGTH", 4))
|
|
STAFF_PASSCODE_MAX_LENGTH = int(os.environ.get("STAFF_PASSCODE_MAX_LENGTH", 6))
|
|
MAX_CONTENT_LENGTH = 5 * 1024 * 1024
|
|
UPLOAD_EXTENSIONS = {"jpg", "jpeg", "png", "gif"}
|
|
UPLOAD_FOLDER = os.environ.get("UPLOAD_FOLDER", "/var/www/salon_pos_uploads")
|
|
WTF_CSRF_ENABLED = True
|
|
WTF_CSRF_TIME_LIMIT = 3600
|
|
|
|
|
|
class DevelopmentConfig(Config):
|
|
DEBUG = True
|
|
SQLALCHEMY_DATABASE_URI = os.environ.get(
|
|
"DATABASE_URL", "mysql+pymysql://root:password@localhost/salon_pos_dev"
|
|
)
|
|
SESSION_COOKIE_SECURE = False
|
|
JWT_COOKIE_SECURE = False
|
|
RATELIMIT_ENABLED = False
|
|
SESSION_TIMEOUT_TENANT = 1800
|
|
SESSION_TIMEOUT_ADMIN = 3600
|
|
|
|
|
|
class ProductionConfig(Config):
|
|
DEBUG = False
|
|
TESTING = False
|
|
SESSION_TIMEOUT_TENANT = int(os.environ.get("SESSION_TIMEOUT_TENANT", 1800))
|
|
SESSION_TIMEOUT_ADMIN = int(os.environ.get("SESSION_TIMEOUT_ADMIN", 3600))
|
|
|
|
|
|
class TestingConfig(Config):
|
|
TESTING = True
|
|
DEBUG = True
|
|
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
|
|
WTF_CSRF_ENABLED = False
|
|
JWT_COOKIE_SECURE = False
|
|
SESSION_COOKIE_SECURE = False
|
|
RATELIMIT_ENABLED = False
|
|
SESSION_TIMEOUT_TENANT = 1800
|
|
SESSION_TIMEOUT_ADMIN = 3600
|
|
BCRYPT_LOG_ROUNDS = 4
|
|
|
|
|
|
config = {
|
|
"development": DevelopmentConfig,
|
|
"production": ProductionConfig,
|
|
"testing": TestingConfig,
|
|
"default": DevelopmentConfig,
|
|
}
|
|
|
|
|
|
def get_config():
|
|
"""Return the config class for the current FLASK_ENV. Used by app factories."""
|
|
import os
|
|
env = os.environ.get("FLASK_ENV", "development")
|
|
return config.get(env, DevelopmentConfig)
|