mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-12 03:48:56 +00:00
* test: migrate tests/proxy_behavior into integration and unit tiers (partial) * test(integration): run settings-dependent management tests on an owned proxy * test(integration): assert stored values in the rewritten management rows * test(integration): pin sibling team allocations against the org guaranteed throughput cap * test(integration): keep Prisma clients out of the shared integration conftest import path --------- Co-authored-by: yuneng <yuneng@berri.ai>
92 lines
3.3 KiB
Python
92 lines
3.3 KiB
Python
import pytest
|
|
|
|
from tests.integration._support.actors import Actor
|
|
from tests.integration._support.actors import create_scratch_team
|
|
|
|
pytestmark = pytest.mark.asyncio(loop_scope="session")
|
|
|
|
|
|
# POST /team/member_delete — actor x team-shape matrix. The resources team is
|
|
# raw-seeded with a victim member already in it; PROXY_ADMIN, the team's team
|
|
# admin, or an org admin of the team's org may remove members; else 403.
|
|
_MATRIX = [
|
|
("alpha/proxy_admin", Actor.PROXY_ADMIN, "alpha", 200),
|
|
("alpha/org_admin", Actor.ORG_ADMIN, "alpha", 200),
|
|
("alpha/team_admin", Actor.TEAM_ADMIN, "alpha", 200),
|
|
("alpha/internal_user", Actor.INTERNAL_USER, "alpha", 403),
|
|
("alpha/owner", Actor.OWNER, "alpha", 403),
|
|
("alpha/unrelated_same_org", Actor.UNRELATED_SAME_ORG, "alpha", 403),
|
|
("alpha/cross_org_user", Actor.CROSS_ORG_USER, "alpha", 403),
|
|
("alpha/service_account", Actor.SERVICE_ACCOUNT, "alpha", 403),
|
|
("alpha/org_b_admin", Actor.ORG_B_ADMIN, "alpha", 403),
|
|
("beta/proxy_admin", Actor.PROXY_ADMIN, "beta", 200),
|
|
("beta/org_admin", Actor.ORG_ADMIN, "beta", 403),
|
|
("beta/team_admin", Actor.TEAM_ADMIN, "beta", 403),
|
|
("beta/internal_user", Actor.INTERNAL_USER, "beta", 403),
|
|
("beta/owner", Actor.OWNER, "beta", 403),
|
|
("beta/unrelated_same_org", Actor.UNRELATED_SAME_ORG, "beta", 403),
|
|
("beta/cross_org_user", Actor.CROSS_ORG_USER, "beta", 403),
|
|
("beta/service_account", Actor.SERVICE_ACCOUNT, "beta", 403),
|
|
("beta/org_b_admin", Actor.ORG_B_ADMIN, "beta", 200),
|
|
]
|
|
|
|
|
|
async def _seed_target(db, actors, shape: str, team_id: str, victim_id: str) -> None:
|
|
if shape == "alpha":
|
|
await create_scratch_team(
|
|
db,
|
|
team_id,
|
|
organization_id=actors.org_a_id,
|
|
admin_user_ids=[actors.keys[Actor.TEAM_ADMIN].user_id],
|
|
member_user_ids=[victim_id],
|
|
)
|
|
elif shape == "beta":
|
|
await create_scratch_team(
|
|
db,
|
|
team_id,
|
|
organization_id=actors.org_b_id,
|
|
member_user_ids=[victim_id],
|
|
)
|
|
else: # pragma: no cover - guard
|
|
pytest.fail(f"unknown shape={shape}")
|
|
|
|
|
|
def _member_ids(row) -> list:
|
|
return [m["user_id"] for m in (row.members_with_roles or [])]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"actor,shape,expected_status",
|
|
[(a, sh, s) for (_id, a, sh, s) in _MATRIX],
|
|
ids=[s[0] for s in _MATRIX],
|
|
)
|
|
async def test_team_member_delete_authz_matrix(
|
|
actor: Actor,
|
|
shape: str,
|
|
expected_status: int,
|
|
gateway_client,
|
|
db,
|
|
resources,
|
|
actors,
|
|
):
|
|
victim_id = resources.tag("victim")
|
|
await _seed_target(db, actors, shape, resources.prefix, victim_id)
|
|
caller = actors.keys[actor]
|
|
|
|
resp = await gateway_client.post(
|
|
"/team/member_delete",
|
|
headers={"Authorization": f"Bearer {caller.cleartext}"},
|
|
json={"team_id": resources.prefix, "user_id": victim_id},
|
|
)
|
|
assert (
|
|
resp.status_code == expected_status
|
|
), f"{actor.value} {shape}: {resp.status_code} {resp.text}"
|
|
|
|
row = await db.db.litellm_teamtable.find_unique(
|
|
where={"team_id": resources.prefix}
|
|
)
|
|
assert row is not None
|
|
if expected_status == 200:
|
|
assert victim_id not in _member_ids(row)
|
|
else:
|
|
assert victim_id in _member_ids(row), "denied but member removed"
|