mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
Merge branch 'main' into litellm_add_scim_patch_user
This commit is contained in:
commit
f8b2e07cce
4 changed files with 80 additions and 2 deletions
13
litellm/proxy/management_endpoints/scim/scim_errors.py
Normal file
13
litellm/proxy/management_endpoints/scim/scim_errors.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
from fastapi import HTTPException
|
||||
|
||||
|
||||
class ScimUserAlreadyExists(HTTPException):
|
||||
"""
|
||||
Exception raised when a user already exists in the database.
|
||||
"""
|
||||
def __init__(self, message: str, scim_type: str = "uniqueness"):
|
||||
super().__init__(status_code=409, detail=message)
|
||||
self.message = message
|
||||
self.scim_type = scim_type
|
||||
self.schemas = ["urn:ietf:params:scim:api:messages:2.0:Error"]
|
||||
|
||||
|
|
@ -17,6 +17,7 @@ from fastapi import (
|
|||
Request,
|
||||
Response,
|
||||
)
|
||||
from prisma.types import HttpConfig
|
||||
|
||||
from litellm._logging import verbose_proxy_logger
|
||||
from litellm.litellm_core_utils.safe_json_dumps import safe_dumps
|
||||
|
|
@ -32,9 +33,11 @@ from litellm.proxy._types import (
|
|||
)
|
||||
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
|
||||
from litellm.proxy.management_endpoints.internal_user_endpoints import new_user
|
||||
from litellm.proxy.management_endpoints.scim.scim_errors import ScimUserAlreadyExists
|
||||
from litellm.proxy.management_endpoints.scim.scim_transformations import (
|
||||
ScimTransformations,
|
||||
)
|
||||
from litellm.proxy.management_endpoints.scim.utils import _extract_error_message
|
||||
from litellm.proxy.management_endpoints.team_endpoints import (
|
||||
new_team,
|
||||
team_member_add,
|
||||
|
|
@ -285,7 +288,6 @@ async def get_user(
|
|||
except Exception as e:
|
||||
raise handle_exception_on_proxy(e)
|
||||
|
||||
|
||||
@scim_router.post(
|
||||
"/Users",
|
||||
response_model=SCIMUser,
|
||||
|
|
@ -335,7 +337,8 @@ async def create_user(
|
|||
user=created_user
|
||||
)
|
||||
return scim_user
|
||||
|
||||
except HTTPException as e: # allow exceptions like SCIMUserAlreadyExists to be raised
|
||||
raise e
|
||||
except Exception as e:
|
||||
raise handle_exception_on_proxy(e)
|
||||
|
||||
|
|
|
|||
20
litellm/proxy/management_endpoints/scim/utils.py
Normal file
20
litellm/proxy/management_endpoints/scim/utils.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
from fastapi import HTTPException
|
||||
|
||||
|
||||
async def _check_user_exists(prisma_client, user_name: str) -> bool:
|
||||
"""Check if user already exists by username"""
|
||||
if not user_name:
|
||||
return False
|
||||
|
||||
existing_user = await prisma_client.db.litellm_usertable.find_unique(
|
||||
where={"user_id": user_name}
|
||||
)
|
||||
return existing_user is not None
|
||||
|
||||
|
||||
def _extract_error_message(http_exception: HTTPException) -> str:
|
||||
"""Extract error message from HTTPException detail"""
|
||||
if isinstance(http_exception.detail, dict):
|
||||
return http_exception.detail.get("error", "User already exists")
|
||||
return str(http_exception.detail)
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
|
||||
from litellm.proxy.management_endpoints.scim.scim_errors import ScimUserAlreadyExists
|
||||
from litellm.proxy.management_endpoints.scim.scim_v2 import create_user
|
||||
from litellm.types.proxy.management_endpoints.scim_v2 import (
|
||||
SCIMUser,
|
||||
SCIMUserEmail,
|
||||
SCIMUserName,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_user_existing_user_conflict(mocker):
|
||||
"""If a user already exists, create_user should raise ScimUserAlreadyExists"""
|
||||
|
||||
scim_user = SCIMUser(
|
||||
schemas=["urn:ietf:params:scim:schemas:core:2.0:User"],
|
||||
userName="existing-user",
|
||||
name=SCIMUserName(familyName="User", givenName="Existing"),
|
||||
emails=[SCIMUserEmail(value="existing@example.com")],
|
||||
)
|
||||
|
||||
mock_prisma = mocker.MagicMock()
|
||||
|
||||
mocker.patch("litellm.proxy.proxy_server.prisma_client", mock_prisma)
|
||||
mocker.patch(
|
||||
"litellm.proxy.management_endpoints.scim.scim_v2._check_user_exists",
|
||||
AsyncMock(return_value=True),
|
||||
)
|
||||
mocked_new_user = mocker.patch(
|
||||
"litellm.proxy.management_endpoints.scim.scim_v2.new_user",
|
||||
AsyncMock(),
|
||||
)
|
||||
|
||||
with pytest.raises(ScimUserAlreadyExists) as exc_info:
|
||||
await create_user(user=scim_user)
|
||||
|
||||
assert exc_info.value.status_code == 409
|
||||
assert "existing-user" in exc_info.value.message
|
||||
mocked_new_user.assert_not_called()
|
||||
Loading…
Add table
Reference in a new issue