mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 01:25:21 +00:00
Small refactor, additional tests
This commit is contained in:
parent
d1fa9596b8
commit
078b8f5399
@ -40,7 +40,7 @@ GRANT [ON CLUSTER cluster_name] role [,...] TO {user | another_role | CURRENT_US
|
||||
## Синтаксис присвоения текущих привилегий {#grant-current-grants-syntax}
|
||||
|
||||
```sql
|
||||
GRANT [ON CLUSTER cluster_name] privilege[(column_name [,...])] [,...] ON {db.table|db.*|*.*|table|*} TO {user | role | CURRENT_USER} [,...] [WITH GRANT OPTION] [WITH REPLACE OPTION]
|
||||
GRANT CURRENT GRANTS[(privilege[(column_name [,...])] [,...] ON {db.table|db.*|*.*|table|*})] TO {user | role | CURRENT_USER} [,...] [WITH GRANT OPTION] [WITH REPLACE OPTION]
|
||||
```
|
||||
|
||||
- `privilege` — Тип привилегии
|
||||
|
@ -334,14 +334,22 @@ namespace
|
||||
template <typename T>
|
||||
void grantCurrentGrantsTemplate(
|
||||
T & grantee,
|
||||
const AccessRightsElements & elements_to_grant,
|
||||
const AccessRightsElements & elements_to_revoke,
|
||||
std::shared_ptr<const ContextAccess> current_user_access,
|
||||
bool grant_option)
|
||||
const AccessRights & rights_to_grant,
|
||||
const AccessRightsElements & elements_to_revoke)
|
||||
{
|
||||
if (!elements_to_revoke.empty())
|
||||
grantee.access.revoke(elements_to_revoke);
|
||||
|
||||
grantee.access.makeUnion(rights_to_grant);
|
||||
}
|
||||
|
||||
/// Grants current user's grants with grant options to specified user.
|
||||
void grantCurrentGrants(
|
||||
IAccessEntity & grantee,
|
||||
const AccessRightsElements & elements_to_grant,
|
||||
const AccessRightsElements & elements_to_revoke,
|
||||
std::shared_ptr<const ContextAccess> current_user_access)
|
||||
{
|
||||
/// We need to collect all current user's grant and filter them by grant option.
|
||||
AccessRightsElements current_user_grantable_elements;
|
||||
auto available_grant_elements = current_user_access->getAccessRights()->getElements();
|
||||
@ -360,36 +368,13 @@ namespace
|
||||
current_user_rights.grant(element);
|
||||
}
|
||||
|
||||
/// If elements_to_grant was not specified it will grant all available for user grants.
|
||||
/// Otherwise, we will intersect available grants with given set.
|
||||
if (elements_to_grant.empty())
|
||||
{
|
||||
if (!grant_option)
|
||||
current_user_rights.revokeGrantOption(AccessType::ALL);
|
||||
AccessRights new_rights(elements_to_grant);
|
||||
new_rights.makeIntersection(current_user_rights);
|
||||
|
||||
grantee.access.makeUnion(current_user_rights);
|
||||
}
|
||||
else
|
||||
{
|
||||
AccessRights new_rights(elements_to_grant);
|
||||
new_rights.makeIntersection(current_user_rights);
|
||||
|
||||
grantee.access.makeUnion(new_rights);
|
||||
}
|
||||
}
|
||||
|
||||
/// Grants current user's grants with grant options to specified user.
|
||||
void grantCurrentGrants(
|
||||
IAccessEntity & grantee,
|
||||
const AccessRightsElements & elements_to_grant,
|
||||
const AccessRightsElements & elements_to_revoke,
|
||||
std::shared_ptr<const ContextAccess> current_user_access,
|
||||
bool grant_option)
|
||||
{
|
||||
if (auto * user = typeid_cast<User *>(&grantee))
|
||||
grantCurrentGrantsTemplate(*user, elements_to_grant, elements_to_revoke, current_user_access, grant_option);
|
||||
grantCurrentGrantsTemplate(*user, new_rights, elements_to_revoke);
|
||||
else if (auto * role = typeid_cast<Role *>(&grantee))
|
||||
grantCurrentGrantsTemplate(*role, elements_to_grant, elements_to_revoke, current_user_access, grant_option);
|
||||
grantCurrentGrantsTemplate(*role, new_rights, elements_to_revoke);
|
||||
}
|
||||
|
||||
/// Updates grants of a specified user or role.
|
||||
@ -465,7 +450,7 @@ BlockIO InterpreterGrantQuery::execute()
|
||||
{
|
||||
auto clone = entity->clone();
|
||||
if (query.current_grants)
|
||||
grantCurrentGrants(*clone, elements_to_grant, elements_to_revoke, current_user_access, query.with_grant_option);
|
||||
grantCurrentGrants(*clone, elements_to_grant, elements_to_revoke, current_user_access);
|
||||
else
|
||||
updateGrantedAccessRightsAndRoles(*clone, elements_to_grant, elements_to_revoke, roles_to_grant, roles_to_revoke, query.admin_option);
|
||||
return clone;
|
||||
|
@ -27,7 +27,6 @@ public:
|
||||
bool replace_access = false;
|
||||
bool replace_granted_roles = false;
|
||||
bool current_grants = false;
|
||||
bool with_grant_option = false;
|
||||
|
||||
std::shared_ptr<ASTRolesOrUsersSet> grantees;
|
||||
|
||||
|
@ -296,6 +296,11 @@ bool ParserGrantQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
if (!ParserToken(TokenType::ClosingRoundBracket).ignore(pos, expected))
|
||||
return false;
|
||||
}
|
||||
|
||||
/// If no elements were specified it will grant all available for user grants.
|
||||
/// Using `.size() == 0` because `.empty()` is overridden and returns true for NONE elements.
|
||||
if (elements.size() == 0) // NOLINT
|
||||
elements.emplace_back(AccessType::ALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -370,7 +375,6 @@ bool ParserGrantQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
query->replace_access = replace_access;
|
||||
query->replace_granted_roles = replace_role;
|
||||
query->current_grants = current_grants;
|
||||
query->with_grant_option = grant_option;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -20,6 +20,9 @@ def start_cluster():
|
||||
instance.query(
|
||||
"CREATE TABLE test.table(x UInt32, y UInt32) ENGINE = MergeTree ORDER BY tuple()"
|
||||
)
|
||||
instance.query(
|
||||
"CREATE TABLE test.table2(x UInt32, y UInt32) ENGINE = MergeTree ORDER BY tuple()"
|
||||
)
|
||||
instance.query("INSERT INTO test.table VALUES (1,5), (2,10)")
|
||||
|
||||
yield cluster
|
||||
@ -608,19 +611,29 @@ def test_grant_current_grants():
|
||||
["GRANT CREATE TABLE, CREATE VIEW ON test.* TO C"]
|
||||
)
|
||||
|
||||
instance.query("DROP USER IF EXISTS C")
|
||||
instance.query("CREATE USER C")
|
||||
instance.query("GRANT CURRENT GRANTS(NONE ON *.*) TO C", user="A")
|
||||
assert instance.query("SHOW GRANTS FOR C") == TSV([])
|
||||
|
||||
|
||||
def test_grant_current_grants_with_partial_revoke():
|
||||
instance.query("CREATE USER A")
|
||||
instance.query("GRANT CREATE TABLE ON *.* TO A")
|
||||
instance.query("REVOKE CREATE TABLE ON test.* FROM A")
|
||||
instance.query("GRANT CREATE TABLE ON test.table TO A WITH GRANT OPTION")
|
||||
instance.query("GRANT SELECT ON *.* TO A WITH GRANT OPTION")
|
||||
instance.query("REVOKE SELECT ON test.* FROM A")
|
||||
instance.query("GRANT SELECT ON test.table TO A WITH GRANT OPTION")
|
||||
instance.query("GRANT SELECT ON test.table2 TO A")
|
||||
|
||||
assert instance.query("SHOW GRANTS FOR A") == TSV(
|
||||
[
|
||||
"GRANT CREATE TABLE ON *.* TO A",
|
||||
"GRANT SELECT ON *.* TO A WITH GRANT OPTION",
|
||||
"REVOKE SELECT ON test.* FROM A",
|
||||
"GRANT SELECT ON test.table TO A WITH GRANT OPTION",
|
||||
"REVOKE SELECT, CREATE TABLE ON test.* FROM A",
|
||||
"GRANT SELECT, CREATE TABLE ON test.table TO A WITH GRANT OPTION",
|
||||
"GRANT SELECT ON test.table2 TO A",
|
||||
]
|
||||
)
|
||||
|
||||
@ -630,7 +643,29 @@ def test_grant_current_grants_with_partial_revoke():
|
||||
[
|
||||
"GRANT SELECT ON *.* TO B",
|
||||
"REVOKE SELECT ON test.* FROM B",
|
||||
"GRANT SELECT ON test.table TO B",
|
||||
"GRANT SELECT, CREATE TABLE ON test.table TO B",
|
||||
]
|
||||
)
|
||||
|
||||
instance.query("DROP USER IF EXISTS B")
|
||||
instance.query("CREATE USER B")
|
||||
instance.query("GRANT CURRENT GRANTS TO B WITH GRANT OPTION", user="A")
|
||||
assert instance.query("SHOW GRANTS FOR B") == TSV(
|
||||
[
|
||||
"GRANT SELECT ON *.* TO B WITH GRANT OPTION",
|
||||
"REVOKE SELECT ON test.* FROM B",
|
||||
"GRANT SELECT, CREATE TABLE ON test.table TO B WITH GRANT OPTION",
|
||||
]
|
||||
)
|
||||
|
||||
instance.query("DROP USER IF EXISTS C")
|
||||
instance.query("CREATE USER C")
|
||||
instance.query("GRANT SELECT ON test.* TO B")
|
||||
instance.query("GRANT CURRENT GRANTS TO C", user="B")
|
||||
assert instance.query("SHOW GRANTS FOR C") == TSV(
|
||||
[
|
||||
"GRANT SELECT ON *.* TO C",
|
||||
"GRANT CREATE TABLE ON test.table TO C",
|
||||
]
|
||||
)
|
||||
|
||||
@ -660,3 +695,18 @@ def test_current_grants_override():
|
||||
"GRANT SELECT ON test.table TO B",
|
||||
]
|
||||
)
|
||||
|
||||
instance.query("DROP USER IF EXISTS B")
|
||||
instance.query("CREATE USER B")
|
||||
instance.query("GRANT SELECT ON test.table TO B")
|
||||
assert instance.query("SHOW GRANTS FOR B") == TSV(
|
||||
["GRANT SELECT ON test.table TO B"]
|
||||
)
|
||||
|
||||
instance.query("GRANT CURRENT GRANTS TO B WITH REPLACE OPTION", user="A")
|
||||
assert instance.query("SHOW GRANTS FOR B") == TSV(
|
||||
[
|
||||
"GRANT SELECT ON *.* TO B",
|
||||
"REVOKE SELECT ON test.* FROM B",
|
||||
]
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user