lazyflat: combined alert + apply behind authenticated web UI

Three isolated services (alert scraper, apply HTTP worker, web UI+DB)
with argon2 auth, signed cookies, CSRF, rate-limited login, kill switch,
apply circuit breaker, audit log, and strict CSP.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Moritz 2026-04-21 09:51:35 +02:00
commit 69f2f1f635
46 changed files with 4183 additions and 0 deletions

83
apply/main.py Normal file
View file

@ -0,0 +1,83 @@
import logging
from contextlib import asynccontextmanager
from urllib.parse import urlparse
from fastapi import Depends, FastAPI, Header, HTTPException, status
from pydantic import BaseModel
from rich.console import Console
from rich.logging import RichHandler
import providers
from classes.application_result import ApplicationResult
from language import _
from settings import INTERNAL_API_KEY, log_settings
def setup_logging():
logging.basicConfig(
level=logging.WARNING,
format="%(message)s",
datefmt="[%X]",
handlers=[RichHandler(markup=True, console=Console(width=110))],
)
logging.getLogger("flat-apply").setLevel(logging.DEBUG)
logger = logging.getLogger("flat-apply")
setup_logging()
class ApplyRequest(BaseModel):
url: str
class ApplyResponse(BaseModel):
success: bool
message: str
def require_api_key(x_internal_api_key: str | None = Header(default=None)) -> None:
if not INTERNAL_API_KEY:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="apply service has no INTERNAL_API_KEY configured",
)
if x_internal_api_key != INTERNAL_API_KEY:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid api key")
@asynccontextmanager
async def lifespan(_app: FastAPI):
log_settings()
logger.info(f"apply ready, providers: {sorted(providers.PROVIDERS)}")
yield
app = FastAPI(lifespan=lifespan, title="lazyflat-apply")
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/apply", response_model=ApplyResponse, dependencies=[Depends(require_api_key)])
async def apply(req: ApplyRequest):
url = req.url.strip()
domain = urlparse(url).netloc.lower().removeprefix("www.")
logger.info(f"apply request for domain={domain} url={url}")
if domain not in providers.PROVIDERS:
logger.warning(f"unsupported provider: {domain}")
result = ApplicationResult(False, message=_("unsupported_association"))
return ApplyResponse(success=result.success, message=str(result))
try:
provider = providers.PROVIDERS[domain]
result = await provider.apply_for_flat(url)
logger.info(f"application result: {repr(result)}")
except Exception as e:
logger.exception("error while applying")
result = ApplicationResult(False, f"Script Error:\n{e}")
return ApplyResponse(success=result.success, message=str(result))