litellm/tests/proxy_admin_ui_tests/test_key_management.py
devin-ai-integration[bot] dfe4df8c8a
test: move whole-unit legacy test files into tests/unit and delete dead skips (#44807)
* test: delete unconditionally skipped legacy tests

* test: move whole-unit legacy test files into tests/unit

* test: keep moved legacy tests free of import-time global state

* test: keep the module-level invocation scan pointed at tests/local_testing

* ci: drop the agent_testing CircleCI job emptied by the move

* test: fix moved-test isolation and router coverage

* test: add Tinyfish search package marker

* test: isolate moved tests from logger state leaks

* test: isolate Helicone logging fixture state

* test: isolate Vertex pass-through credentials between moved tests

* test: cancel S3 periodic flush tasks started by moved tests

* ci: restore CircleCI assistant test selection after move

* test: prevent Datadog datetime import shadowing

* ci: drop the litellm_assistants_api_testing CircleCI job emptied by the move

* test: deduplicate imports in rebased unit tests

* test: remove duplicate passthrough router patch import

* test: remove moved legacy source files after rebase

* test: align moved tests with rebased main

* test: carry main's legacy-file edits into moved destinations

* test: make the moved cost map fallback tests assert the fetch and the backup

The four fallback cases only checked the result was non-empty, so they still
passed with integrity validation disabled. They now inject a mock client, assert
one fetch happened, and assert the result is exactly the local backup with the
fallback reason recorded.

---------

Co-authored-by: yuneng <yuneng@berri.ai>
2026-10-07 05:02:28 +00:00

313 lines
8.7 KiB
Python

from unittest.mock import MagicMock, patch
from dotenv import load_dotenv
load_dotenv()
# this file is to test litellm/proxy
import logging
import pytest
import litellm
from litellm._logging import verbose_proxy_logger
from litellm.proxy._types import *
from litellm.proxy.management_endpoints.key_management_endpoints import (
generate_key_fn,
)
from litellm.proxy.proxy_server import (
LitellmUserRoles,
)
from litellm.proxy.utils import ProxyLogging
verbose_proxy_logger.setLevel(level=logging.DEBUG)
from litellm.caching.caching import DualCache
from litellm.proxy._types import (
GenerateKeyRequest,
UpdateKeyRequest,
UserAPIKeyAuth,
)
from tests._master_key import MASTER_KEY
proxy_logging_obj = ProxyLogging(user_api_key_cache=DualCache())
################ Unit Tests for testing regeneration of keys ###########
def test_is_team_key():
from litellm.proxy.management_endpoints.key_management_endpoints import _is_team_key
assert _is_team_key(GenerateKeyRequest(team_id="test_team_id"))
assert not _is_team_key(GenerateKeyRequest(user_id="test_user_id"))
def test_team_key_generation_team_member_check():
from fastapi import HTTPException
from litellm.proxy._types import LiteLLM_TeamTableCachedObj
from litellm.proxy.management_endpoints.key_management_endpoints import (
_team_key_generation_check,
)
litellm.key_generation_settings = {
"team_key_generation": {"allowed_team_member_roles": ["admin"]}
}
team_table = LiteLLM_TeamTableCachedObj(
team_id="test_team_id",
team_alias="test_team_alias",
members_with_roles=[Member(role="admin", user_id="test_user_id")],
)
assert _team_key_generation_check(
team_table=team_table,
user_api_key_dict=UserAPIKeyAuth(
user_id="test_user_id",
user_role=LitellmUserRoles.INTERNAL_USER,
api_key=MASTER_KEY,
team_member=Member(role="admin", user_id="test_user_id"),
),
data=GenerateKeyRequest(),
route=KeyManagementRoutes.KEY_GENERATE,
)
team_table = LiteLLM_TeamTableCachedObj(
team_id="test_team_id",
team_alias="test_team_alias",
members_with_roles=[Member(role="user", user_id="test_user_id")],
)
with pytest.raises(HTTPException):
_team_key_generation_check(
team_table=team_table,
user_api_key_dict=UserAPIKeyAuth(
user_role=LitellmUserRoles.INTERNAL_USER,
api_key=MASTER_KEY,
user_id="test_user_id",
team_member=Member(role="user", user_id="test_user_id"),
),
data=GenerateKeyRequest(),
route=KeyManagementRoutes.KEY_GENERATE,
)
@pytest.mark.parametrize(
"team_key_generation_settings, input_data, expected_result",
[
({"required_params": ["tags"]}, GenerateKeyRequest(tags=["test_tags"]), True),
({}, GenerateKeyRequest(), True),
(
{"required_params": ["models"]},
GenerateKeyRequest(tags=["test_tags"]),
False,
),
],
)
@pytest.mark.parametrize("key_type", ["team_key", "personal_key"])
def test_key_generation_required_params_check(
team_key_generation_settings, input_data, expected_result, key_type
):
from fastapi import HTTPException
from litellm.proxy._types import LiteLLM_TeamTableCachedObj
from litellm.proxy.management_endpoints.key_management_endpoints import (
_personal_key_generation_check,
_team_key_generation_check,
)
from litellm.types.utils import (
PersonalUIKeyGenerationConfig,
StandardKeyGenerationConfig,
TeamUIKeyGenerationConfig,
)
user_api_key_dict = UserAPIKeyAuth(
user_role=LitellmUserRoles.INTERNAL_USER,
api_key=MASTER_KEY,
user_id="test_user_id",
team_id="test_team_id",
team_member=None,
)
team_table = LiteLLM_TeamTableCachedObj(
team_id="test_team_id",
team_alias="test_team_alias",
members_with_roles=[Member(role="admin", user_id="test_user_id")],
)
if key_type == "team_key":
litellm.key_generation_settings = StandardKeyGenerationConfig(
team_key_generation=TeamUIKeyGenerationConfig(
**team_key_generation_settings
)
)
elif key_type == "personal_key":
litellm.key_generation_settings = StandardKeyGenerationConfig(
personal_key_generation=PersonalUIKeyGenerationConfig(
**team_key_generation_settings
)
)
if expected_result:
if key_type == "team_key":
assert _team_key_generation_check(
team_table=team_table,
user_api_key_dict=user_api_key_dict,
data=input_data,
route=KeyManagementRoutes.KEY_GENERATE,
)
elif key_type == "personal_key":
assert _personal_key_generation_check(
user_api_key_dict=user_api_key_dict,
data=input_data,
)
else:
if key_type == "team_key":
with pytest.raises(HTTPException):
_team_key_generation_check(
team_table=team_table,
user_api_key_dict=user_api_key_dict,
data=input_data,
route=KeyManagementRoutes.KEY_GENERATE,
)
elif key_type == "personal_key":
with pytest.raises(HTTPException):
_personal_key_generation_check(user_api_key_dict, input_data)
def test_personal_key_generation_check():
from fastapi import HTTPException
from litellm.proxy.management_endpoints.key_management_endpoints import (
_personal_key_generation_check,
)
litellm.key_generation_settings = {
"personal_key_generation": {"allowed_user_roles": ["proxy_admin"]}
}
assert _personal_key_generation_check(
user_api_key_dict=UserAPIKeyAuth(
user_role=LitellmUserRoles.PROXY_ADMIN, api_key=MASTER_KEY, user_id="admin"
),
data=GenerateKeyRequest(),
)
with pytest.raises(HTTPException):
_personal_key_generation_check(
user_api_key_dict=UserAPIKeyAuth(
user_role=LitellmUserRoles.INTERNAL_USER,
api_key=MASTER_KEY,
user_id="admin",
),
data=GenerateKeyRequest(),
)
@pytest.mark.parametrize(
"update_request_data, non_default_values, existing_metadata, expected_result",
[
(
{"metadata": {"test": "new"}},
{"metadata": {"test": "new"}},
{"test": "test"},
{"metadata": {"test": "new"}},
),
(
{"tags": ["new_tag"]},
{},
{"tags": ["old_tag"]},
{"metadata": {"tags": ["new_tag"]}},
),
(
{"enforced_params": ["metadata.tags"]},
{},
{"tags": ["old_tag"]},
{"metadata": {"tags": ["old_tag"], "enforced_params": ["metadata.tags"]}},
),
(
{"disable_global_guardrails": True},
{},
{},
{"metadata": {"disable_global_guardrails": True}},
),
(
{"disable_global_guardrails": False},
{},
{"disable_global_guardrails": True},
{"metadata": {"disable_global_guardrails": False}},
),
],
)
def test_prepare_metadata_fields(
update_request_data, non_default_values, existing_metadata, expected_result
):
from litellm.proxy.management_endpoints.key_management_endpoints import (
prepare_metadata_fields,
)
args = {
"data": UpdateKeyRequest(
key="sk-1qGQUJJTcljeaPfzgWRrXQ", **update_request_data
),
"non_default_values": non_default_values,
"existing_metadata": existing_metadata,
}
updated_non_default_values = prepare_metadata_fields(**args)
assert updated_non_default_values == expected_result
@pytest.mark.asyncio
@patch("litellm.proxy.management_endpoints.key_management_endpoints.get_team_object")
async def test_key_generate_always_db_team(mock_get_team_object):
setattr(litellm.proxy.proxy_server, "prisma_client", MagicMock())
mock_get_team_object.return_value = None
try:
await generate_key_fn(
data=GenerateKeyRequest(team_id="1234"),
user_api_key_dict=UserAPIKeyAuth(
user_role=LitellmUserRoles.PROXY_ADMIN,
api_key=MASTER_KEY,
user_id="admin",
),
)
except Exception as e:
print(f"Error: {e}")
mock_get_team_object.assert_called_once()
assert mock_get_team_object.call_args.kwargs["check_db_only"] == True