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-ebcc021
WEAVIATE_128: 1.28.0-rc.0-d00c5ca
jobs:
lint-and-format:
name: Run Linter and Formatter
Expand Down
7 changes: 7 additions & 0 deletions integration/test_rbac.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,5 +301,12 @@ def test_multiple_permissions(client_factory: ClientFactory) -> None:
assert len(role.data_permissions) == 2
assert role.data_permissions[0].action == Actions.Data.CREATE
assert role.data_permissions[1].action == Actions.Data.UPDATE

assert client.roles.has_permission(
permission=role.collections_permissions[0], role=role_name
)
assert client.roles.has_permission(
permission=required_permissions[1][0], role=role_name
)
finally:
client.roles.delete(role_name)
50 changes: 50 additions & 0 deletions weaviate/rbac/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,41 +221,91 @@ class CollectionsPermission:
collection: str
action: CollectionsAction

def _to_weaviate(self) -> WeaviatePermission:
return {
"action": self.action,
"collections": {
"collection": self.collection,
"tenant": "*",
},
}


@dataclass
class DataPermission:
collection: str
action: DataAction

def _to_weaviate(self) -> WeaviatePermission:
return {
"action": self.action,
"data": {
"collection": self.collection,
"object": "*",
"tenant": "*",
},
}


@dataclass
class RolesPermission:
role: str
action: RolesAction

def _to_weaviate(self) -> WeaviatePermission:
return {
"action": self.action,
"roles": {
"role": self.role,
},
}


@dataclass
class UsersPermission:
action: UsersAction

def _to_weaviate(self) -> WeaviatePermission:
return {"action": self.action}


@dataclass
class ClusterPermission:
action: ClusterAction

def _to_weaviate(self) -> WeaviatePermission:
return {"action": self.action}


@dataclass
class BackupsPermission:
collection: str
action: BackupsAction

def _to_weaviate(self) -> WeaviatePermission:
return {
"action": self.action,
"backups": {
"collection": self.collection,
},
}


@dataclass
class NodesPermission:
collection: Optional[str]
verbosity: Verbosity
action: NodesAction

def _to_weaviate(self) -> WeaviatePermission:
return {
"action": self.action,
"nodes": {
"collection": self.collection or "*",
"verbosity": self.verbosity,
},
}


PermissionsOutputType = Union[
ClusterPermission,
Expand Down
26 changes: 26 additions & 0 deletions weaviate/rbac/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from weaviate.connect.v4 import _ExpectedStatusCodes
from weaviate.rbac.models import (
_Permission,
PermissionsOutputType,
PermissionsInputType,
Role,
User,
Expand Down Expand Up @@ -129,6 +130,17 @@ async def _remove_permissions(self, permissions: List[WeaviatePermission], role:
status_codes=_ExpectedStatusCodes(ok_in=[200], error="Remove permissions"),
)

async def _has_permission(self, permission: WeaviatePermission, role: str) -> bool:
path = f"/authz/roles/{role}/has-permission"

res = await self._connection.post(
path,
weaviate_object=permission,
error_msg="Could not check permission",
status_codes=_ExpectedStatusCodes(ok_in=[200], error="Check permission"),
)
return cast(bool, res.json())


class _RolesAsync(_RolesBase):
def __user_from_weaviate_user(self, user: str) -> User:
Expand Down Expand Up @@ -287,6 +299,20 @@ async def remove_permissions(
role_name,
)

async def has_permission(
self, *, permission: Union[_Permission, PermissionsOutputType], role: str
) -> bool:
"""Check if a role has a specific permission.

Args:
permission: The permission to check.
role: The role to check the permission for.

Returns:
True if the role has the permission, False otherwise.
"""
return await self._has_permission(permission._to_weaviate(), role)


def _flatten_permissions(permissions: PermissionsInputType) -> List[_Permission]:
if isinstance(permissions, _Permission):
Expand Down
11 changes: 10 additions & 1 deletion weaviate/rbac/sync.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from typing import Dict, List, Optional, Union

from weaviate.rbac.models import PermissionsInputType, Role, User
from weaviate.rbac.models import (
_Permission,
PermissionsOutputType,
PermissionsInputType,
Role,
User,
)
from weaviate.rbac.roles import _RolesBase

class _Roles(_RolesBase):
Expand All @@ -16,3 +22,6 @@ class _Roles(_RolesBase):
def revoke_from_user(self, *, role_names: Union[str, List[str]], user: str) -> None: ...
def add_permissions(self, *, permissions: PermissionsInputType, role_name: str) -> None: ...
def remove_permissions(self, *, permissions: PermissionsInputType, role_name: str) -> None: ...
def has_permission(
self, *, permission: Union[_Permission, PermissionsOutputType], role: str
) -> bool: ...
Loading