PySimpleSocial/config.py.example

142 lines
4.8 KiB
Plaintext

config.py.example# Configuration file. Each variable can be overridden by a
# corresponding environment variable
import os
import sys
import copy
import logging
import pathlib
from slowapi import Limiter
from slowapi.util import get_remote_address
from fastapi_login import LoginManager
# Authentication configuration
LOGIN_SECRET_KEY = (
os.getenv("LOGIN_SECRET_KEY") or "login-secret"
) # Recommended value: os.urandom(24).hex()
USE_BEARER_HEADER = True
USE_COOKIE = True
# Logging configuration
LOG_LEVEL = int(os.getenv("LOG_LEVEL") or 0) or 20
LOG_FILE = os.getenv("LOG_FILE") or "" # Empty to disable
LOG_FORMAT = os.getenv("LOG_FORMAT") or "[%(levelname)s - %(asctime)s] %(message)s"
LOG_DATE_FORMAT = os.getenv("LOG_DATE_FORMAT") or "%d/%m/%Y %p"
# Bcrypt configuration
BCRYPT_ROUNDS = (
os.getenv("BCRYPT_ROUNDS") or 10
) # How many rounds are used when salting
# Rate limit configuration
REDIS_URL = "" # Used for rate limits. Empty to fall back to memory
REDIS_OPTIONS = {} # Options for redis
RATELIMIT_ENABLED = False # False to disable rate limiting
RATELIMIT_STRATEGY = "moving-window" # Refer to https://flask-limiter.readthedocs.io/en/stable/strategies.html
# Session configuration
SESSION_EXPIRE_LIMIT = 3600 # Unit is in seconds
SESSION_COOKIE_NAME = "_social_media_session"
COOKIE_SAMESITE_POLICY = "none" # Options are "lax", "none", "strict"
COOKIE_DOMAIN = "localhost" # Empty to disable this
COOKIE_PATH = "/"
COOKIE_HTTPONLY = True
SECURE_COOKIE = False # Set to true in production, False during development (unless your local server has HTTPS)
# SMTP configuration
SMTP_HOST = "smtp.nocturn9x.space"
SMTP_USER = "info@example.com"
SMTP_PASSWORD = "password"
SMTP_PORT = 587
SMTP_USE_TLS = True
SMTP_FROM_USER = "info@example.com"
SMTP_TEMPLATES_DIRECTORY = pathlib.Path(__file__) / "templates" / "email"
SMTP_TIMEOUT = 10
# Miscellaneous
# Usernames containing these characters are not valid
INVALID_USERNAME_CHARACTERS = ["@", "\\", "/"] # Empty this to allow any character
# Empty this to disable username validation
VALIDATE_USERNAME_REGEX = (
rf"^([^{''.join(INVALID_USERNAME_CHARACTERS)}]|[a-z0-9A-Z]){{5,32}}$"
)
# Criteria:
# - Between 10 and 72 characters long
# - At least 2 uppercase letters
# - At least 3 lowercase letters
# - At least one special character (!, @, #, $, %, &, *, _, +, /, \, (, ), £, ", ?, ^
# - At least 2 numbers
# You can change the repetitions to enforce stricter/laxer rules or empty
# this field to disable weakness validation
VALIDATE_PASSWORD_REGEX = r"^(?=.*[A-Z]){2,}(?=.*[\"!@%#$&*_^\?\\\/(\)\+\-])+(?=.*[0-9]){2,}(?=.*[a-z]){3,}.{10,72}$"
FORCE_EMAIL_VERIFICATION = False
EMAIL_VERIFICATION_EXPIRATION = 3600 # In seconds
PLATFORM_NAME = "PySimpleSocial" # Used in emails
HAS_HTTPS = False
class NotAuthenticated(Exception):
pass
class AdminNotAuthenticated(Exception):
pass
if __name__ != "__main__":
LOGGER: logging.Logger = logging.getLogger("socialMedia")
LOGGER.setLevel(LOG_LEVEL)
handler = logging.StreamHandler(sys.stderr)
formatter = logging.Formatter(fmt=LOG_FORMAT, datefmt=LOG_DATE_FORMAT)
handler.setFormatter(formatter)
LOGGER.addHandler(handler)
handler.setLevel(LOG_LEVEL)
if LOG_FILE:
file_handler = logging.FileHandler(LOG_FILE, "a", "utf8")
file_handler.setFormatter(formatter)
LOGGER.addHandler(handler)
file_handler.setLevel(LOG_LEVEL)
logging.getLogger("uvicorn").addHandler(file_handler)
LIMITER = Limiter(
key_func=get_remote_address,
strategy=RATELIMIT_STRATEGY,
storage_uri=REDIS_URL or None,
in_memory_fallback_enabled=bool(REDIS_URL),
storage_options=REDIS_OPTIONS,
enabled=RATELIMIT_ENABLED,
)
MANAGER = LoginManager(
LOGIN_SECRET_KEY,
"/user",
use_cookie=True,
cookie_name=SESSION_COOKIE_NAME,
use_header=USE_BEARER_HEADER,
custom_exception=NotAuthenticated,
)
UNVERIFIED_MANAGER = copy.deepcopy(MANAGE)
ADMIN_MANAGER = LoginManager(
LOGIN_SECRET_KEY,
"/admin",
use_cookie=True,
cookie_name=f"{SESSION_COOKIE_NAME}_admin",
use_header=USE_BEARER_HEADER,
custom_exception=AdminNotAuthenticated
)
# Uvicorn config
HOST = os.getenv("HOST") or "localhost"
PORT = int(os.getenv("PORT") or 0) or 8000
WORKERS = int(os.getenv("PORT") or 0) or 1
# Storage configuration
STORAGE_ENGINE = "database" # Stores media inside the database. Other options are "local" to use a local/remote folder
# or "url" for uploading to a CDN
STORAGE_FOLDER = "" # Only needed when STORAGE_ENGINE is set to local
MAX_MEDIA_SIZE = 5242880 # Max length of media allowed. Anything bigger raises a 415 HTTP Exception
ALLOWED_MEDIA_TYPES = ["gif", "png", "jpeg", "tiff"]
ZLIB_COMPRESSION_LEVEL = 9