diff --git a/litellm/proxy/auth/route_checks.py b/litellm/proxy/auth/route_checks.py index 22e6bbffb3..6976555aee 100644 --- a/litellm/proxy/auth/route_checks.py +++ b/litellm/proxy/auth/route_checks.py @@ -153,47 +153,11 @@ class RouteChecks: ): pass elif _user_role == LitellmUserRoles.PROXY_ADMIN_VIEW_ONLY.value: - - if RouteChecks.is_llm_api_route(route=route): - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=f"user not allowed to access this OpenAI routes, role= {_user_role}", - ) - - # Check if this is a write operation on management routes - if RouteChecks.check_route_access( - route=route, allowed_routes=LiteLLMRoutes.management_routes.value - ): - # For management routes, only allow read operations or specific allowed updates - if route == "/user/update": - # Check the Request params are valid for PROXY_ADMIN_VIEW_ONLY - if request_data is not None and isinstance(request_data, dict): - _params_updated = request_data.keys() - for param in _params_updated: - if param not in ["user_email", "password"]: - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=f"user not allowed to access this route, role= {_user_role}. Trying to access: {route} and updating invalid param: {param}. only user_email and password can be updated", - ) - elif route in ["/user/new", "/user/delete", "/team/new", "/team/update", "/team/delete", "/model/new", "/model/update", "/model/delete"]: - # Block write operations for PROXY_ADMIN_VIEW_ONLY - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=f"user not allowed to access this route, role= {_user_role}. Trying to access: {route}", - ) - # Allow read operations on management routes (like /user/info, /team/info, /model/info) - pass - elif RouteChecks.check_route_access( - route=route, allowed_routes=LiteLLMRoutes.admin_viewer_routes.value - ): - # Allow access to admin viewer routes (read-only admin endpoints) - pass - else: - # For other routes, block access - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=f"user not allowed to access this route, role= {_user_role}. Trying to access: {route}", - ) + RouteChecks._check_proxy_admin_viewer_access( + route=route, + _user_role=_user_role, + request_data=request_data, + ) elif ( _user_role == LitellmUserRoles.INTERNAL_USER.value and RouteChecks.check_route_access( @@ -410,3 +374,53 @@ class RouteChecks: if "streamGenerateContent" in route: return True return False + + @staticmethod + def _check_proxy_admin_viewer_access( + route: str, + _user_role: str, + request_data: dict, + ) -> None: + """ + Check access for PROXY_ADMIN_VIEW_ONLY role + """ + if RouteChecks.is_llm_api_route(route=route): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=f"user not allowed to access this OpenAI routes, role= {_user_role}", + ) + + # Check if this is a write operation on management routes + if RouteChecks.check_route_access( + route=route, allowed_routes=LiteLLMRoutes.management_routes.value + ): + # For management routes, only allow read operations or specific allowed updates + if route == "/user/update": + # Check the Request params are valid for PROXY_ADMIN_VIEW_ONLY + if request_data is not None and isinstance(request_data, dict): + _params_updated = request_data.keys() + for param in _params_updated: + if param not in ["user_email", "password"]: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=f"user not allowed to access this route, role= {_user_role}. Trying to access: {route} and updating invalid param: {param}. only user_email and password can be updated", + ) + elif route in ["/user/new", "/user/delete", "/team/new", "/team/update", "/team/delete", "/model/new", "/model/update", "/model/delete"]: + # Block write operations for PROXY_ADMIN_VIEW_ONLY + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=f"user not allowed to access this route, role= {_user_role}. Trying to access: {route}", + ) + # Allow read operations on management routes (like /user/info, /team/info, /model/info) + return + elif RouteChecks.check_route_access( + route=route, allowed_routes=LiteLLMRoutes.admin_viewer_routes.value + ): + # Allow access to admin viewer routes (read-only admin endpoints) + return + else: + # For other routes, block access + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=f"user not allowed to access this route, role= {_user_role}. Trying to access: {route}", + )