Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ env:
WEAVIATE_125: 1.25.24
WEAVIATE_126: 1.26.8
WEAVIATE_127: 1.27.1
WEAVIATE_128: 1.28.0-rc.0
WEAVIATE_128: 1.28.0-rc.0-ebcc021
jobs:
lint-and-format:
name: Run Linter and Formatter
Expand Down
40 changes: 40 additions & 0 deletions mock_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from weaviate.connect.base import ConnectionParams, ProtocolParams
from weaviate.proto.v1 import (
batch_pb2,
batch_delete_pb2,
properties_pb2,
tenants_pb2,
search_get_pb2,
Expand Down Expand Up @@ -310,3 +311,42 @@ def retries(
service = MockRetriesWeaviateService()
weaviate_pb2_grpc.add_WeaviateServicer_to_server(service, start_grpc_server)
return weaviate_client.collections.get("RetriesCollection"), service


class MockForbiddenWeaviateService(weaviate_pb2_grpc.WeaviateServicer):
def Search(
self, request: search_get_pb2.SearchRequest, context: grpc.ServicerContext
) -> search_get_pb2.SearchReply:
context.set_code(grpc.StatusCode.PERMISSION_DENIED)
context.set_details("Permission denied")
return search_get_pb2.SearchReply()

def TenantsGet(
self, request: tenants_pb2.TenantsGetRequest, context: ServicerContext
) -> tenants_pb2.TenantsGetReply:
context.set_code(grpc.StatusCode.PERMISSION_DENIED)
context.set_details("Permission denied")
return tenants_pb2.TenantsGetReply()

def BatchObjects(
self, request: batch_pb2.BatchObjectsRequest, context: grpc.ServicerContext
) -> batch_pb2.BatchObjectsReply:
context.set_code(grpc.StatusCode.PERMISSION_DENIED)
context.set_details("Permission denied")
return batch_pb2.BatchObjectsReply()

def BatchDelete(
self, request: batch_delete_pb2.BatchDeleteRequest, context: grpc.ServicerContext
) -> batch_delete_pb2.BatchDeleteReply:
context.set_code(grpc.StatusCode.PERMISSION_DENIED)
context.set_details("Permission denied")
return batch_delete_pb2.BatchDeleteReply()


@pytest.fixture(scope="function")
def forbidden(
weaviate_client: weaviate.WeaviateClient, start_grpc_server: grpc.Server
) -> weaviate.collections.Collection:
service = MockForbiddenWeaviateService()
weaviate_pb2_grpc.add_WeaviateServicer_to_server(service, start_grpc_server)
return weaviate_client.collections.get("ForbiddenCollection")
14 changes: 14 additions & 0 deletions mock_tests/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,3 +460,17 @@ def test_grpc_retry_logic(
assert len(tenants) == 1
assert tenants[0].name == "tenant1"
assert service.tenants_count == 2


def test_grpc_forbidden_exception(forbidden: weaviate.collections.Collection) -> None:
with pytest.raises(weaviate.exceptions.InsufficientPermissionsError):
forbidden.query.fetch_objects()

with pytest.raises(weaviate.exceptions.InsufficientPermissionsError):
forbidden.tenants.get()

with pytest.raises(weaviate.exceptions.InsufficientPermissionsError):
forbidden.data.delete_many(where=wvc.query.Filter.by_property("name").equal("test"))

with pytest.raises(weaviate.exceptions.InsufficientPermissionsError):
forbidden.data.insert_many([{"name": "test"}])
6 changes: 4 additions & 2 deletions weaviate/collections/batch/grpc_batch_delete.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
from weaviate.collections.classes.config import ConsistencyLevel
from weaviate.collections.classes.filters import _Filters
from weaviate.collections.filters import _FilterToGRPC
from weaviate.collections.grpc.shared import _BaseGRPC
from weaviate.collections.grpc.shared import _BaseGRPC, PERMISSION_DENIED
from weaviate.collections.queries.base import _WeaviateUUIDInt
from weaviate.connect import ConnectionV4
from weaviate.exceptions import WeaviateDeleteManyError
from weaviate.exceptions import WeaviateDeleteManyError, InsufficientPermissionsError
from weaviate.proto.v1 import batch_delete_pb2


Expand Down Expand Up @@ -62,4 +62,6 @@ async def batch_delete(
)

except AioRpcError as e:
if e.code().name == PERMISSION_DENIED:
raise InsufficientPermissionsError(e)
raise WeaviateDeleteManyError(str(e))
5 changes: 4 additions & 1 deletion weaviate/collections/batch/grpc_batch_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
from weaviate.collections.classes.config import ConsistencyLevel
from weaviate.collections.classes.internal import ReferenceToMulti, ReferenceInputs
from weaviate.collections.classes.types import GeoCoordinate, PhoneNumber
from weaviate.collections.grpc.shared import _BaseGRPC
from weaviate.collections.grpc.shared import _BaseGRPC, PERMISSION_DENIED
from weaviate.connect import ConnectionV4
from weaviate.exceptions import (
WeaviateBatchError,
WeaviateInsertInvalidPropertyError,
WeaviateInsertManyAllFailedError,
WeaviateInvalidInputError,
InsufficientPermissionsError,
)
from weaviate.proto.v1 import batch_pb2, base_pb2
from weaviate.util import _datetime_to_string, _get_vector_v4
Expand Down Expand Up @@ -152,6 +153,8 @@ async def __send_batch(
objects[result.index] = result.error
return objects
except AioRpcError as e:
if e.code().name == PERMISSION_DENIED:
raise InsufficientPermissionsError(e)
raise WeaviateBatchError(str(e)) from e

def __translate_properties_from_python_to_grpc(
Expand Down
9 changes: 7 additions & 2 deletions weaviate/collections/grpc/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@
)
from weaviate.collections.filters import _FilterToGRPC
from weaviate.collections.grpc.retry import _Retry
from weaviate.collections.grpc.shared import _BaseGRPC
from weaviate.collections.grpc.shared import _BaseGRPC, PERMISSION_DENIED
from weaviate.connect import ConnectionV4
from weaviate.exceptions import (
InsufficientPermissionsError,
WeaviateQueryError,
WeaviateUnsupportedFeatureError,
WeaviateInvalidInputError,
Expand Down Expand Up @@ -810,7 +811,11 @@ async def __call(self, request: search_get_pb2.SearchRequest) -> search_get_pb2.
timeout=self._connection.timeout_config.query,
)
return cast(search_get_pb2.SearchReply, res)
except (AioRpcError, WeaviateRetryError) as e:
except AioRpcError as e:
if e.code().name == PERMISSION_DENIED:
raise InsufficientPermissionsError(e)
raise WeaviateQueryError(str(e), "GRPC search") # pyright: ignore
except WeaviateRetryError as e:
raise WeaviateQueryError(str(e), "GRPC search") # pyright: ignore

def _metadata_to_grpc(self, metadata: _MetadataQuery) -> search_get_pb2.MetadataRequest:
Expand Down
2 changes: 2 additions & 0 deletions weaviate/collections/grpc/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from weaviate.connect import ConnectionV4
from weaviate.proto.v1 import base_pb2

PERMISSION_DENIED = "PERMISSION_DENIED"


class _BaseGRPC:
def __init__(
Expand Down
6 changes: 4 additions & 2 deletions weaviate/collections/grpc/tenants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from weaviate.collections.classes.config import ConsistencyLevel
from weaviate.collections.classes.tenants import TenantActivityStatus
from weaviate.collections.grpc.retry import _Retry
from weaviate.collections.grpc.shared import _BaseGRPC
from weaviate.collections.grpc.shared import _BaseGRPC, PERMISSION_DENIED
from weaviate.connect import ConnectionV4
from weaviate.exceptions import WeaviateTenantGetError
from weaviate.exceptions import WeaviateTenantGetError, InsufficientPermissionsError
from weaviate.proto.v1 import tenants_pb2


Expand Down Expand Up @@ -38,6 +38,8 @@ async def get(self, names: Optional[Sequence[str]]) -> tenants_pb2.TenantsGetRep
timeout=self._connection.timeout_config.query,
)
except AioRpcError as e:
if e.code().name == PERMISSION_DENIED:
raise InsufficientPermissionsError(e)
raise WeaviateTenantGetError(str(e)) from e

return cast(tenants_pb2.TenantsGetReply, res)
Expand Down
Loading