Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUGFIX] Fix issue with DatabaseRoles not allowed with grants #145

Merged
merged 2 commits into from
Nov 7, 2024
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
26 changes: 26 additions & 0 deletions tests/test_grant.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,29 @@ def test_grant_on_dynamic_tables():
assert future_grant._data.in_name == "SOMEDB.SOMESCHEMA"
assert future_grant._data.in_type == ResourceType.SCHEMA
assert future_grant._data.on_type == ResourceType.DYNAMIC_TABLE


def test_grant_database_role_to_database_role():
database = res.Database(name="somedb")
parent = res.DatabaseRole(name="parent", database=database)
child = res.DatabaseRole(name="child", database=database)
grant = res.RoleGrant(role=child, to_role=parent)
assert grant.role.name == "child"
assert grant.to.name == "parent"


def test_grant_database_role_to_account_role():
database = res.Database(name="somedb")
parent = res.Role(name="parent")
child = res.DatabaseRole(name="child", database=database)
grant = res.RoleGrant(role=child, to_role=parent)
assert grant.role.name == "child"
assert grant.to.name == "parent"


def test_grant_database_role_to_system_role():
database = res.Database(name="somedb")
child = res.DatabaseRole(name="child", database=database)
grant = res.RoleGrant(role=child, to_role="SYSADMIN")
assert grant.role.name == "child"
assert grant.to.name == "SYSADMIN"
13 changes: 7 additions & 6 deletions titan/resources/grant.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@

from ..enums import ParseableEnum, ResourceType
from ..identifiers import FQN, parse_FQN, resource_label_for_type, resource_type_for_label
from ..parse import parse_grant, format_collection_string
from ..parse import format_collection_string, parse_grant
from ..privs import all_privs_for_resource_type
from ..props import FlagProp, IdentifierProp, Props
from ..resource_name import ResourceName
from ..role_ref import RoleRef
from ..scope import AccountScope
from .resource import NamedResource, Resource, ResourcePointer, ResourceSpec
from .role import Role
Expand All @@ -23,7 +24,7 @@ class _Grant(ResourceSpec):
priv: str
on: str
on_type: ResourceType
to: Role
to: RoleRef
grant_option: bool = False
owner: Role = field(default=None, metadata={"fetchable": False})
_privs: list[str] = field(default_factory=list, metadata={"triggers_create": True})
Expand Down Expand Up @@ -242,7 +243,7 @@ class _FutureGrant(ResourceSpec):
on_type: ResourceType
in_type: ResourceType
in_name: ResourceName
to: Role
to: RoleRef
grant_option: bool = False

def __post_init__(self):
Expand Down Expand Up @@ -425,7 +426,7 @@ class _GrantOnAll(ResourceSpec):
on_type: ResourceType
in_type: ResourceType
in_name: ResourceName
to: Role
to: RoleRef
grant_option: bool = False

def __post_init__(self):
Expand Down Expand Up @@ -587,8 +588,8 @@ def grant_on_all_fqn(data: _GrantOnAll):

@dataclass(unsafe_hash=True)
class _RoleGrant(ResourceSpec):
role: Role
to_role: Role = None
role: RoleRef
to_role: RoleRef = None
to_user: User = None

def __post_init__(self):
Expand Down
8 changes: 5 additions & 3 deletions titan/resources/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@
setattr(self, f.name, new_value)
except TypeError as err:
human_readable_classname = self.__class__.__name__[1:]
if issubclass(f.type, Enum):
if isclass(f.type) and issubclass(f.type, Enum):
raise TypeError(
f"Expected {human_readable_classname}.{f.name} to be one of ({', '.join(f.type.__members__.keys())}), got {repr(field_value)} instead"
) from err
Expand Down Expand Up @@ -699,13 +699,15 @@
ResourceType.ROLE,
):
return role_ref
elif isinstance(role_ref, str):
elif isinstance(role_ref, str) or isinstance(role_ref, ResourceName):
return ResourcePointer(name=role_ref, resource_type=infer_role_type_from_name(role_ref))
else:
raise TypeError


def infer_role_type_from_name(name: str) -> ResourceType:
def infer_role_type_from_name(name: Union[str, ResourceName]) -> ResourceType:
if isinstance(name, ResourceName):
name = str(name)

Check warning on line 710 in titan/resources/resource.py

View check run for this annotation

Codecov / codecov/patch

titan/resources/resource.py#L710

Added line #L710 was not covered by tests
if name == "":
return ResourceType.ROLE
identifier = parse_identifier(name, is_db_scoped=True)
Expand Down