video_press/app/config.py

51 lines
1.8 KiB
Python

"""
app/config.py
=============
Central configuration and the path-jail helper used by every other module.
All tuneable values can be overridden via environment variables:
MEDIA_ROOT Root directory the application may read/write (default: /media)
DB_PATH Path to the SQLite database file (default: <project>/videopress.db)
PORT TCP port Gunicorn listens on (default: 8080)
LOG_LEVEL Gunicorn log verbosity (default: info)
"""
import os
from pathlib import Path
# ---------------------------------------------------------------------------
# Paths
# ---------------------------------------------------------------------------
PACKAGE_DIR = Path(__file__).resolve().parent # …/app/
BASE_DIR = PACKAGE_DIR.parent # …/videocompressor/
# Every file-system operation in the application is restricted to MEDIA_ROOT.
MEDIA_ROOT = Path(os.environ.get('MEDIA_ROOT', '/media')).resolve()
# ---------------------------------------------------------------------------
# Path-jail helper
# ---------------------------------------------------------------------------
def safe_path(raw: str) -> Path:
"""
Resolve *raw* to an absolute path and assert it is inside MEDIA_ROOT.
Returns the resolved Path on success.
Raises PermissionError if the path would escape MEDIA_ROOT (including
symlink traversal and ../../ attacks).
"""
try:
resolved = Path(raw).resolve()
except Exception:
raise PermissionError(f"Invalid path: {raw!r}")
root_str = str(MEDIA_ROOT)
path_str = str(resolved)
if path_str != root_str and not path_str.startswith(root_str + os.sep):
raise PermissionError(
f"Access denied: '{resolved}' is outside the allowed "
f"media root ({MEDIA_ROOT})."
)
return resolved