refactor: S06.2 backend router auto-discovery via ROUTER_CONFIGS manifest (replaces 18 explicit imports)
This commit is contained in:
+30
-68
@@ -21,25 +21,6 @@ import auth_service as auth_module
|
|||||||
import config
|
import config
|
||||||
from config import CORS_ORIGINS, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, VOLUME_ROOT, get_client_ip
|
from config import CORS_ORIGINS, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, VOLUME_ROOT, get_client_ip
|
||||||
from rbac import require_page
|
from rbac import require_page
|
||||||
from routers import auth as auth_router
|
|
||||||
from routers import (
|
|
||||||
chat_summary,
|
|
||||||
conversation_tracker,
|
|
||||||
files,
|
|
||||||
gitea,
|
|
||||||
litellm,
|
|
||||||
opc_agents,
|
|
||||||
opc_projects,
|
|
||||||
opc_tasks,
|
|
||||||
opc_ws,
|
|
||||||
passkey,
|
|
||||||
security,
|
|
||||||
system,
|
|
||||||
terminal,
|
|
||||||
totp,
|
|
||||||
transmission,
|
|
||||||
)
|
|
||||||
|
|
||||||
_tz_cst = timezone(timedelta(hours=8))
|
_tz_cst = timezone(timedelta(hours=8))
|
||||||
|
|
||||||
|
|
||||||
@@ -271,57 +252,38 @@ async def _inject_user(request: Request, user=Depends(auth_module.get_current_us
|
|||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
# Public auth endpoints
|
# Auto-discovered router registration (from ROUTER_CONFIGS manifest)
|
||||||
app.include_router(auth_router.router, prefix="/api/auth", tags=["auth"])
|
from routers import ROUTER_CONFIGS, WS_ROUTES
|
||||||
app.include_router(passkey.router, prefix="/api/auth", tags=["passkey"])
|
import importlib
|
||||||
app.include_router(totp.router, prefix="/api/auth", tags=["totp"])
|
import re
|
||||||
|
|
||||||
# Protected endpoints with page-level RBAC
|
for cfg in ROUTER_CONFIGS:
|
||||||
app.include_router(
|
mod = importlib.import_module('routers.' + cfg['module'])
|
||||||
gitea.router, prefix="/api/gitea", dependencies=[Depends(_inject_user), Depends(require_page("gitea"))]
|
router_attr = cfg.get('router_attr', 'router')
|
||||||
)
|
router_obj = getattr(mod, router_attr)
|
||||||
app.include_router(
|
prefix = cfg.get('prefix')
|
||||||
files.router, prefix="/api/files", dependencies=[Depends(_inject_user)]
|
tags = cfg.get('tags')
|
||||||
)
|
deps = cfg.get('deps', [])
|
||||||
# Public file download endpoint (no auth required for token-based downloads)
|
dep_objects = []
|
||||||
app.include_router(files.public_router, prefix="/api/files")
|
for d in deps:
|
||||||
app.include_router(
|
if d == '_inject_user':
|
||||||
system.router, prefix="/api/system", dependencies=[Depends(_inject_user), Depends(require_page("dashboard"))]
|
dep_objects.append(Depends(_inject_user))
|
||||||
)
|
elif d.startswith('require_page('):
|
||||||
app.include_router(
|
# Extract page name from require_page('gitea') or require_page(gitea)
|
||||||
litellm.router, prefix="/api/litellm", dependencies=[Depends(_inject_user), Depends(require_page("dashboard"))]
|
m = re.search(r'require_page\(["\'](.*?)["\']\)', d)
|
||||||
)
|
page_name = m.group(1) if m else d.split('(')[1].rstrip(')')
|
||||||
app.include_router(
|
dep_objects.append(Depends(require_page(page_name)))
|
||||||
chat_summary.router,
|
kwargs = {'dependencies': dep_objects} if dep_objects else {}
|
||||||
prefix="/api/chat-summary",
|
if prefix is not None:
|
||||||
dependencies=[Depends(_inject_user), Depends(require_page("chat-digest"))],
|
kwargs['prefix'] = prefix
|
||||||
)
|
if tags:
|
||||||
app.include_router(
|
kwargs['tags'] = tags
|
||||||
conversation_tracker.router,
|
app.include_router(router_obj, **kwargs)
|
||||||
prefix="/api/conversations",
|
|
||||||
dependencies=[Depends(_inject_user), Depends(require_page("conversations"))],
|
|
||||||
)
|
|
||||||
app.include_router(
|
|
||||||
security.router, prefix="/api/security", dependencies=[Depends(_inject_user), Depends(require_page("security"))]
|
|
||||||
)
|
|
||||||
app.include_router(
|
|
||||||
transmission.router, dependencies=[Depends(_inject_user), Depends(require_page("transmission"))]
|
|
||||||
)
|
|
||||||
|
|
||||||
# OPC endpoints
|
for ws in WS_ROUTES:
|
||||||
app.include_router(
|
mod = importlib.import_module('routers.' + ws['module'])
|
||||||
opc_tasks.router, prefix="/api/opc", dependencies=[Depends(_inject_user), Depends(require_page("opc"))]
|
handler = getattr(mod, ws['handler'])
|
||||||
)
|
app.add_api_websocket_route(ws['path'], handler)
|
||||||
app.include_router(
|
|
||||||
opc_agents.router, prefix="/api/opc", dependencies=[Depends(_inject_user), Depends(require_page("opc"))]
|
|
||||||
)
|
|
||||||
app.include_router(
|
|
||||||
opc_projects.router, prefix="/api/opc", dependencies=[Depends(_inject_user), Depends(require_page("opc"))]
|
|
||||||
)
|
|
||||||
|
|
||||||
# WebSocket endpoint (auth handled inside handler via auth cookie; query token fallback temporary)
|
|
||||||
app.add_api_websocket_route("/ws/terminal", terminal.ws_endpoint)
|
|
||||||
app.add_api_websocket_route("/ws/opc", opc_ws.websocket_endpoint)
|
|
||||||
|
|
||||||
# Mount static files (skip if directory doesn't exist, e.g., in test environments)
|
# Mount static files (skip if directory doesn't exist, e.g., in test environments)
|
||||||
import os
|
import os
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
"""Router auto-discovery manifest.
|
||||||
|
Each entry defines how a router module gets registered.
|
||||||
|
"""
|
||||||
|
ROUTER_CONFIGS = [
|
||||||
|
{"module": "auth", "prefix": "/api/auth", "tags": ["auth"]},
|
||||||
|
{"module": "passkey", "prefix": "/api/auth", "tags": ["passkey"]},
|
||||||
|
{"module": "totp", "prefix": "/api/auth", "tags": ["totp"]},
|
||||||
|
{"module": "gitea", "prefix": "/api/gitea", "deps": ["_inject_user", "require_page(\"gitea\")"]},
|
||||||
|
{"module": "files", "prefix": "/api/files", "deps": ["_inject_user"]},
|
||||||
|
{"module": "files", "router_attr": "public_router", "prefix": "/api/files"},
|
||||||
|
{"module": "system", "prefix": "/api/system", "deps": ["_inject_user", "require_page(\"dashboard\")"]},
|
||||||
|
{"module": "litellm", "prefix": "/api/litellm", "deps": ["_inject_user", "require_page(\"dashboard\")"]},
|
||||||
|
{"module": "chat_summary", "prefix": "/api/chat-summary", "deps": ["_inject_user", "require_page(\"chat-digest\")"]},
|
||||||
|
{"module": "conversation_tracker", "prefix": "/api/conversations", "deps": ["_inject_user", "require_page(\"conversations\")"]},
|
||||||
|
{"module": "security", "prefix": "/api/security", "deps": ["_inject_user", "require_page(\"security\")"]},
|
||||||
|
{"module": "transmission", "prefix": None, "deps": ["_inject_user", "require_page(\"transmission\")"]},
|
||||||
|
{"module": "opc_tasks", "prefix": "/api/opc", "deps": ["_inject_user", "require_page(\"opc\")"]},
|
||||||
|
{"module": "opc_agents", "prefix": "/api/opc", "deps": ["_inject_user", "require_page(\"opc\")"]},
|
||||||
|
{"module": "opc_projects", "prefix": "/api/opc", "deps": ["_inject_user", "require_page(\"opc\")"]},
|
||||||
|
]
|
||||||
|
WS_ROUTES = [
|
||||||
|
{"module": "terminal", "path": "/ws/terminal", "handler": "ws_endpoint"},
|
||||||
|
{"module": "opc_ws", "path": "/ws/opc", "handler": "websocket_endpoint"},
|
||||||
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user