feat: add CORS configuration options to enhance API security
This commit is contained in:
+14
@@ -15,3 +15,17 @@ PLEXPLAYLISTSYNC_AUTH_TOKEN_SECRET=REPLACE_WITH_A_RANDOM_STRING
|
||||
|
||||
# Token TTL seconds (optional)
|
||||
PLEXPLAYLISTSYNC_AUTH_TOKEN_TTL_SECONDS=86400
|
||||
|
||||
# CORS allowlist (optional)
|
||||
# Default is empty (CORS disabled; same-origin only).
|
||||
# Accepts comma-separated list or a JSON array.
|
||||
# Example:
|
||||
# PLEXPLAYLISTSYNC_CORS_ALLOWED_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
|
||||
# or
|
||||
# PLEXPLAYLISTSYNC_CORS_ALLOWED_ORIGINS=["https://your.domain"]
|
||||
PLEXPLAYLISTSYNC_CORS_ALLOWED_ORIGINS=
|
||||
|
||||
# Allow cookies/credentials for allowlisted origins (optional)
|
||||
# 1 = enabled, 0 = disabled
|
||||
# Note: if origins contains '*', credentials will be forced off.
|
||||
PLEXPLAYLISTSYNC_CORS_ALLOW_CREDENTIALS=0
|
||||
+47
-2
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import json
|
||||
from datetime import datetime
|
||||
from typing import Sequence
|
||||
|
||||
@@ -21,6 +22,50 @@ from app.utils.auth import load_auth_config, issue_token, verify_token
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
def _parse_cors_allowed_origins(raw: str | None) -> list[str]:
|
||||
if not raw:
|
||||
return []
|
||||
|
||||
value = raw.strip()
|
||||
if not value:
|
||||
return []
|
||||
|
||||
if value == "*":
|
||||
return ["*"]
|
||||
|
||||
try:
|
||||
if value.startswith("["):
|
||||
parsed = json.loads(value)
|
||||
if isinstance(parsed, list):
|
||||
origins = [str(item).strip() for item in parsed]
|
||||
else:
|
||||
origins = [str(parsed).strip()]
|
||||
else:
|
||||
origins = [part.strip() for part in value.split(",")]
|
||||
except Exception:
|
||||
logger.warning(
|
||||
"Invalid PLEXPLAYLISTSYNC_CORS_ALLOWED_ORIGINS; CORS will be disabled."
|
||||
)
|
||||
return []
|
||||
|
||||
return [origin for origin in origins if origin]
|
||||
|
||||
|
||||
def _env_truthy(name: str, default: str = "0") -> bool:
|
||||
value = os.getenv(name, default)
|
||||
return str(value).strip().lower() in {"1", "true", "yes", "y", "on"}
|
||||
|
||||
|
||||
_CORS_ALLOWED_ORIGINS = _parse_cors_allowed_origins(
|
||||
os.getenv("PLEXPLAYLISTSYNC_CORS_ALLOWED_ORIGINS", "")
|
||||
)
|
||||
_CORS_ALLOW_CREDENTIALS = (
|
||||
False
|
||||
if "*" in _CORS_ALLOWED_ORIGINS
|
||||
else _env_truthy("PLEXPLAYLISTSYNC_CORS_ALLOW_CREDENTIALS", "0")
|
||||
)
|
||||
|
||||
# --- Optional API Authentication (username/password) ---
|
||||
AUTH_CONFIG = load_auth_config()
|
||||
|
||||
@@ -107,8 +152,8 @@ async def startup_event():
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_origins=_CORS_ALLOWED_ORIGINS,
|
||||
allow_credentials=_CORS_ALLOW_CREDENTIALS,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
+13
-5
@@ -3,12 +3,12 @@ services:
|
||||
build: .
|
||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8080 --reload
|
||||
ports:
|
||||
- "8888:8080"
|
||||
- "8000:8080"
|
||||
volumes:
|
||||
- PATH_TO_YOUR_PLAYLISTS:/app/playlists
|
||||
- PATH_TO_DATA/backup:/app/data/backup
|
||||
- PATH_TO_DATA/config:/app/data/config
|
||||
- PATH_TO_DATA/sync_artifacts:/app/data/sync_artifacts
|
||||
- ./playlists:/app/playlists
|
||||
- ./data/backup:/app/data/backup
|
||||
- ./data/config:/app/data/config
|
||||
- ./data/sync_artifacts:/app/data/sync_artifacts
|
||||
environment:
|
||||
- PYTHONUNBUFFERED=1
|
||||
- PYTHONDONTWRITEBYTECODE=1
|
||||
@@ -16,6 +16,14 @@ services:
|
||||
- PLEXPLAYLISTSYNC_BACKUP_DIR=/app/data/backup
|
||||
- TZ=${TZ:-UTC}
|
||||
- LOG_LEVEL=${LOG_LEVEL:-INFO}
|
||||
# CORS (default: disabled / same-origin only)
|
||||
# Comma-separated list or JSON array. Example:
|
||||
# - PLEXPLAYLISTSYNC_CORS_ALLOWED_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
|
||||
# - PLEXPLAYLISTSYNC_CORS_ALLOWED_ORIGINS=["https://your.domain"]
|
||||
# Use '*' only if you understand the risk (credentials will be forced off).
|
||||
- PLEXPLAYLISTSYNC_CORS_ALLOWED_ORIGINS=${PLEXPLAYLISTSYNC_CORS_ALLOWED_ORIGINS:-}
|
||||
# Optional: allow cookies/credentials for allowed origins (ignored when origins contains '*')
|
||||
- PLEXPLAYLISTSYNC_CORS_ALLOW_CREDENTIALS=${PLEXPLAYLISTSYNC_CORS_ALLOW_CREDENTIALS:-0}
|
||||
# Optional API auth (protects /api/*).
|
||||
# Set PLEXPLAYLISTSYNC_AUTH_ENABLED=1 to enable.
|
||||
- PLEXPLAYLISTSYNC_AUTH_ENABLED=${PLEXPLAYLISTSYNC_AUTH_ENABLED:-0}
|
||||
|
||||
Reference in New Issue
Block a user