Add subspace-tv FastAPI service with Unraid deployment

Includes FastAPI application with device authentication, Docker configuration,
Bruno API tests, and git-based deployment scripts for Unraid.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Michael Simard
2026-01-22 09:22:32 -06:00
parent 171d55bd4e
commit 57ad4b0f33
21 changed files with 904 additions and 0 deletions

67
src/auth.py Normal file
View File

@@ -0,0 +1,67 @@
"""Authorization management for device access control."""
import json
import os
from pathlib import Path
from typing import Set
class AuthorizationManager:
"""Manages device authorization with hot-reload capability."""
def __init__(self, file_path: str):
"""Initialize authorization manager with file path.
Args:
file_path: Path to the authorized_devices.json file
"""
self.file_path = Path(file_path)
self._authorized_devices: Set[str] = set()
self._last_modified: float = 0.0
self._load_authorization_list()
def _load_authorization_list(self) -> None:
"""Load authorization list from JSON file."""
try:
if not self.file_path.exists():
self._authorized_devices = set()
self._last_modified = 0.0
return
stat = os.stat(self.file_path)
self._last_modified = stat.st_mtime
with open(self.file_path, "r") as f:
data = json.load(f)
self._authorized_devices = set(data.get("authorized_devices", []))
except (json.JSONDecodeError, OSError) as e:
self._authorized_devices = set()
self._last_modified = 0.0
def _check_reload(self) -> None:
"""Check if authorization file has been modified and reload if necessary."""
try:
if not self.file_path.exists():
if self._last_modified != 0.0:
self._authorized_devices = set()
self._last_modified = 0.0
return
stat = os.stat(self.file_path)
if stat.st_mtime > self._last_modified:
self._load_authorization_list()
except OSError:
pass
def is_authorized(self, device_id: str) -> bool:
"""Check if a device ID is authorized.
Args:
device_id: The device identifier to check
Returns:
True if authorized, False otherwise
"""
self._check_reload()
return device_id in self._authorized_devices