Solve pr issues

This commit is contained in:
pufit 2023-04-12 20:28:17 -04:00
parent 078b8f5399
commit aa0f3bc994
3 changed files with 60 additions and 23 deletions

View File

@ -346,11 +346,21 @@ namespace
/// 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)
const AccessRights & new_rights,
const AccessRightsElements & elements_to_revoke)
{
if (auto * user = typeid_cast<User *>(&grantee))
grantCurrentGrantsTemplate(*user, new_rights, elements_to_revoke);
else if (auto * role = typeid_cast<Role *>(&grantee))
grantCurrentGrantsTemplate(*role, new_rights, elements_to_revoke);
}
/// Calculates all available rights to grant with current user intersection.
void calculateCurrentGrantRightsWithIntersection(
AccessRights & rights,
std::shared_ptr<const ContextAccess> current_user_access,
const AccessRightsElements & elements_to_grant)
{
/// 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();
std::copy_if(
@ -368,13 +378,8 @@ namespace
current_user_rights.grant(element);
}
AccessRights new_rights(elements_to_grant);
new_rights.makeIntersection(current_user_rights);
if (auto * user = typeid_cast<User *>(&grantee))
grantCurrentGrantsTemplate(*user, new_rights, elements_to_revoke);
else if (auto * role = typeid_cast<Role *>(&grantee))
grantCurrentGrantsTemplate(*role, new_rights, elements_to_revoke);
rights.grant(elements_to_grant);
rights.makeIntersection(current_user_rights);
}
/// Updates grants of a specified user or role.
@ -445,12 +450,16 @@ BlockIO InterpreterGrantQuery::execute()
if (need_check_grantees_are_allowed)
current_user_access->checkGranteesAreAllowed(grantees);
AccessRights new_rights;
if (query.current_grants)
calculateCurrentGrantRightsWithIntersection(new_rights, current_user_access, elements_to_grant);
/// Update roles and users listed in `grantees`.
auto update_func = [&](const AccessEntityPtr & entity) -> AccessEntityPtr
{
auto clone = entity->clone();
if (query.current_grants)
grantCurrentGrants(*clone, elements_to_grant, elements_to_revoke, current_user_access);
grantCurrentGrants(*clone, new_rights, elements_to_revoke);
else
updateGrantedAccessRightsAndRoles(*clone, elements_to_grant, elements_to_revoke, roles_to_grant, roles_to_revoke, query.admin_option);
return clone;

View File

@ -295,14 +295,33 @@ 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.
/// Specifically, this should handle `GRANT CURRENT GRANTS() ...`
if (elements.size() == 0) // NOLINT
elements.emplace_back(AccessType::ALL);
}
else
{
AccessRightsElement default_element(AccessType::ALL);
if (!ParserKeyword{"ON"}.ignore(pos, expected))
return false;
String database_name, table_name;
bool any_database = false, any_table = false;
if (!parseDatabaseAndTableNameOrAsterisks(pos, expected, database_name, any_database, table_name, any_table))
return false;
default_element.any_database = any_database;
default_element.database = database_name;
default_element.any_table = any_table;
default_element.table = table_name;
elements.push_back(std::move(default_element));
}
}
else
{
if (!parseElementsWithoutOptions(pos, expected, elements) && !parseRoles(pos, expected, is_revoke, attach_mode, roles))
return false;

View File

@ -600,7 +600,7 @@ def test_grant_current_grants():
)
instance.query("CREATE USER B")
instance.query("GRANT CURRENT GRANTS TO B", user="A")
instance.query("GRANT CURRENT GRANTS ON *.* TO B", user="A")
assert instance.query("SHOW GRANTS FOR B") == TSV(
["GRANT SELECT, CREATE TABLE, CREATE VIEW ON test.* TO B"]
)
@ -638,7 +638,7 @@ def test_grant_current_grants_with_partial_revoke():
)
instance.query("CREATE USER B")
instance.query("GRANT CURRENT GRANTS TO B", user="A")
instance.query("GRANT CURRENT GRANTS ON *.* TO B", user="A")
assert instance.query("SHOW GRANTS FOR B") == TSV(
[
"GRANT SELECT ON *.* TO B",
@ -649,7 +649,7 @@ def test_grant_current_grants_with_partial_revoke():
instance.query("DROP USER IF EXISTS B")
instance.query("CREATE USER B")
instance.query("GRANT CURRENT GRANTS TO B WITH GRANT OPTION", user="A")
instance.query("GRANT CURRENT GRANTS ON *.* TO B WITH GRANT OPTION", user="A")
assert instance.query("SHOW GRANTS FOR B") == TSV(
[
"GRANT SELECT ON *.* TO B WITH GRANT OPTION",
@ -661,7 +661,7 @@ def test_grant_current_grants_with_partial_revoke():
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")
instance.query("GRANT CURRENT GRANTS ON *.* TO C", user="B")
assert instance.query("SHOW GRANTS FOR C") == TSV(
[
"GRANT SELECT ON *.* TO C",
@ -669,6 +669,15 @@ def test_grant_current_grants_with_partial_revoke():
]
)
instance.query("DROP USER IF EXISTS B")
instance.query("CREATE USER B")
instance.query("GRANT CURRENT GRANTS ON test.* TO B WITH GRANT OPTION", user="A")
assert instance.query("SHOW GRANTS FOR B") == TSV(
[
"GRANT SELECT, CREATE TABLE ON test.table TO B WITH GRANT OPTION",
]
)
def test_current_grants_override():
instance.query("CREATE USER A")
@ -687,7 +696,7 @@ def test_current_grants_override():
["GRANT SELECT ON test.table TO B"]
)
instance.query("GRANT CURRENT GRANTS TO B", user="A")
instance.query("GRANT CURRENT GRANTS ON *.* TO B", user="A")
assert instance.query("SHOW GRANTS FOR B") == TSV(
[
"GRANT SELECT ON *.* TO B",
@ -703,7 +712,7 @@ def test_current_grants_override():
["GRANT SELECT ON test.table TO B"]
)
instance.query("GRANT CURRENT GRANTS TO B WITH REPLACE OPTION", user="A")
instance.query("GRANT CURRENT GRANTS ON *.* TO B WITH REPLACE OPTION", user="A")
assert instance.query("SHOW GRANTS FOR B") == TSV(
[
"GRANT SELECT ON *.* TO B",