diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index 66a3a12412..d63575200d 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -1071,7 +1071,7 @@ async def chat_completion( # Check if user has access to the model if not BYPASS_MODEL_ACCESS_CONTROL and (user.role != 'admin' or not BYPASS_ADMIN_ACCESS_CONTROL): try: - await check_model_access(user, model) + await check_model_access(user, model, model_info=model_info) except Exception as e: raise e else: diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index a5b2261b14..79ea1030a2 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -428,7 +428,7 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) return models -async def check_model_access(user, model, db=None): +async def check_model_access(user, model, model_info=None, db=None): if model.get('arena'): meta = model.get('info', {}).get('meta', {}) access_grants = meta.get('access_grants', []) @@ -440,23 +440,35 @@ async def check_model_access(user, model, db=None): ): raise Exception('Model not found') else: - model_info = await Models.get_model_by_id(model.get('id'), db=db) + # Callers that already fetched the row (chat completion entry) pass it in + if model_info is None or model_info.id != model.get('id'): + model_info = await Models.get_model_by_id(model.get('id'), db=db) if not model_info: raise Exception('Model not found') - elif not ( + + # One group-membership fetch shared by the direct check and every + # base-model hop; skipped when no check below needs it. + user_group_ids = None + if user.id != model_info.user_id or model_info.base_model_id: + user_group_ids = {group.id for group in await Groups.get_groups_by_member_id(user.id, db=db)} + + if not ( user.id == model_info.user_id or await AccessGrants.has_access( user_id=user.id, resource_type='model', resource_id=model_info.id, permission='read', + user_group_ids=user_group_ids, db=db, ) ): raise Exception('Model not found') # Enforce access on chained base models - if not await has_base_model_access(user.id, model_info, user_role=user.role, db=db): + if not await has_base_model_access( + user.id, model_info, user_role=user.role, user_group_ids=user_group_ids, db=db + ): raise Exception('Model not found')