Skip to content

Commit 4e6c4be

Browse files
authored
[Feat] Permission management vector stores on LiteLLM Key, Team, Orgs (#11213)
* fix: init commit for object permissions * fix: init commit for object permissions * fix: add vector_store_id to permissions * fix vector store selector * feat:add vector store permission mgmt * feat: ui add allowed vector stores dropdown * feat: add new vector store object permissions * testing: key mgmt * fix: stor vector store permissions on team * ui select vector store for teams * ui add vector store settings for orgs * feat: allow setting org vector store permissions * test: adding team permissions for vector stores
1 parent 178a614 commit 4e6c4be

File tree

15 files changed

+429
-5
lines changed

15 files changed

+429
-5
lines changed

litellm-proxy-extras/litellm_proxy_extras/schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ model LiteLLM_UserTable {
155155
model LiteLLM_ObjectPermissionTable {
156156
object_permission_id String @id @default(uuid())
157157
mcp_servers String[] @default([])
158+
vector_stores String[] @default([])
158159
159160
teams LiteLLM_TeamTable[]
160161
verification_tokens LiteLLM_VerificationToken[]

litellm/model_prices_and_context_window_backup.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,23 @@
421421
"supports_system_messages": true,
422422
"supports_tool_choice": true
423423
},
424+
"gpt-4o-mini-audio-preview": {
425+
"max_tokens": 16384,
426+
"max_input_tokens": 128000,
427+
"max_output_tokens": 16384,
428+
"input_cost_per_token": 0.00000015,
429+
"input_cost_per_audio_token": 0.00001,
430+
"output_cost_per_token": 0.0000006,
431+
"output_cost_per_audio_token": 0.00002,
432+
"litellm_provider": "openai",
433+
"mode": "chat",
434+
"supports_function_calling": true,
435+
"supports_parallel_function_calling": true,
436+
"supports_audio_input": true,
437+
"supports_audio_output": true,
438+
"supports_system_messages": true,
439+
"supports_tool_choice": true
440+
},
424441
"gpt-4o-mini-audio-preview-2024-12-17": {
425442
"max_tokens": 16384,
426443
"max_input_tokens": 128000,

litellm/proxy/_types.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,11 @@ def set_model_info(cls, values):
659659
return values
660660

661661

662+
class LiteLLM_ObjectPermissionBase(LiteLLMPydanticObjectBase):
663+
mcp_servers: Optional[List[str]] = None
664+
vector_stores: Optional[List[str]] = None
665+
666+
662667
class GenerateRequestBase(LiteLLMPydanticObjectBase):
663668
"""
664669
Overlapping schema between key and user generate/update requests
@@ -689,6 +694,7 @@ class GenerateRequestBase(LiteLLMPydanticObjectBase):
689694
guardrails: Optional[List[str]] = None
690695
blocked: Optional[bool] = None
691696
aliases: Optional[dict] = {}
697+
object_permission: Optional[LiteLLM_ObjectPermissionBase] = None
692698

693699

694700
class KeyRequestBase(GenerateRequestBase):
@@ -1110,6 +1116,7 @@ class NewTeamRequest(TeamBase):
11101116
model_aliases: Optional[dict] = None
11111117
tags: Optional[list] = None
11121118
guardrails: Optional[List[str]] = None
1119+
object_permission: Optional[LiteLLM_ObjectPermissionBase] = None
11131120

11141121
model_config = ConfigDict(protected_namespaces=())
11151122

@@ -1261,6 +1268,12 @@ class LiteLLM_TeamTable(TeamBase):
12611268
updated_at: Optional[datetime] = None
12621269
created_at: Optional[datetime] = None
12631270

1271+
#########################################################
1272+
# Object Permission - MCP, Vector Stores etc.
1273+
#########################################################
1274+
object_permission_id: Optional[str] = None
1275+
object_permission: Optional[LiteLLM_ObjectPermissionTable] = None
1276+
12641277
model_config = ConfigDict(protected_namespaces=())
12651278

12661279
@model_validator(mode="before")
@@ -1338,6 +1351,11 @@ class NewOrganizationRequest(LiteLLM_BudgetTable):
13381351
budget_id: Optional[str] = None
13391352
metadata: Optional[dict] = None
13401353

1354+
#########################################################
1355+
# Object Permission - MCP, Vector Stores etc.
1356+
#########################################################
1357+
object_permission: Optional[LiteLLM_ObjectPermissionBase] = None
1358+
13411359

13421360
class OrganizationRequest(LiteLLMPydanticObjectBase):
13431361
organizations: List[str]
@@ -1619,6 +1637,7 @@ class LiteLLM_VerificationToken(LiteLLMPydanticObjectBase):
16191637
created_by: Optional[str] = None
16201638
updated_at: Optional[datetime] = None
16211639
updated_by: Optional[str] = None
1640+
object_permission: Optional[LiteLLM_ObjectPermissionTable] = None
16221641

16231642
model_config = ConfigDict(protected_namespaces=())
16241643

@@ -1761,6 +1780,7 @@ class LiteLLM_UserTable(LiteLLMPydanticObjectBase):
17611780
metadata: Optional[dict] = None
17621781
created_at: Optional[datetime] = None
17631782
updated_at: Optional[datetime] = None
1783+
object_permission: Optional[LiteLLM_ObjectPermissionTable] = None
17641784

17651785
@model_validator(mode="before")
17661786
@classmethod
@@ -1790,6 +1810,12 @@ class LiteLLM_OrganizationTable(LiteLLMPydanticObjectBase):
17901810
users: Optional[List[LiteLLM_UserTable]] = None
17911811
litellm_budget_table: Optional[LiteLLM_BudgetTable] = None
17921812

1813+
#########################################################
1814+
# Object Permission - MCP, Vector Stores etc.
1815+
#########################################################
1816+
object_permission: Optional[LiteLLM_ObjectPermissionTable] = None
1817+
object_permission_id: Optional[str] = None
1818+
17931819

17941820
class LiteLLM_OrganizationTableWithMembers(LiteLLM_OrganizationTable):
17951821
"""Returned by the /organization/info endpoint and /organization/list endpoint"""

litellm/proxy/management_endpoints/key_management_endpoints.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ async def generate_key_fn( # noqa: PLR0915
376376
- tags: Optional[List[str]] - Tags for [tracking spend](https://litellm.vercel.app/docs/proxy/enterprise#tracking-spend-for-custom-tags) and/or doing [tag-based routing](https://litellm.vercel.app/docs/proxy/tag_routing).
377377
- enforced_params: Optional[List[str]] - List of enforced params for the key (Enterprise only). [Docs](https://docs.litellm.ai/docs/proxy/enterprise#enforce-required-params-for-llm-requests)
378378
- allowed_routes: Optional[list] - List of allowed routes for the key. Store the actual route or store a wildcard pattern for a set of routes. Example - ["/chat/completions", "/embeddings", "/keys/*"]
379+
- object_permission: Optional[LiteLLM_ObjectPermissionTable] - key-specific object permission. Example - {"vector_stores": ["vector_store_1", "vector_store_2"]}. IF null or {} then no object permission.
379380
Examples:
380381
381382
1. Allow users to turn on/off pii masking
@@ -571,6 +572,11 @@ async def generate_key_fn( # noqa: PLR0915
571572

572573
data_json.pop("tags")
573574

575+
data_json = await _set_object_permission(
576+
data_json=data_json,
577+
prisma_client=prisma_client,
578+
)
579+
574580
await _enforce_unique_key_alias(
575581
key_alias=data_json.get("key_alias", None),
576582
prisma_client=prisma_client,
@@ -641,6 +647,32 @@ def prepare_metadata_fields(
641647
return non_default_values
642648

643649

650+
async def _set_object_permission(
651+
data_json: dict,
652+
prisma_client: Optional[PrismaClient],
653+
):
654+
"""
655+
Creates the LiteLLM_ObjectPermissionTable record for the key.
656+
- Handles permissions for vector stores and mcp servers.
657+
"""
658+
if prisma_client is None:
659+
return data_json
660+
661+
if "object_permission" in data_json:
662+
created_object_permission = (
663+
await prisma_client.db.litellm_objectpermissiontable.create(
664+
data=data_json["object_permission"],
665+
)
666+
)
667+
data_json[
668+
"object_permission_id"
669+
] = created_object_permission.object_permission_id
670+
671+
# delete the object_permission from the data_json
672+
data_json.pop("object_permission")
673+
return data_json
674+
675+
644676
def prepare_key_update_data(
645677
data: Union[UpdateKeyRequest, RegenerateKeyRequest], existing_key_row
646678
):
@@ -1273,6 +1305,9 @@ async def generate_key_helper_fn( # noqa: PLR0915
12731305
updated_by: Optional[str] = None,
12741306
allowed_routes: Optional[list] = None,
12751307
sso_user_id: Optional[str] = None,
1308+
object_permission_id: Optional[
1309+
str
1310+
] = None, # object_permission_id <-> LiteLLM_ObjectPermissionTable
12761311
):
12771312
from litellm.proxy.proxy_server import (
12781313
litellm_proxy_budget_name,
@@ -1351,6 +1386,7 @@ async def generate_key_helper_fn( # noqa: PLR0915
13511386
"budget_reset_at": reset_at,
13521387
"allowed_cache_controls": allowed_cache_controls,
13531388
"sso_user_id": sso_user_id,
1389+
"object_permission_id": object_permission_id,
13541390
}
13551391
if teams is not None:
13561392
user_data["teams"] = teams
@@ -1379,6 +1415,7 @@ async def generate_key_helper_fn( # noqa: PLR0915
13791415
"created_by": created_by,
13801416
"updated_by": updated_by,
13811417
"allowed_routes": allowed_routes or [],
1418+
"object_permission_id": object_permission_id,
13821419
}
13831420

13841421
if (
@@ -1452,6 +1489,9 @@ async def generate_key_helper_fn( # noqa: PLR0915
14521489
key_data["litellm_budget_table"] = getattr(
14531490
create_key_response, "litellm_budget_table", None
14541491
)
1492+
key_data["object_permission"] = getattr(
1493+
create_key_response, "object_permission", None
1494+
)
14551495
key_data["created_at"] = getattr(create_key_response, "created_at", None)
14561496
key_data["updated_at"] = getattr(create_key_response, "updated_at", None)
14571497
except Exception as e:

litellm/proxy/management_endpoints/organization_endpoints.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ async def new_organization(
168168

169169
data.budget_id = _budget.budget_id
170170

171+
## Handle Object Permission - MCP, Vector Stores etc.
172+
object_permission_id = await _set_object_permission(
173+
data=data,
174+
prisma_client=prisma_client,
175+
)
176+
171177
"""
172178
Ensure only models that user has access to, are given to org
173179
"""
@@ -189,6 +195,7 @@ async def new_organization(
189195

190196
organization_row = LiteLLM_OrganizationTable(
191197
**data.json(exclude_none=True),
198+
object_permission_id=object_permission_id,
192199
created_by=user_api_key_dict.user_id or litellm_proxy_admin_name,
193200
updated_by=user_api_key_dict.user_id or litellm_proxy_admin_name,
194201
)
@@ -207,6 +214,30 @@ async def new_organization(
207214
return response
208215

209216

217+
async def _set_object_permission(
218+
data: NewOrganizationRequest,
219+
prisma_client: Optional[PrismaClient],
220+
) -> Optional[str]:
221+
"""
222+
Creates the LiteLLM_ObjectPermissionTable record for the organization.
223+
- Handles permissions for vector stores and mcp servers.
224+
225+
Returns the object_permission_id if created, otherwise None.
226+
"""
227+
if prisma_client is None:
228+
return None
229+
230+
if data.object_permission is not None:
231+
created_object_permission = (
232+
await prisma_client.db.litellm_objectpermissiontable.create(
233+
data=data.object_permission.model_dump(exclude_none=True),
234+
)
235+
)
236+
del data.object_permission
237+
return created_object_permission.object_permission_id
238+
return None
239+
240+
210241
@router.patch(
211242
"/organization/update",
212243
tags=["organization management"],

litellm/proxy/management_endpoints/team_endpoints.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,17 @@ async def new_team( # noqa: PLR0915
298298

299299
_model_id = model_dict.id
300300

301+
## Handle Object Permission - MCP, Vector Stores etc.
302+
object_permission_id = await _set_object_permission(
303+
data=data,
304+
prisma_client=prisma_client,
305+
)
306+
301307
## ADD TO TEAM TABLE
302308
complete_team_data = LiteLLM_TeamTable(
303309
**data.json(),
304310
model_id=_model_id,
311+
object_permission_id=object_permission_id,
305312
)
306313

307314
# Set Management Endpoint Metadata Fields
@@ -411,6 +418,30 @@ async def _update_model_table(
411418
return _model_id
412419

413420

421+
async def _set_object_permission(
422+
data: NewTeamRequest,
423+
prisma_client: Optional[PrismaClient],
424+
) -> Optional[str]:
425+
"""
426+
Creates the LiteLLM_ObjectPermissionTable record for the team.
427+
- Handles permissions for vector stores and mcp servers.
428+
429+
Returns the object_permission_id if created, otherwise None.
430+
"""
431+
if prisma_client is None:
432+
return None
433+
434+
if data.object_permission is not None:
435+
created_object_permission = (
436+
await prisma_client.db.litellm_objectpermissiontable.create(
437+
data=data.object_permission.model_dump(exclude_none=True),
438+
)
439+
)
440+
del data.object_permission
441+
return created_object_permission.object_permission_id
442+
return None
443+
444+
414445
def validate_team_org_change(
415446
team: LiteLLM_TeamTable, organization: LiteLLM_OrganizationTable, llm_router: Router
416447
) -> bool:

litellm/proxy/schema.prisma

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ model LiteLLM_UserTable {
155155
model LiteLLM_ObjectPermissionTable {
156156
object_permission_id String @id @default(uuid())
157157
mcp_servers String[] @default([])
158-
158+
vector_stores String[] @default([])
159159
teams LiteLLM_TeamTable[]
160160
verification_tokens LiteLLM_VerificationToken[]
161161
organizations LiteLLM_OrganizationTable[]

litellm/proxy/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2798,6 +2798,8 @@ def handle_exception_on_proxy(e: Exception) -> ProxyException:
27982798
"""
27992799
from fastapi import status
28002800

2801+
verbose_proxy_logger.exception(f"Exception: {e}")
2802+
28012803
if isinstance(e, HTTPException):
28022804
return ProxyException(
28032805
message=getattr(e, "detail", f"error({str(e)})"),

schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ model LiteLLM_UserTable {
155155
model LiteLLM_ObjectPermissionTable {
156156
object_permission_id String @id @default(uuid())
157157
mcp_servers String[] @default([])
158+
vector_stores String[] @default([])
158159
159160
teams LiteLLM_TeamTable[]
160161
verification_tokens LiteLLM_VerificationToken[]

0 commit comments

Comments
 (0)