- FastAPI async gateway with httpx proxying to multiple upstreams - SQLite database with SQLAlchemy ORM - Admin console: manage services, users, API keys, endpoint access - Per-key, per-endpoint granular access control - OpenAPI document sync and caching (5-minute TTL) - Request/response logging with full transaction inspection - In-memory rate limiting (per-key, fixed-window) - Tiered log retention (7d payloads, 90d rows, incremental vacuum) - TLS verification toggle per service (for self-signed certificates) - Service connectivity validation with automatic endpoint refresh - Request browser with filters and deep-link inspection - Docker setup with persistent volume - Modal forms for create/edit flows Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
30 lines
957 B
Python
30 lines
957 B
Python
from fastapi import Depends, HTTPException, Request, status
|
|
from fastapi.responses import RedirectResponse
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app import config, security
|
|
from app.database import get_db
|
|
from app.models import User
|
|
|
|
|
|
class LoginRequired(HTTPException):
|
|
"""Raised when there is no valid session; handled by redirecting to /admin/login."""
|
|
|
|
def __init__(self):
|
|
super().__init__(status_code=status.HTTP_303_SEE_OTHER)
|
|
|
|
|
|
def login_redirect_handler(request: Request, exc: LoginRequired):
|
|
return RedirectResponse("/admin/login", status_code=303)
|
|
|
|
|
|
def current_user(request: Request, db: Session = Depends(get_db)) -> User:
|
|
token = request.cookies.get(config.SESSION_COOKIE)
|
|
user_id = security.read_session_token(token) if token else None
|
|
if user_id is None:
|
|
raise LoginRequired()
|
|
user = db.get(User, user_id)
|
|
if user is None or not user.is_active:
|
|
raise LoginRequired()
|
|
return user
|