Refactor REGEX filters to eliminate 500 errors
You can currently create a 500 error on mysql by passing | as the name filter because mysql assumes regex values are well crafted by the application layer. This puts in facilities to provide a safe regex filter per db engine. It also refactors some of the inline code from _regex_instance_filter into slightly more logical blocks, which will make it a little more straight forward about where we need to do something smarter about determining the dbtype in a cellsv2 world. Change-Id: Ice2e21666905fdb76c001195e8fca21b427ea737 Closes-Bug: 1546396
This commit is contained in:
parent
bde73b365a
commit
8f2538f8fb
@ -2309,17 +2309,51 @@ def _tag_instance_filter(context, query, filters):
|
|||||||
return query
|
return query
|
||||||
|
|
||||||
|
|
||||||
def _get_regexp_op_for_connection(db_connection):
|
def _db_connection_type(db_connection):
|
||||||
|
"""Returns a lowercase symbol for the db type.
|
||||||
|
|
||||||
|
This is useful when we need to change what we are doing per DB
|
||||||
|
(like handling regexes). In a CellsV2 world it probably needs to
|
||||||
|
do something better than use the database configuration string.
|
||||||
|
"""
|
||||||
|
|
||||||
db_string = db_connection.split(':')[0].split('+')[0]
|
db_string = db_connection.split(':')[0].split('+')[0]
|
||||||
|
return db_string.lower()
|
||||||
|
|
||||||
|
|
||||||
|
def _safe_regex_mysql(raw_string):
|
||||||
|
"""Make regex safe to mysql.
|
||||||
|
|
||||||
|
Certain items like '|' are interpreted raw by mysql REGEX. If you
|
||||||
|
search for a single | then you trigger an error because it's
|
||||||
|
expecting content on either side.
|
||||||
|
|
||||||
|
For consistency sake we escape all '|'. This does mean we wouldn't
|
||||||
|
support something like foo|bar to match completely different
|
||||||
|
things, however, one can argue putting such complicated regex into
|
||||||
|
name search probably means you are doing this wrong.
|
||||||
|
"""
|
||||||
|
return raw_string.replace('|', '\\|')
|
||||||
|
|
||||||
|
|
||||||
|
def _get_regexp_ops(connection):
|
||||||
|
"""Return safety filter and db opts for regex."""
|
||||||
regexp_op_map = {
|
regexp_op_map = {
|
||||||
'postgresql': '~',
|
'postgresql': '~',
|
||||||
'mysql': 'REGEXP',
|
'mysql': 'REGEXP',
|
||||||
'sqlite': 'REGEXP'
|
'sqlite': 'REGEXP'
|
||||||
}
|
}
|
||||||
return regexp_op_map.get(db_string, 'LIKE')
|
regex_safe_filters = {
|
||||||
|
'mysql': _safe_regex_mysql
|
||||||
|
}
|
||||||
|
db_type = _db_connection_type(connection)
|
||||||
|
|
||||||
|
return (regex_safe_filters.get(db_type, lambda x: x),
|
||||||
|
regexp_op_map.get(db_type, 'LIKE'))
|
||||||
|
|
||||||
|
|
||||||
def _regex_instance_filter(query, filters):
|
def _regex_instance_filter(query, filters):
|
||||||
|
|
||||||
"""Applies regular expression filtering to an Instance query.
|
"""Applies regular expression filtering to an Instance query.
|
||||||
|
|
||||||
Returns the updated query.
|
Returns the updated query.
|
||||||
@ -2329,7 +2363,7 @@ def _regex_instance_filter(query, filters):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
model = models.Instance
|
model = models.Instance
|
||||||
db_regexp_op = _get_regexp_op_for_connection(CONF.database.connection)
|
safe_regex_filter, db_regexp_op = _get_regexp_ops(CONF.database.connection)
|
||||||
for filter_name in filters:
|
for filter_name in filters:
|
||||||
try:
|
try:
|
||||||
column_attr = getattr(model, filter_name)
|
column_attr = getattr(model, filter_name)
|
||||||
@ -2345,6 +2379,7 @@ def _regex_instance_filter(query, filters):
|
|||||||
query = query.filter(column_attr.op(db_regexp_op)(
|
query = query.filter(column_attr.op(db_regexp_op)(
|
||||||
u'%' + filter_val + u'%'))
|
u'%' + filter_val + u'%'))
|
||||||
else:
|
else:
|
||||||
|
filter_val = safe_regex_filter(filter_val)
|
||||||
query = query.filter(column_attr.op(db_regexp_op)(
|
query = query.filter(column_attr.op(db_regexp_op)(
|
||||||
filter_val))
|
filter_val))
|
||||||
return query
|
return query
|
||||||
|
Loading…
x
Reference in New Issue
Block a user