rayhpeng 0f82f8a3a2 feat(app): add plugin system with auth plugin and static assets
Add new application structure:
- app/main.py - application entry point
- app/plugins/ - plugin system with auth plugin:
  - api/ - REST API endpoints and schemas
  - authorization/ - auth policies, providers, hooks
  - domain/ - business logic (service, models, jwt, password)
  - injection/ - route injection and guards
  - ops/ - operational utilities
  - runtime/ - runtime configuration
  - security/ - middleware, CSRF, dependencies
  - storage/ - user repositories and models
- app/static/ - static assets (scalar.js for API docs)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-22 11:31:42 +08:00

39 lines
1.3 KiB
Python

"""Validation helpers for config-driven auth route policies."""
from __future__ import annotations
from fastapi import FastAPI
from fastapi.routing import APIRoute
from app.plugins.auth.injection.registry_loader import RoutePolicyRegistry
_IGNORED_METHODS = frozenset({"HEAD", "OPTIONS"})
def _iter_route_keys(app: FastAPI) -> set[tuple[str, str]]:
keys: set[tuple[str, str]] = set()
for route in app.routes:
if not isinstance(route, APIRoute):
continue
for method in route.methods:
if method in _IGNORED_METHODS:
continue
keys.add((method, route.path))
return keys
def validate_route_policy_registry(app: FastAPI, registry: RoutePolicyRegistry) -> None:
route_keys = _iter_route_keys(app)
missing = sorted(route_keys - registry.keys)
extra = sorted(registry.keys - route_keys)
problems: list[str] = []
if missing:
problems.append("Missing route policy entries:\n" + "\n".join(f" - {method} {path}" for method, path in missing))
if extra:
problems.append("Unknown route policy entries:\n" + "\n".join(f" - {method} {path}" for method, path in extra))
if problems:
raise RuntimeError("\n\n".join(problems))
__all__ = ["validate_route_policy_registry"]