mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-11 03:38:38 +00:00
test(proxy): use behavioral assertions in project ownership tests
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
ba518a981d
commit
1049ac4bff
1 changed files with 26 additions and 20 deletions
|
|
@ -16,6 +16,7 @@ from fastapi import HTTPException
|
|||
|
||||
import inspect
|
||||
|
||||
from litellm.models.project import LiteLLM_ProjectTable
|
||||
from litellm.proxy._types import (
|
||||
GenerateKeyRequest,
|
||||
KeyManagementRoutes,
|
||||
|
|
@ -20474,11 +20475,10 @@ async def test_project_detachment_preserves_omission_and_other_key_fields():
|
|||
|
||||
@pytest.mark.parametrize("project_id", [None, "project-orbit", "project-other", ""])
|
||||
@pytest.mark.asyncio
|
||||
async def test_project_detachment_uses_effective_project_for_validation(project_id: str | None):
|
||||
async def test_project_detachment_uses_effective_project_for_validation_on_unowned_project(
|
||||
project_id: str | None,
|
||||
):
|
||||
existing: Final = LiteLLM_VerificationToken(token="project-detach-token", project_id="project-orbit")
|
||||
# An unowned project: this cell is about WHICH project the validation uses,
|
||||
# so the ownership gate (#41089) must not be what it measures. Giving the
|
||||
# key a team instead would pull the whole team lookup into a MagicMock db.
|
||||
cache: Final = await _cache_with_project("project-orbit", ["model-orbit"], team_id=None)
|
||||
data: Final = UpdateKeyRequest(key=existing.token, project_id=project_id, models=["model-other"])
|
||||
if project_id is None:
|
||||
|
|
@ -20807,8 +20807,8 @@ async def test_bulk_key_update_rejects_project_team_change_and_allows_other_fiel
|
|||
new_callable=AsyncMock,
|
||||
),
|
||||
patch(
|
||||
"litellm.proxy.management_endpoints.key_management_endpoints.KeyManagementEventHooks.async_key_updated_hook",
|
||||
new_callable=AsyncMock,
|
||||
"litellm.proxy.management_endpoints.key_management_endpoints.KeyManagementEventHooks",
|
||||
SimpleNamespace(async_key_updated_hook=AsyncMock()),
|
||||
),
|
||||
):
|
||||
response: Final = await bulk_update_keys(
|
||||
|
|
@ -20836,16 +20836,22 @@ async def test_bulk_key_update_rejects_project_team_change_and_allows_other_fiel
|
|||
|
||||
@pytest.mark.parametrize(
|
||||
"request_fields",
|
||||
[{"key_alias": "renamed"}, {"team_id": "team-a"}],
|
||||
[{"key_alias": "renamed"}, {"team_id": _OWNERSHIP_KEY_TEAM}],
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_key_team_ownership_mutation_allows_legacy_mismatch_without_changes(
|
||||
request_fields: dict[str, str],
|
||||
) -> None:
|
||||
prisma_client: Final = MagicMock()
|
||||
prisma_client.db.litellm_projecttable.find_unique = AsyncMock(
|
||||
return_value=LiteLLM_ProjectTable(
|
||||
project_id=_OWNED_PROJECT,
|
||||
team_id=_OWNERSHIP_PROJECT_TEAM,
|
||||
)
|
||||
)
|
||||
existing_key_row: Final = LiteLLM_VerificationToken(
|
||||
token="hashed-key",
|
||||
team_id="team-a",
|
||||
team_id=_OWNERSHIP_KEY_TEAM,
|
||||
project_id=_OWNED_PROJECT,
|
||||
)
|
||||
|
||||
|
|
@ -20856,15 +20862,19 @@ async def test_key_team_ownership_mutation_allows_legacy_mismatch_without_change
|
|||
user_api_key_cache=UserApiKeyCache(),
|
||||
)
|
||||
|
||||
assert prisma_client.mock_calls == []
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_key_team_ownership_mutation_allows_detach_with_team_change() -> None:
|
||||
prisma_client: Final = MagicMock()
|
||||
prisma_client.db.litellm_projecttable.find_unique = AsyncMock(
|
||||
return_value=LiteLLM_ProjectTable(
|
||||
project_id=_OWNED_PROJECT,
|
||||
team_id=_OWNERSHIP_PROJECT_TEAM,
|
||||
)
|
||||
)
|
||||
existing_key_row: Final = LiteLLM_VerificationToken(
|
||||
token="hashed-key",
|
||||
team_id="team-a",
|
||||
team_id=_OWNERSHIP_KEY_TEAM,
|
||||
project_id=_OWNED_PROJECT,
|
||||
)
|
||||
|
||||
|
|
@ -20875,8 +20885,6 @@ async def test_key_team_ownership_mutation_allows_detach_with_team_change() -> N
|
|||
user_api_key_cache=UserApiKeyCache(),
|
||||
)
|
||||
|
||||
assert prisma_client.mock_calls == []
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("key_team_id", "expected_status", "expected_updates"),
|
||||
|
|
@ -20932,23 +20940,21 @@ async def test_regenerate_checks_project_team_ownership(
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_key_project_team_validation_uses_project_missing_404(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
project_lookup: Final = AsyncMock(return_value=None)
|
||||
monkeypatch.setattr(
|
||||
"litellm.proxy.management_endpoints.key_management_endpoints.get_project_object",
|
||||
project_lookup,
|
||||
)
|
||||
async def test_key_project_team_validation_uses_project_missing_404() -> None:
|
||||
prisma_client: Final = MagicMock()
|
||||
prisma_client.db.litellm_projecttable.find_unique = AsyncMock(return_value=None)
|
||||
|
||||
with pytest.raises(HTTPException) as error:
|
||||
await _check_key_project_team(
|
||||
project_id=_OWNED_PROJECT,
|
||||
key_team_id="team-a",
|
||||
prisma_client=MagicMock(),
|
||||
prisma_client=prisma_client,
|
||||
user_api_key_cache=UserApiKeyCache(),
|
||||
)
|
||||
|
||||
assert error.value.status_code == 404
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bulk_update_team_keys_runs_custom_key_policy_per_key(monkeypatch):
|
||||
from litellm.types.proxy.management_endpoints.key_management_endpoints import (
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue