From 43ec7ed456fa082e7807c53167bb9d47ffc25ab8 Mon Sep 17 00:00:00 2001 From: Tim Abbott Date: Mon, 21 May 2018 08:44:00 -0700 Subject: [PATCH] narrow: Add is_web_public_compatible check for narrows. This will be used to limit which narrows will be allowed for web-public browsing of Zulip. --- zerver/lib/narrow.py | 11 ++++++++++- zerver/tests/test_archive.py | 1 - zerver/tests/test_narrow.py | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/zerver/lib/narrow.py b/zerver/lib/narrow.py index c963763cd8..bb05bf216d 100644 --- a/zerver/lib/narrow.py +++ b/zerver/lib/narrow.py @@ -1,7 +1,7 @@ from zerver.lib.request import JsonableError from django.utils.translation import ugettext as _ -from typing import Any, Callable, Iterable, Mapping, Sequence +from typing import Any, Callable, Dict, Iterable, Mapping, Sequence def check_supported_events_narrow_filter(narrow: Iterable[Sequence[str]]) -> None: @@ -10,6 +10,15 @@ def check_supported_events_narrow_filter(narrow: Iterable[Sequence[str]]) -> Non if operator not in ["stream", "topic", "sender", "is"]: raise JsonableError(_("Operator %s not supported.") % (operator,)) +def is_web_public_compatible(narrow: Iterable[Dict[str, str]]) -> bool: + for element in narrow: + operator = element['operator'] + if 'operand' not in element: + return False + if operator not in ["stream", "topic", "sender", "has", "search", "near", "id"]: + return False + return True + def build_narrow_filter(narrow: Iterable[Sequence[str]]) -> Callable[[Mapping[str, Any]], bool]: """Changes to this function should come with corresponding changes to BuildNarrowFilterTest.""" diff --git a/zerver/tests/test_archive.py b/zerver/tests/test_archive.py index 1c96d31cb7..fba27a2cf7 100644 --- a/zerver/tests/test_archive.py +++ b/zerver/tests/test_archive.py @@ -7,7 +7,6 @@ from zerver.lib.actions import get_web_public_streams, get_web_public_subs, \ from zerver.models import get_realm class GlobalPublicStreamTest(ZulipTestCase): - def test_non_existant_stream_id(self) -> None: # Here we use a relatively big number as stream id assumming such an id # won't exist in the test DB. diff --git a/zerver/tests/test_narrow.py b/zerver/tests/test_narrow.py index 03fd596e49..dcf567b930 100644 --- a/zerver/tests/test_narrow.py +++ b/zerver/tests/test_narrow.py @@ -19,6 +19,7 @@ from zerver.lib.message import ( ) from zerver.lib.narrow import ( build_narrow_filter, + is_web_public_compatible, ) from zerver.lib.request import JsonableError from zerver.lib.sqlalchemy_utils import get_sqlalchemy_connection @@ -344,7 +345,7 @@ class NarrowBuilderTest(ZulipTestCase): def _build_query(self, term: Dict[str, Any]) -> Query: return self.builder.add_term(self.raw_query, term) -class BuildNarrowFilterTest(TestCase): +class NarrowLibraryTest(TestCase): def test_build_narrow_filter(self) -> None: fixtures_path = os.path.join(os.path.dirname(__file__), 'fixtures/narrow.json') @@ -364,6 +365,39 @@ class BuildNarrowFilterTest(TestCase): with self.assertRaises(JsonableError): build_narrow_filter(["invalid_operator", "operand"]) + def test_is_web_public_compatible(self) -> None: + self.assertTrue(is_web_public_compatible([])) + self.assertTrue(is_web_public_compatible([{"operator": "has", + "operand": "attachment"}])) + self.assertTrue(is_web_public_compatible([{"operator": "has", + "operand": "image"}])) + self.assertTrue(is_web_public_compatible([{"operator": "search", + "operand": "magic"}])) + self.assertTrue(is_web_public_compatible([{"operator": "near", + "operand": "15"}])) + self.assertTrue(is_web_public_compatible([{"operator": "id", + "operand": "15"}, + {"operator": "has", + "operand": "attachment"}])) + self.assertTrue(is_web_public_compatible([{"operator": "sender", + "operand": "hamlet@zulip.com"}])) + self.assertFalse(is_web_public_compatible([{"operator": "pm-with", + "operand": "hamlet@zulip.com"}])) + self.assertFalse(is_web_public_compatible([{"operator": "group-pm-with", + "operand": "hamlet@zulip.com"}])) + self.assertTrue(is_web_public_compatible([{"operator": "stream", + "operand": "Denmark"}])) + self.assertTrue(is_web_public_compatible([{"operator": "stream", + "operand": "Denmark"}, + {"operator": "topic", + "operand": "logic"}])) + self.assertFalse(is_web_public_compatible([{"operator": "is", + "operand": "starred"}])) + self.assertFalse(is_web_public_compatible([{"operator": "is", + "operand": "private"}])) + # Malformed input not allowed + self.assertFalse(is_web_public_compatible([{"operator": "has"}])) + class IncludeHistoryTest(ZulipTestCase): def test_ok_to_include_history(self) -> None: user_profile = self.example_user("hamlet")