Implement code word based remote authentication #1

Merged
LeoVasanko merged 16 commits from remote-auth into main 2025-12-08 23:56:48 +00:00
3 changed files with 15 additions and 4 deletions
Showing only changes of commit 9763ab37bc - Show all commits
+3 -1
View File
@@ -273,7 +273,7 @@ def main():
}
# Dev mode: enable reload when PASKIA_DEVMODE is set
devmode = os.environ.get("PASKIA_DEVMODE") == "1"
devmode = bool(os.environ.get("PASKIA_DEVMODE"))
if devmode:
# Security: dev mode must run on localhost:4402 to prevent
# accidental public exposure of the Vite dev server
@@ -281,6 +281,8 @@ def main():
raise SystemExit(f"Dev mode requires localhost:4402, got {host}:{port}")
run_kwargs["reload"] = True
run_kwargs["reload_dirs"] = ["paskia"]
# Suppress uvicorn startup messages in dev mode
run_kwargs["log_level"] = "warning"
if uds:
run_kwargs["uds"] = uds
+5
View File
@@ -45,6 +45,11 @@ async def lifespan(app: FastAPI): # pragma: no cover - startup path
# Re-raise to fail fast
raise
# Restore info level logging after startup (suppressed during uvicorn init in dev mode)
if frontend.is_dev_mode():
logging.getLogger("uvicorn").setLevel(logging.INFO)
logging.getLogger("uvicorn.access").setLevel(logging.INFO)
yield
# Shutdown cleanup
+7 -3
View File
@@ -8,7 +8,10 @@ import httpx
__all__ = ["path", "file", "read", "is_dev_mode"]
DEV_SERVER = "http://localhost:4403"
def _get_dev_server() -> str | None:
"""Get the dev server URL from environment, or None if not in dev mode."""
return os.environ.get("PASKIA_DEVMODE") or None
def _resolve_static_dir() -> Path:
@@ -34,7 +37,7 @@ def file(*parts: str) -> Path:
def is_dev_mode() -> bool:
"""Check if we're running in dev mode (Vite frontend server)."""
return os.environ.get("PASKIA_DEVMODE") == "1"
return bool(_get_dev_server())
async def read(filepath: str) -> tuple[bytes, int, dict[str, str]]:
@@ -51,8 +54,9 @@ async def read(filepath: str) -> tuple[bytes, int, dict[str, str]]:
FastAPI Response(*args) or Sanic raw response.
"""
if is_dev_mode():
dev_server = _get_dev_server()
async with httpx.AsyncClient() as client:
resp = await client.get(f"{DEV_SERVER}{filepath}")
resp = await client.get(f"{dev_server}{filepath}")
resp.raise_for_status()
mime = resp.headers.get("content-type", "application/octet-stream")
# Strip charset suffix if present