mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-08 22:21:35 +00:00
Fix duplicate validation, None dereference, and JSONDecodeError
- Remove duplicate validation block from update_key_fn — team limits,
project limits, team-change, and MCP server checks are already
performed in full by _validate_update_key_data called just above
- Guard against None return from get_team_object in fetch_all_mcp_servers
before accessing team_obj.members_with_roles (raises 404 on unknown team)
- Wrap json.loads in _resolve_team_allowed_mcp_servers with try/except
JSONDecodeError so a malformed stored string falls back to {} instead
of surfacing an unhandled exception
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9c8659e28d
commit
8664612ab2
3 changed files with 14 additions and 77 deletions
|
|
@ -2052,82 +2052,6 @@ async def update_key_fn(
|
|||
user_api_key_cache=user_api_key_cache,
|
||||
)
|
||||
|
||||
# Only check team limits if key has a team_id
|
||||
team_obj: Optional[LiteLLM_TeamTableCachedObj] = None
|
||||
if data.team_id is not None:
|
||||
team_obj = await get_team_object(
|
||||
team_id=data.team_id,
|
||||
prisma_client=prisma_client,
|
||||
user_api_key_cache=user_api_key_cache,
|
||||
check_db_only=True,
|
||||
)
|
||||
|
||||
if team_obj is not None:
|
||||
await _check_team_key_limits(
|
||||
team_table=team_obj,
|
||||
data=data,
|
||||
prisma_client=prisma_client,
|
||||
)
|
||||
|
||||
# Validate key against project limits if project_id is being set
|
||||
_project_id_to_check = getattr(data, "project_id", None) or getattr(
|
||||
existing_key_row, "project_id", None
|
||||
)
|
||||
if _project_id_to_check is not None and (
|
||||
data.models is not None or data.max_budget is not None
|
||||
):
|
||||
await _check_project_key_limits(
|
||||
project_id=_project_id_to_check,
|
||||
data=data,
|
||||
prisma_client=prisma_client,
|
||||
user_api_key_cache=user_api_key_cache,
|
||||
)
|
||||
|
||||
# if team change - check if this is possible
|
||||
if is_different_team(data=data, existing_key_row=existing_key_row):
|
||||
if llm_router is None:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail={
|
||||
"error": "LLM router not found. Please set it up by passing in a valid config.yaml or adding models via the UI."
|
||||
},
|
||||
)
|
||||
# team_obj should be set since is_different_team() returns True only when data.team_id is not None
|
||||
if team_obj is None:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail={
|
||||
"error": "Team object not found for team change validation"
|
||||
},
|
||||
)
|
||||
await validate_key_team_change(
|
||||
key=existing_key_row,
|
||||
team=team_obj,
|
||||
change_initiated_by=user_api_key_dict,
|
||||
llm_router=llm_router,
|
||||
)
|
||||
|
||||
# Validate MCP servers in object_permission against the effective team
|
||||
if data.object_permission is not None:
|
||||
effective_team_obj = team_obj
|
||||
# If team_id isn't being changed, resolve the existing key's team
|
||||
if effective_team_obj is None and existing_key_row.team_id:
|
||||
effective_team_obj = await get_team_object(
|
||||
team_id=existing_key_row.team_id,
|
||||
prisma_client=prisma_client,
|
||||
user_api_key_cache=user_api_key_cache,
|
||||
check_db_only=True,
|
||||
)
|
||||
object_permission_dict = (
|
||||
data.object_permission.model_dump()
|
||||
if hasattr(data.object_permission, "model_dump")
|
||||
else data.object_permission
|
||||
)
|
||||
await validate_key_mcp_servers_against_team(
|
||||
object_permission=object_permission_dict,
|
||||
team_obj=effective_team_obj,
|
||||
)
|
||||
|
||||
non_default_values = await prepare_key_update_data(
|
||||
data=data, existing_key_row=existing_key_row
|
||||
)
|
||||
|
|
|
|||
|
|
@ -739,6 +739,11 @@ if MCP_AVAILABLE:
|
|||
user_api_key_cache=user_api_key_cache,
|
||||
check_db_only=True,
|
||||
)
|
||||
if team_obj is None:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail=f"Team not found: {sanitized_team_id}",
|
||||
)
|
||||
user_in_team = any(
|
||||
m.user_id is not None and m.user_id == user_api_key_dict.user_id
|
||||
for m in team_obj.members_with_roles
|
||||
|
|
|
|||
|
|
@ -215,7 +215,15 @@ async def _resolve_team_allowed_mcp_servers(
|
|||
)
|
||||
raw_tool_perms = team_object_permission.mcp_tool_permissions or {}
|
||||
if isinstance(raw_tool_perms, str):
|
||||
raw_tool_perms = json.loads(raw_tool_perms)
|
||||
try:
|
||||
raw_tool_perms = json.loads(raw_tool_perms)
|
||||
except json.JSONDecodeError:
|
||||
verbose_proxy_logger.warning(
|
||||
"Failed to deserialize mcp_tool_permissions as JSON; treating as empty. "
|
||||
"Value: %r",
|
||||
raw_tool_perms,
|
||||
)
|
||||
raw_tool_perms = {}
|
||||
tool_perm_servers: List[str] = list(raw_tool_perms.keys())
|
||||
return set(direct_servers + access_group_servers + tool_perm_servers)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue