mirror of
https://github.com/ZwareBear/awx.git
synced 2026-03-19 23:33:37 -05:00
[FieldLookupBackend] limit iexact to string fields (#12569)
Change: - Case-insensitive search only makes sense on strings, so check the type of the field we are searching and ensure it is a string field (TextField, CharField, or some subclass thereof). - This prevents a 500 error when a user uses iexact on, e.g., an integer field. Now, a 400 Bad Request is returned instead. Test Plan: - Added simple unit tests for iexact Tickets: - Fixes #9222 Signed-off-by: Rick Elrod <rick@elrod.me>
This commit is contained in:
@@ -232,6 +232,9 @@ class FieldLookupBackend(BaseFilterBackend):
|
|||||||
re.compile(value)
|
re.compile(value)
|
||||||
except re.error as e:
|
except re.error as e:
|
||||||
raise ValueError(e.args[0])
|
raise ValueError(e.args[0])
|
||||||
|
elif new_lookup.endswith('__iexact'):
|
||||||
|
if not isinstance(field, (CharField, TextField)):
|
||||||
|
raise ValueError(f'{field.name} is not a text field and cannot be filtered by case-insensitive search')
|
||||||
elif new_lookup.endswith('__search'):
|
elif new_lookup.endswith('__search'):
|
||||||
related_model = getattr(field, 'related_model', None)
|
related_model = getattr(field, 'related_model', None)
|
||||||
if not related_model:
|
if not related_model:
|
||||||
@@ -258,8 +261,8 @@ class FieldLookupBackend(BaseFilterBackend):
|
|||||||
search_filters = {}
|
search_filters = {}
|
||||||
needs_distinct = False
|
needs_distinct = False
|
||||||
# Can only have two values: 'AND', 'OR'
|
# Can only have two values: 'AND', 'OR'
|
||||||
# If 'AND' is used, an iterm must satisfy all condition to show up in the results.
|
# If 'AND' is used, an item must satisfy all conditions to show up in the results.
|
||||||
# If 'OR' is used, an item just need to satisfy one condition to appear in results.
|
# If 'OR' is used, an item just needs to satisfy one condition to appear in results.
|
||||||
search_filter_relation = 'OR'
|
search_filter_relation = 'OR'
|
||||||
for key, values in request.query_params.lists():
|
for key, values in request.query_params.lists():
|
||||||
if key in self.RESERVED_NAMES:
|
if key in self.RESERVED_NAMES:
|
||||||
|
|||||||
@@ -79,6 +79,19 @@ def test_invalid_field():
|
|||||||
assert 'is not an allowed field name. Must be ascii encodable.' in str(excinfo.value)
|
assert 'is not an allowed field name. Must be ascii encodable.' in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
|
def test_valid_iexact():
|
||||||
|
field_lookup = FieldLookupBackend()
|
||||||
|
value, new_lookup, _ = field_lookup.value_to_python(JobTemplate, 'project__name__iexact', 'foo')
|
||||||
|
assert 'foo' in value
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_iexact():
|
||||||
|
field_lookup = FieldLookupBackend()
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
field_lookup.value_to_python(Job, 'id__iexact', '1')
|
||||||
|
assert 'is not a text field and cannot be filtered by case-insensitive search' in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('lookup_suffix', ['', 'contains', 'startswith', 'in'])
|
@pytest.mark.parametrize('lookup_suffix', ['', 'contains', 'startswith', 'in'])
|
||||||
@pytest.mark.parametrize('password_field', Credential.PASSWORD_FIELDS)
|
@pytest.mark.parametrize('password_field', Credential.PASSWORD_FIELDS)
|
||||||
def test_filter_on_password_field(password_field, lookup_suffix):
|
def test_filter_on_password_field(password_field, lookup_suffix):
|
||||||
|
|||||||
Reference in New Issue
Block a user