mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-12 23:01:41 +00:00
refactor(logs): match ui_view_spend_logs' team-scope clause shape
The scope predicate expanded permitted team ids into an IN list with one
placeholder each, copied from /key/aliases. ui_view_spend_logs, which owns
the same page and the same scoping rules, builds ("user" = $X OR team_id =
ANY($Y::text[])) instead: a single array parameter whatever the team count,
and no placeholder arithmetic to keep in step with the rest of the query.
Same semantics, but the two clauses now read identically, so a future change
to how spend logs are scoped is harder to apply to one and miss in the other.
This commit is contained in:
parent
2a50b3a087
commit
fc278bbf9f
2 changed files with 11 additions and 8 deletions
|
|
@ -833,9 +833,10 @@ async def _build_end_user_scope_condition(
|
|||
|
||||
team_clause: tuple[str, ...] = ()
|
||||
if permitted_team_ids:
|
||||
placeholders = ", ".join(f"${len(query_params) + i + 1}" for i in range(len(permitted_team_ids)))
|
||||
query_params.extend(permitted_team_ids)
|
||||
team_clause = (f"team_id IN ({placeholders})",)
|
||||
# = ANY(::text[]) rather than an expanded IN list, matching the clause
|
||||
# ui_view_spend_logs builds: one parameter whatever the team count.
|
||||
query_params.append(permitted_team_ids)
|
||||
team_clause = (f"team_id = ANY(${len(query_params)}::text[])",)
|
||||
|
||||
scope_parts = user_clause + team_clause
|
||||
if not scope_parts:
|
||||
|
|
|
|||
|
|
@ -885,7 +885,7 @@ def test_customer_aliases_applies_no_scope_for_a_proxy_admin(mock_prisma_client,
|
|||
|
||||
sql = query_raw.call_args.args[0]
|
||||
assert '"user" =' not in sql
|
||||
assert "team_id IN" not in sql
|
||||
assert "team_id" not in sql
|
||||
|
||||
|
||||
@pytest.mark.parametrize("role", [LitellmUserRoles.INTERNAL_USER, LitellmUserRoles.INTERNAL_USER_VIEW_ONLY])
|
||||
|
|
@ -904,8 +904,10 @@ def test_customer_aliases_scopes_a_team_admin_to_their_own_rows_and_teams(mock_p
|
|||
|
||||
assert response.status_code == 200
|
||||
sql = query_raw.call_args.args[0]
|
||||
assert '("user" = $3 OR team_id IN ($4, $5))' in sql
|
||||
assert query_raw.call_args.args[3:6] == ("team-admin-1", "team-a", "team-b")
|
||||
# Same clause shape ui_view_spend_logs builds, so the two cannot diverge.
|
||||
assert '("user" = $3 OR team_id = ANY($4::text[]))' in sql
|
||||
assert query_raw.call_args.args[3] == "team-admin-1"
|
||||
assert query_raw.call_args.args[4] == ["team-a", "team-b"]
|
||||
|
||||
|
||||
def test_customer_aliases_scopes_a_teamless_user_to_their_own_rows(mock_prisma_client):
|
||||
|
|
@ -923,7 +925,7 @@ def test_customer_aliases_scopes_a_teamless_user_to_their_own_rows(mock_prisma_c
|
|||
assert response.status_code == 200
|
||||
sql = query_raw.call_args.args[0]
|
||||
assert '("user" = $3)' in sql
|
||||
assert "team_id IN" not in sql
|
||||
assert "team_id" not in sql
|
||||
assert query_raw.call_args.args[3] == "solo"
|
||||
|
||||
|
||||
|
|
@ -960,7 +962,7 @@ def test_customer_aliases_scopes_when_permitted_team_lookup_fails(mock_prisma_cl
|
|||
assert response.status_code == 200
|
||||
sql = query_raw.call_args.args[0]
|
||||
assert '("user" = $3)' in sql
|
||||
assert "team_id IN" not in sql
|
||||
assert "team_id" not in sql
|
||||
|
||||
|
||||
def test_customer_aliases_fetches_one_extra_row_and_trims_it(mock_prisma_client, mock_user_api_key_auth):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue