From 5cfb92cfc60ffcc0096e894245892eec12e9ea1a Mon Sep 17 00:00:00 2001 From: "Gan, Jimmy" Date: Thu, 2 Apr 2026 00:34:25 +0800 Subject: [PATCH] fix: revert to original _inject_user in main.py, ensure it runs before require_page --- dashboard/backend/main.py | 13 +++++++++---- dashboard/backend/rbac.py | 20 ++++++-------------- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/dashboard/backend/main.py b/dashboard/backend/main.py index 154daf3..607c391 100644 --- a/dashboard/backend/main.py +++ b/dashboard/backend/main.py @@ -9,7 +9,7 @@ from slowapi.errors import RateLimitExceeded from routers import docker_router, gitea, files, terminal, system, auth, chat_summary, security, passkey, totp, litellm, cc_connect, info_engine, opc_tasks, opc_agents, opc_ws, opc_projects import auth as auth_module import config -from rbac import require_page, _inject_user +from rbac import require_page import asyncio import httpx @@ -164,6 +164,11 @@ def _router_reachable(): except Exception: return False +# Dependency to store user in request.state for rbac dependencies +async def _inject_user(request: Request, user = Depends(auth_module.get_current_user)): + request.state.user = user + return user + # Public auth endpoints app.include_router(auth.router, prefix="/api/auth", tags=["auth"]) app.include_router(passkey.router, prefix="/api/auth", tags=["passkey"]) @@ -191,11 +196,11 @@ app.include_router(security.router, prefix="/api/security", # OPC endpoints app.include_router(opc_tasks.router, prefix="/api/opc", - dependencies=[Depends(require_page("opc"))]) + dependencies=[Depends(_inject_user), Depends(require_page("opc"))]) app.include_router(opc_agents.router, prefix="/api/opc", - dependencies=[Depends(require_page("opc"))]) + dependencies=[Depends(_inject_user), Depends(require_page("opc"))]) app.include_router(opc_projects.router, prefix="/api/opc", - dependencies=[Depends(require_page("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) diff --git a/dashboard/backend/rbac.py b/dashboard/backend/rbac.py index 526d91a..87e8416 100644 --- a/dashboard/backend/rbac.py +++ b/dashboard/backend/rbac.py @@ -115,7 +115,8 @@ def has_page_access(user: User, page: str) -> bool: def require_page(page: str): """FastAPI dependency factory — 403 if user lacks page access.""" - async def checker(user: User = Depends(_inject_user)): + async def checker(request: Request): + user: User = request.state.user if not has_page_access(user, page): raise HTTPException(status_code=403, detail="Access denied") return checker @@ -123,7 +124,8 @@ def require_page(page: str): def require_admin(): """FastAPI dependency — 403 if user is not admin.""" - async def checker(user: User = Depends(_inject_user)): + async def checker(request: Request): + user: User = request.state.user if user.role != "admin": raise HTTPException(status_code=403, detail="Admin only") return checker @@ -131,18 +133,8 @@ def require_admin(): def require_write(): """FastAPI dependency — 403 if viewer tries non-GET method.""" - async def checker(request: Request, user: User = Depends(_inject_user)): + async def checker(request: Request): + user: User = request.state.user if user.role == "viewer" and request.method != "GET": raise HTTPException(status_code=403, detail="Read-only access") return checker - - -async def _inject_user(request: Request): - """Dependency to store user in request.state for rbac dependencies. - - Import auth module at runtime to avoid circular imports. - """ - import auth as auth_module - user = await auth_module.get_current_user(request) - request.state.user = user - return user