mirror of
https://github.com/ansible-collections/community.mysql.git
synced 2025-04-18 16:31:26 -07:00
mysql_user: add proper handling of INSERT, UPDATE, REFERENCES on columns (#107)
* mysql_user: add proper handling of INSERT, UPDATE, REFERENCES on columns * Add changelog fragment * fix sanity * fix CI * fix sanity * fix CI * make the assertion fairer * Improve
This commit is contained in:
parent
2694464ffb
commit
979588e2cd
4 changed files with 127 additions and 40 deletions
|
@ -769,15 +769,12 @@ def privileges_get(cursor, user, host):
|
|||
privileges = res.group(1).split(",")
|
||||
privileges = [pick(x.strip()) for x in privileges]
|
||||
|
||||
# Handle cases when there's GRANT SELECT (colA, ...) in privileges.
|
||||
# Handle cases when there's privs like GRANT SELECT (colA, ...) in privs.
|
||||
# To this point, the privileges list can look like
|
||||
# ['SELECT (`A`', '`B`)', 'INSERT'] that is incorrect (SELECT statement is splitted).
|
||||
# Columns should also be sorted to compare it with desired privileges later.
|
||||
# Determine if there's a case similar to the above:
|
||||
start, end = has_select_on_col(privileges)
|
||||
# If not, either start and end will be None
|
||||
if start is not None:
|
||||
privileges = handle_select_on_col(privileges, start, end)
|
||||
privileges = normalize_col_grants(privileges)
|
||||
|
||||
if "WITH GRANT OPTION" in res.group(7):
|
||||
privileges.append('GRANT')
|
||||
|
@ -788,7 +785,23 @@ def privileges_get(cursor, user, host):
|
|||
return output
|
||||
|
||||
|
||||
def has_select_on_col(privileges):
|
||||
def normalize_col_grants(privileges):
|
||||
"""Fix and sort grants on columns in privileges list
|
||||
|
||||
Make ['SELECT (A, B)', 'INSERT (A, B)', 'DETELE']
|
||||
from ['SELECT (A', 'B)', 'INSERT (B', 'A)', 'DELETE'].
|
||||
See unit tests in tests/unit/plugins/modules/test_mysql_user.py
|
||||
"""
|
||||
for grant in ('SELECT', 'UPDATE', 'INSERT', 'REFERENCES'):
|
||||
start, end = has_grant_on_col(privileges, grant)
|
||||
# If not, either start and end will be None
|
||||
if start is not None:
|
||||
privileges = handle_grant_on_col(privileges, start, end)
|
||||
|
||||
return privileges
|
||||
|
||||
|
||||
def has_grant_on_col(privileges, grant):
|
||||
"""Check if there is a statement like SELECT (colA, colB)
|
||||
in the privilege list.
|
||||
|
||||
|
@ -799,7 +812,7 @@ def has_select_on_col(privileges):
|
|||
start = None
|
||||
end = None
|
||||
for n, priv in enumerate(privileges):
|
||||
if 'SELECT (' in priv:
|
||||
if '%s (' % grant in priv:
|
||||
# We found the start element
|
||||
start = n
|
||||
|
||||
|
@ -819,8 +832,8 @@ def has_select_on_col(privileges):
|
|||
return None, None
|
||||
|
||||
|
||||
def handle_select_on_col(privileges, start, end):
|
||||
"""Handle cases when the SELECT (colA, ...) is in the privileges list."""
|
||||
def handle_grant_on_col(privileges, start, end):
|
||||
"""Handle cases when the privs like SELECT (colA, ...) is in the privileges list."""
|
||||
# When the privileges list look like ['SELECT (colA,', 'colB)']
|
||||
# (Notice that the statement is splitted)
|
||||
if start != end:
|
||||
|
@ -844,7 +857,7 @@ def handle_select_on_col(privileges, start, end):
|
|||
|
||||
|
||||
def sort_column_order(statement):
|
||||
"""Sort column order in SELECT (colA, colB, ...) grants.
|
||||
"""Sort column order in grants like SELECT (colA, colB, ...).
|
||||
|
||||
MySQL changes columns order like below:
|
||||
---------------------------------------
|
||||
|
@ -870,8 +883,10 @@ def sort_column_order(statement):
|
|||
# 3. Sort
|
||||
# 4. Put between () and return
|
||||
|
||||
# "SELECT (colA, colB) => "colA, colB"
|
||||
columns = statement.split('(')[1].rstrip(')')
|
||||
# "SELECT/UPDATE/.. (colA, colB) => "colA, colB"
|
||||
tmp = statement.split('(')
|
||||
priv_name = tmp[0]
|
||||
columns = tmp[1].rstrip(')')
|
||||
|
||||
# "colA, colB" => ["colA", "colB"]
|
||||
columns = columns.split(',')
|
||||
|
@ -881,7 +896,7 @@ def sort_column_order(statement):
|
|||
columns[i] = col.strip('`')
|
||||
|
||||
columns.sort()
|
||||
return 'SELECT (%s)' % ', '.join(columns)
|
||||
return '%s(%s)' % (priv_name, ', '.join(columns))
|
||||
|
||||
|
||||
def privileges_unpack(priv, mode):
|
||||
|
@ -927,10 +942,8 @@ def privileges_unpack(priv, mode):
|
|||
output[pieces[0]] = pieces[1].upper().split(',')
|
||||
privs = output[pieces[0]]
|
||||
|
||||
# Handle cases when there's GRANT SELECT (colA, ...) in privs.
|
||||
start, end = has_select_on_col(output[pieces[0]])
|
||||
if start is not None:
|
||||
output[pieces[0]] = handle_select_on_col(output[pieces[0]], start, end)
|
||||
# Handle cases when there's privs like GRANT SELECT (colA, ...) in privs.
|
||||
output[pieces[0]] = normalize_col_grants(output[pieces[0]])
|
||||
|
||||
new_privs = frozenset(privs)
|
||||
if not new_privs.issubset(VALID_PRIVS):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue