Skip to content

Commit

Permalink
Validate "path matches" conditions as regular expressions
Browse files Browse the repository at this point in the history
Because "path matches" conditions can be any valid regular expression, this change simply uses `re.compile()` to validate them.

Previously they were validated as URL paths, without querystring or URL scheme-matching characters allowed. This warned on some valid regular expressions that it shouldn't have.

This fix is what @chosak suggested in #77.
  • Loading branch information
willbarton committed Mar 17, 2021
1 parent 6c70ee1 commit 71b8d02
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 23 deletions.
7 changes: 7 additions & 0 deletions docs/releasenotes.md
@@ -1,5 +1,12 @@
# Release Notes

## Unreleased

### What's new?

- Fixed the "path matches" condition validator to allow any valid regular expression.


## 5.0.3

### What's new?
Expand Down
2 changes: 1 addition & 1 deletion flags/conditions/__init__.py
Expand Up @@ -20,6 +20,6 @@
validate_boolean,
validate_date,
validate_parameter,
validate_path,
validate_path_re,
validate_user,
)
4 changes: 2 additions & 2 deletions flags/conditions/conditions.py
Expand Up @@ -9,7 +9,7 @@
validate_boolean,
validate_date,
validate_parameter,
validate_path,
validate_path_re,
validate_user,
)

Expand Down Expand Up @@ -67,7 +67,7 @@ def parameter_condition(param_name, request=None, **kwargs):
return request.GET.get(param_name) == param_value


@register("path matches", validator=validate_path)
@register("path matches", validator=validate_path_re)
def path_condition(pattern, request=None, **kwargs):
""" Does the request's path match the given regular expression? """
if request is None:
Expand Down
19 changes: 10 additions & 9 deletions flags/conditions/validators.py
Expand Up @@ -7,22 +7,23 @@
from django.utils import dateparse


validate_path = RegexValidator(
re.compile(r"^[^\s:?#]+$", re.UNICODE),
message=(
"Enter a valid path without a URL scheme, query string, or fragment."
),
code="invalid",
)


validate_parameter = RegexValidator(
re.compile(r"^[-_\w=]+$", re.UNICODE),
message="Enter a valid HTTP parameter name.",
code="invalid",
)


def validate_path_re(value):
try:
re.compile(value)
except re.error as e:
raise ValidationError(
"Enter either a valid path or a regular expression to match a "
"path, without a URL scheme, query string, or fragment."
) from e


def validate_boolean(value):
message = "Enter one of 'on', 'off', 'true', 'false', etc."
try:
Expand Down
19 changes: 8 additions & 11 deletions flags/tests/test_conditions_validators.py
Expand Up @@ -6,7 +6,7 @@
validate_boolean,
validate_date,
validate_parameter,
validate_path,
validate_path_re,
validate_user,
)

Expand All @@ -26,18 +26,15 @@ def test_valid_parameter_strings(self):


class ValidatePathTestCase(TestCase):
def test_invalid_path_strings(self):
def test_invalid_path_regexs(self):
with self.assertRaises(ValidationError):
validate_path("/my/path#foo")
with self.assertRaises(ValidationError):
validate_path("/my/path?foo=bar")
with self.assertRaises(ValidationError):
validate_path("https://foo/my/path")
validate_path_re("*foo/my/path")

def test_valid_path_strings(self):
validate_path("/my/path")
validate_path("/my/path/")
validate_path("my/path/")
def test_valid_path_regexs(self):
validate_path_re("/my/path")
validate_path_re("/my/path/")
validate_path_re("my/path/")
validate_path_re(r"^/my/(path)?$")


class ValidateBooleanTestCase(TestCase):
Expand Down

0 comments on commit 71b8d02

Please sign in to comment.