Copilot commented on code in PR #11026:
URL: https://github.com/apache/gravitino/pull/11026#discussion_r3216676725
##########
clients/client-python/gravitino/api/authorization/privileges.py:
##########
@@ -169,6 +171,21 @@ class Name(Enum):
RUN_JOB = (0, 1 << 27)
"""The privilege to run a job."""
+ CREATE_VIEW = (0, 1 << 28)
+ """The privilege to create a view."""
+
+ SELECT_VIEW = (0, 1 << 29)
+ """The privilege to select data from a view."""
Review Comment:
For backward compatibility with existing Gravitino deployments/clients,
consider supporting deprecated legacy privilege names that exist in the
server/Java API (e.g., CREATE_MODEL and CREATE_MODEL_VERSION) by adding them as
aliases in Privilege.Name (sharing the same bit values) and mapping them in
Privileges.allow()/deny(). Without this, Privileges.allow("CREATE_MODEL") will
raise IllegalArgumentException even though the privilege name may still appear
in older policies or user code.
##########
clients/client-python/gravitino/api/metadata_object.py:
##########
@@ -56,6 +56,9 @@ class Type(Enum):
MySQL, etc.
"""
+ VIEW = "view"
+ """A view is mapped to the view of relational data sources like Apache
Hive, MySQL, etc."""
+
Review Comment:
Adding MetadataObject.Type.VIEW/FUNCTION here makes them part of the public
type system, but MetadataObjects.of()/parse() and MetadataObjects.parent()
currently don't recognize VIEW/FUNCTION (e.g., name-length/type validation and
parent resolution). This will raise IllegalArgumentException when callers try
to construct securable objects for view/function privileges. Please update
MetadataObjects to support VIEW/FUNCTION (including parent type = SCHEMA and
3-part names) and extend existing unit tests accordingly.
##########
clients/client-python/gravitino/api/authorization/privileges.py:
##########
@@ -218,6 +235,1454 @@ class Condition(Enum):
DENY = "DENY"
-class Privileges:
- # TODO Implement the Privileges class.
- pass
+class GenericPrivilege(Privilege):
+ """Abstract class representing a generic privilege."""
+
+ def __init__(
+ self,
+ condition: Privilege.Condition,
+ name: Privilege.Name,
+ ) -> None:
+ self._condition = condition
+ self._name = name
+
+ def name(self) -> Privilege.Name:
+ return self._name
+
+ def condition(self) -> Privilege.Condition:
+ return self._condition
+
+ def simple_string(self) -> str:
+ return f"{self._condition.name} {self._name.name.lower().replace('_',
' ')}"
+
+ def __hash__(self) -> int:
+ return hash((self._condition, self._name))
+
+ def __eq__(self, value: object) -> bool:
+ if not isinstance(value, GenericPrivilege):
+ return False
+ return self._condition == value._condition and self._name ==
value._name
+
+
+class CreateCatalog(GenericPrivilege):
+ """The privilege to create a catalog."""
+
+ _ALLOW_INSTANCE: Optional[CreateCatalog] = None
+ _DENY_INSTANCE: Optional[CreateCatalog] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The privilege with allow condition.
+ """
+ if CreateCatalog._ALLOW_INSTANCE is None:
+ CreateCatalog._ALLOW_INSTANCE = CreateCatalog(
+ Privilege.Condition.ALLOW, Privilege.Name.CREATE_CATALOG
+ )
+ return CreateCatalog._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+ """
+ if CreateCatalog._DENY_INSTANCE is None:
+ CreateCatalog._DENY_INSTANCE = CreateCatalog(
+ Privilege.Condition.DENY, Privilege.Name.CREATE_CATALOG
+ )
+ return CreateCatalog._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type == MetadataObject.Type.METALAKE
+
+
+class UseCatalog(GenericPrivilege):
+ """The privilege to use a catalog."""
+
+ _ALLOW_INSTANCE: Optional[UseCatalog] = None
+ _DENY_INSTANCE: Optional[UseCatalog] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+ """
+ if UseCatalog._ALLOW_INSTANCE is None:
+ UseCatalog._ALLOW_INSTANCE = UseCatalog(
+ Privilege.Condition.ALLOW, Privilege.Name.USE_CATALOG
+ )
+
+ return UseCatalog._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+ """
+ if UseCatalog._DENY_INSTANCE is None:
+ UseCatalog._DENY_INSTANCE = UseCatalog(
+ Privilege.Condition.DENY, Privilege.Name.USE_CATALOG
+ )
+
+ return UseCatalog._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in [MetadataObject.Type.METALAKE,
MetadataObject.Type.CATALOG]
+
+
+class UseSchema(GenericPrivilege):
+ """The privilege to use a schema."""
+
+ _ALLOW_INSTANCE: Optional[UseSchema] = None
+ _DENY_INSTANCE: Optional[UseSchema] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+ """
+ if UseSchema._ALLOW_INSTANCE is None:
+ UseSchema._ALLOW_INSTANCE = UseSchema(
+ Privilege.Condition.ALLOW, Privilege.Name.USE_SCHEMA
+ )
+
+ return UseSchema._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+ """
+ if UseSchema._DENY_INSTANCE is None:
+ UseSchema._DENY_INSTANCE = UseSchema(
+ Privilege.Condition.DENY, Privilege.Name.USE_SCHEMA
+ )
+
+ return UseSchema._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in Privileges.SCHEMA_SUPPORTED_TYPES
+
+
+class CreateSchema(GenericPrivilege):
+ """Privilege to create a schema."""
+
+ _ALLOW_INSTANCE: Optional[CreateSchema] = None
+ _DENY_INSTANCE: Optional[CreateSchema] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+ """
+ if CreateSchema._ALLOW_INSTANCE is None:
+ CreateSchema._ALLOW_INSTANCE = CreateSchema(
+ Privilege.Condition.ALLOW, Privilege.Name.CREATE_SCHEMA
+ )
+
+ return CreateSchema._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+ """
+ if CreateSchema._DENY_INSTANCE is None:
+ CreateSchema._DENY_INSTANCE = CreateSchema(
+ Privilege.Condition.DENY, Privilege.Name.CREATE_SCHEMA
+ )
+
+ return CreateSchema._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in [MetadataObject.Type.METALAKE,
MetadataObject.Type.CATALOG]
+
+
+class CreateTable(GenericPrivilege):
+ """The privilege to create a table."""
+
+ _ALLOW_INSTANCE: Optional[CreateTable] = None
+ _DENY_INSTANCE: Optional[CreateTable] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+ """
+ if CreateTable._ALLOW_INSTANCE is None:
+ CreateTable._ALLOW_INSTANCE = CreateTable(
+ Privilege.Condition.ALLOW, Privilege.Name.CREATE_TABLE
+ )
+
+ return CreateTable._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+ """
+ if CreateTable._DENY_INSTANCE is None:
+ CreateTable._DENY_INSTANCE = CreateTable(
+ Privilege.Condition.DENY, Privilege.Name.CREATE_TABLE
+ )
+
+ return CreateTable._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in Privileges.SCHEMA_SUPPORTED_TYPES
+
+
+class SelectTable(GenericPrivilege):
+ """
+ Privilege to select table.
+ """
+
+ _ALLOW_INSTANCE: Optional[SelectTable] = None
+ _DENY_INSTANCE: Optional[SelectTable] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+ """
+ if SelectTable._ALLOW_INSTANCE is None:
+ SelectTable._ALLOW_INSTANCE = SelectTable(
+ Privilege.Condition.ALLOW, Privilege.Name.SELECT_TABLE
+ )
+
+ return SelectTable._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+ """
+ if SelectTable._DENY_INSTANCE is None:
+ SelectTable._DENY_INSTANCE = SelectTable(
+ Privilege.Condition.DENY, Privilege.Name.SELECT_TABLE
+ )
+
+ return SelectTable._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in Privileges.TABLE_SUPPORTED_TYPES
+
+
+class ModifyTable(GenericPrivilege):
+ """The privilege to write data to a table or modify the table schema."""
+
+ _ALLOW_INSTANCE: Optional[ModifyTable] = None
+ _DENY_INSTANCE: Optional[ModifyTable] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+ """
+ if ModifyTable._ALLOW_INSTANCE is None:
+ ModifyTable._ALLOW_INSTANCE = ModifyTable(
+ Privilege.Condition.ALLOW, Privilege.Name.MODIFY_TABLE
+ )
+
+ return ModifyTable._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+ """
+ if ModifyTable._DENY_INSTANCE is None:
+ ModifyTable._DENY_INSTANCE = ModifyTable(
+ Privilege.Condition.DENY, Privilege.Name.MODIFY_TABLE
+ )
+
+ return ModifyTable._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in Privileges.TABLE_SUPPORTED_TYPES
+
+
+class CreateFileset(GenericPrivilege):
+ """The privilege to create a fileset."""
+
+ _ALLOW_INSTANCE: Optional[CreateFileset] = None
+ _DENY_INSTANCE: Optional[CreateFileset] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+ """
+ if CreateFileset._ALLOW_INSTANCE is None:
+ CreateFileset._ALLOW_INSTANCE = CreateFileset(
+ Privilege.Condition.ALLOW, Privilege.Name.CREATE_FILESET
+ )
+
+ return CreateFileset._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+ """
+ if CreateFileset._DENY_INSTANCE is None:
+ CreateFileset._DENY_INSTANCE = CreateFileset(
+ Privilege.Condition.DENY, Privilege.Name.CREATE_FILESET
+ )
+
+ return CreateFileset._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in Privileges.SCHEMA_SUPPORTED_TYPES
+
+
+class ReadFileset(GenericPrivilege):
+ """
+ Privilege to read fileset.
+ """
+
+ _ALLOW_INSTANCE: Optional[ReadFileset] = None
+ _DENY_INSTANCE: Optional[ReadFileset] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+ """
+ if ReadFileset._ALLOW_INSTANCE is None:
+ ReadFileset._ALLOW_INSTANCE = ReadFileset(
+ Privilege.Condition.ALLOW, Privilege.Name.READ_FILESET
+ )
+
+ return ReadFileset._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+ """
+ if ReadFileset._DENY_INSTANCE is None:
+ ReadFileset._DENY_INSTANCE = ReadFileset(
+ Privilege.Condition.DENY, Privilege.Name.READ_FILESET
+ )
+
+ return ReadFileset._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in Privileges.FILESET_SUPPORTED_TYPES
+
+
+class WriteFileset(GenericPrivilege):
+ """
+ Privilege to write fileset.
+ """
+
+ _ALLOW_INSTANCE: Optional[WriteFileset] = None
+ _DENY_INSTANCE: Optional[WriteFileset] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+ """
+ if WriteFileset._ALLOW_INSTANCE is None:
+ WriteFileset._ALLOW_INSTANCE = WriteFileset(
+ Privilege.Condition.ALLOW, Privilege.Name.WRITE_FILESET
+ )
+
+ return WriteFileset._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+
+ """
+ if WriteFileset._DENY_INSTANCE is None:
+ WriteFileset._DENY_INSTANCE = WriteFileset(
+ Privilege.Condition.DENY, Privilege.Name.WRITE_FILESET
+ )
+
+ return WriteFileset._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in Privileges.FILESET_SUPPORTED_TYPES
+
+
+class CreateTopic(GenericPrivilege):
+ """The privilege to create a topic."""
+
+ _ALLOW_INSTANCE: Optional[CreateTopic] = None
+ _DENY_INSTANCE: Optional[CreateTopic] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+
+ """
+ if CreateTopic._ALLOW_INSTANCE is None:
+ CreateTopic._ALLOW_INSTANCE = CreateTopic(
+ Privilege.Condition.ALLOW, Privilege.Name.CREATE_TOPIC
+ )
+
+ return CreateTopic._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+
+ """
+ if CreateTopic._DENY_INSTANCE is None:
+ CreateTopic._DENY_INSTANCE = CreateTopic(
+ Privilege.Condition.DENY, Privilege.Name.CREATE_TOPIC
+ )
+
+ return CreateTopic._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in Privileges.SCHEMA_SUPPORTED_TYPES
+
+
+class ConsumeTopic(GenericPrivilege):
+ """
+ Privilege for consuming a topic.
+ """
+
+ _ALLOW_INSTANCE: Optional[ConsumeTopic] = None
+ _DENY_INSTANCE: Optional[ConsumeTopic] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+
+ """
+ if ConsumeTopic._ALLOW_INSTANCE is None:
+ ConsumeTopic._ALLOW_INSTANCE = ConsumeTopic(
+ Privilege.Condition.ALLOW, Privilege.Name.CONSUME_TOPIC
+ )
+
+ return ConsumeTopic._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+
+ """
+ if ConsumeTopic._DENY_INSTANCE is None:
+ ConsumeTopic._DENY_INSTANCE = ConsumeTopic(
+ Privilege.Condition.DENY, Privilege.Name.CONSUME_TOPIC
+ )
+
+ return ConsumeTopic._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in Privileges.TOPIC_SUPPORTED_TYPES
+
+
+class ProduceTopic(GenericPrivilege):
+ """The privilege to produce to a topic."""
+
+ _ALLOW_INSTANCE: Optional[ProduceTopic] = None
+ _DENY_INSTANCE: Optional[ProduceTopic] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+
+ """
+ if ProduceTopic._ALLOW_INSTANCE is None:
+ ProduceTopic._ALLOW_INSTANCE = ProduceTopic(
+ Privilege.Condition.ALLOW, Privilege.Name.PRODUCE_TOPIC
+ )
+
+ return ProduceTopic._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+
+ """
+ if ProduceTopic._DENY_INSTANCE is None:
+ ProduceTopic._DENY_INSTANCE = ProduceTopic(
+ Privilege.Condition.DENY, Privilege.Name.PRODUCE_TOPIC
+ )
+
+ return ProduceTopic._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type in Privileges.TOPIC_SUPPORTED_TYPES
+
+
+class ManageUsers(GenericPrivilege):
+ """The privilege to manage users."""
+
+ _ALLOW_INSTANCE: Optional[ManageUsers] = None
+ _DENY_INSTANCE: Optional[ManageUsers] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+
+ """
+ if ManageUsers._ALLOW_INSTANCE is None:
+ ManageUsers._ALLOW_INSTANCE = ManageUsers(
+ Privilege.Condition.ALLOW, Privilege.Name.MANAGE_USERS
+ )
+ return ManageUsers._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+
+ """
+ if ManageUsers._DENY_INSTANCE is None:
+ ManageUsers._DENY_INSTANCE = ManageUsers(
+ Privilege.Condition.DENY, Privilege.Name.MANAGE_USERS
+ )
+ return ManageUsers._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type == MetadataObject.Type.METALAKE
+
+
+class ManageGroups(GenericPrivilege):
+ """The privilege to manage groups."""
+
+ _ALLOW_INSTANCE: Optional[ManageGroups] = None
+ _DENY_INSTANCE: Optional[ManageGroups] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+
+ """
+ if ManageGroups._ALLOW_INSTANCE is None:
+ ManageGroups._ALLOW_INSTANCE = ManageGroups(
+ Privilege.Condition.ALLOW, Privilege.Name.MANAGE_GROUPS
+ )
+
+ return ManageGroups._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+
+ """
+ if ManageGroups._DENY_INSTANCE is None:
+ ManageGroups._DENY_INSTANCE = ManageGroups(
+ Privilege.Condition.DENY, Privilege.Name.MANAGE_GROUPS
+ )
+
+ return ManageGroups._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type == MetadataObject.Type.METALAKE
+
+
+class CreateRole(GenericPrivilege):
+ """The privilege to create a role."""
+
+ _ALLOW_INSTANCE: Optional[CreateRole] = None
+ _DENY_INSTANCE: Optional[CreateRole] = None
+
+ @staticmethod
+ def allow() -> Privilege:
+ """
+ Retrieve the instance with allow condition of the privilege.
+
+ Returns:
+ Privilege: The instance with allow condition of the privilege.
+
+ """
+ if CreateRole._ALLOW_INSTANCE is None:
+ CreateRole._ALLOW_INSTANCE = CreateRole(
+ Privilege.Condition.ALLOW, Privilege.Name.CREATE_ROLE
+ )
+
+ return CreateRole._ALLOW_INSTANCE
+
+ @staticmethod
+ def deny() -> Privilege:
+ """
+ Retrieve the instance with deny condition of the privilege.
+
+ Returns:
+ Privilege: The instance with deny condition of the privilege.
+
+ """
+ if CreateRole._DENY_INSTANCE is None:
+ CreateRole._DENY_INSTANCE = CreateRole(
+ Privilege.Condition.DENY, Privilege.Name.CREATE_ROLE
+ )
+
+ return CreateRole._DENY_INSTANCE
+
+ def can_bind_to(self, obj_type: MetadataObject.Type) -> bool:
+ return obj_type == MetadataObject.Type.METALAKE
+
+
+class ManageGrants(GenericPrivilege):
+ """
+ The privilege to grant or revoke privileges on securable objects. If bound
on the metalake,
+ we can grant or revoke the role for users or groups.Unlike most privileges,
+ this can be bound at any level of the object hierarchy — METALAKE,
+ CATALOG, SCHEMA, TABLE, VIEW, TOPIC, FILESET, or MODEL.
Review Comment:
ManageGrants docstring is out of sync with the actual supported binding
types: Privileges.MANAGE_GRANTS_SUPPORTED_TYPES includes FUNCTION, but the
docstring list ends at MODEL. Also, "groups.Unlike" is missing a space. Please
update the docstring to include FUNCTION and fix the spacing/grammar so the
documentation matches behavior.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]