mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-06-03 20:29:45 +00:00
Fix: Restrict date query rewrites to date or datetime fields only (#12864)
This commit is contained in:
@@ -52,7 +52,7 @@ _DATE_KEYWORD_PATTERN = "|".join(
|
||||
)
|
||||
|
||||
_FIELD_DATE_RE = regex.compile(
|
||||
rf"""(?P<field>\w+)\s*:\s*(?:
|
||||
rf"""(?<!\w)(?P<field>created|modified|added)\s*:\s*(?:
|
||||
(?P<quote>["'])(?P<quoted>{_DATE_KEYWORD_PATTERN})(?P=quote)
|
||||
|
|
||||
(?P<bare>{_DATE_KEYWORD_PATTERN})(?![\w-])
|
||||
@@ -69,10 +69,13 @@ _WHOOSH_REL_RANGE_RE = regex.compile(
|
||||
r"\[-(?P<n>\d+)\s+(?P<unit>second|minute|hour|day|week|month|year)s?\s+to\s+now\]",
|
||||
regex.IGNORECASE,
|
||||
)
|
||||
# Whoosh-style 8-digit date: field:YYYYMMDD — field-aware so timezone can be applied correctly
|
||||
_DATE8_RE = regex.compile(r"(?P<field>\w+):(?P<date8>\d{8})\b")
|
||||
# Whoosh-style 8-digit date: field:YYYYMMDD — field-aware so timezone can be applied correctly.
|
||||
# Scoped to date fields only; numeric fields (asn, id, page_count, ...) must not be rewritten.
|
||||
_DATE8_RE = regex.compile(
|
||||
r"(?<!\w)(?P<field>created|modified|added):(?P<date8>\d{8})\b",
|
||||
)
|
||||
_YEAR_RANGE_RE = regex.compile(
|
||||
r"(?P<field>\w+):\[(?P<y1>\d{4})\s+TO\s+(?P<y2>\d{4})\]",
|
||||
r"(?<!\w)(?P<field>created|modified|added):\[(?P<y1>\d{4})\s+TO\s+(?P<y2>\d{4})\]",
|
||||
regex.IGNORECASE,
|
||||
)
|
||||
_SIMPLE_QUERY_TOKEN_RE = regex.compile(r"\S+")
|
||||
|
||||
@@ -541,6 +541,45 @@ class TestYearRangeRewriting:
|
||||
assert "20201231" in result or "2020-12-31" in result
|
||||
|
||||
|
||||
class TestNonDateFieldsNotRewritten:
|
||||
"""Date rewriters must only fire on the date fields (created/modified/added).
|
||||
|
||||
Integer fields like asn/id/page_count and unknown fields would otherwise be
|
||||
rewritten into date ranges and rejected by Tantivy as type mismatches.
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"query",
|
||||
[
|
||||
pytest.param("asn:20240101", id="asn_8digit"),
|
||||
pytest.param("id:20240101", id="id_8digit"),
|
||||
pytest.param("page_count:12345678", id="page_count_8digit"),
|
||||
pytest.param("num_notes:20231201", id="num_notes_8digit"),
|
||||
],
|
||||
)
|
||||
def test_8digit_on_integer_field_passes_through_unchanged(self, query: str) -> None:
|
||||
assert rewrite_natural_date_keywords(query, EASTERN) == query
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"query",
|
||||
[
|
||||
pytest.param("asn:[2000 TO 2024]", id="asn_year_range"),
|
||||
pytest.param("id:[2000 TO 2024]", id="id_year_range"),
|
||||
pytest.param("page_count:[2000 TO 2024]", id="page_count_year_range"),
|
||||
],
|
||||
)
|
||||
def test_year_range_on_integer_field_passes_through_unchanged(
|
||||
self,
|
||||
query: str,
|
||||
) -> None:
|
||||
assert rewrite_natural_date_keywords(query, UTC) == query
|
||||
|
||||
def test_unknown_field_keyword_passes_through_unchanged(self) -> None:
|
||||
# foobar is not a date field: 'foobar:today' must not become a date range,
|
||||
# which Tantivy would otherwise reject as an unknown/typed field.
|
||||
assert rewrite_natural_date_keywords("foobar:today", UTC) == "foobar:today"
|
||||
|
||||
|
||||
class TestPassthrough:
|
||||
"""Queries without field prefixes or unrelated content pass through unchanged."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user