From 3e7538b9745d25bebd8b44b4c7ad2817a726563d Mon Sep 17 00:00:00 2001 From: Aman Agrawal Date: Mon, 5 Oct 2020 14:20:51 +0530 Subject: [PATCH] filter: Copy is_web_public_compatible from server to frontend. This will be used to check if the narrow being requested by spectator requires authentication without requesting the server. Having this check locally, makes this process look snappy to the user and doesn't result in 404s in the browser log. --- frontend_tests/node_tests/filter.js | 36 +++++++++++++++++++++++++++++ static/js/filter.js | 13 +++++++++++ static/js/hash_util.js | 2 ++ zerver/lib/narrow.py | 1 + 4 files changed, 52 insertions(+) diff --git a/frontend_tests/node_tests/filter.js b/frontend_tests/node_tests/filter.js index 447157a48b..7845621e6c 100644 --- a/frontend_tests/node_tests/filter.js +++ b/frontend_tests/node_tests/filter.js @@ -1614,3 +1614,39 @@ test("error_cases", ({override}) => { const predicate = get_predicate([["pm-with", "Joe@example.com"]]); assert.ok(!predicate({type: "private"})); }); + +run_test("is_web_public_compatible", () => { + // tests same as test_is_web_public_compatible from test_message_fetch.py + assert.ok(Filter.is_web_public_compatible([])); + assert.ok(Filter.is_web_public_compatible([{operator: "has", operand: "attachment"}])); + assert.ok(Filter.is_web_public_compatible([{operator: "has", operand: "image"}])); + assert.ok(Filter.is_web_public_compatible([{operator: "search", operand: "magic"}])); + assert.ok(Filter.is_web_public_compatible([{operator: "near", operand: "15"}])); + assert.ok( + Filter.is_web_public_compatible([ + {operator: "id", operand: "15"}, + {operator: "has", operand: "attachment"}, + ]), + ); + assert.ok(Filter.is_web_public_compatible([{operator: "sender", operand: "hamlet@zulip.com"}])); + assert.ok( + !Filter.is_web_public_compatible([{operator: "pm-with", operand: "hamlet@zulip.com"}]), + ); + assert.ok( + !Filter.is_web_public_compatible([ + {operator: "group-pm-with", operand: "hamlet@zulip.com"}, + ]), + ); + assert.ok(Filter.is_web_public_compatible([{operator: "stream", operand: "Denmark"}])); + assert.ok( + Filter.is_web_public_compatible([ + {operator: "stream", operand: "Denmark"}, + {operator: "topic", operand: "logic"}, + ]), + ); + assert.ok(!Filter.is_web_public_compatible([{operator: "is", operand: "starred"}])); + assert.ok(!Filter.is_web_public_compatible([{operator: "is", operand: "private"}])); + assert.ok(Filter.is_web_public_compatible([{operator: "streams", operand: "public"}])); + // Malformed input not allowed + assert.ok(!Filter.is_web_public_compatible([{operator: "has"}])); +}); diff --git a/static/js/filter.js b/static/js/filter.js index a1ca94a714..97405ccdf1 100644 --- a/static/js/filter.js +++ b/static/js/filter.js @@ -1,6 +1,7 @@ import Handlebars from "handlebars/runtime"; import _ from "lodash"; +import * as hash_util from "./hash_util"; import {$t} from "./i18n"; import * as message_edit from "./message_edit"; import * as message_parser from "./message_parser"; @@ -1005,4 +1006,16 @@ export class Filter { static describe(operators) { return Handlebars.Utils.escapeExpression(Filter.describe_unescaped(operators)); } + + static is_web_public_compatible(ops) { + for (const op of ops) { + if (op.operand === undefined) { + return false; + } + if (!hash_util.allowed_web_public_narrows.includes(op.operator)) { + return false; + } + } + return true; + } } diff --git a/static/js/hash_util.js b/static/js/hash_util.js index c788f6769c..0747bc7c53 100644 --- a/static/js/hash_util.js +++ b/static/js/hash_util.js @@ -283,6 +283,8 @@ export const allowed_web_public_narrows = [ ]; export function is_web_public_compatible(hash) { + // Defines which views are supported for spectators. + // This implementation should agree with the similar function in zerver/lib/narrow.py. const web_public_allowed_hashes = [ "", "narrow", // full #narrow hash handled in narrow.is_web_public_compatible diff --git a/zerver/lib/narrow.py b/zerver/lib/narrow.py index d623ff4fec..6cbe5b5e40 100644 --- a/zerver/lib/narrow.py +++ b/zerver/lib/narrow.py @@ -30,6 +30,7 @@ def check_supported_events_narrow_filter(narrow: Iterable[Sequence[str]]) -> Non def is_web_public_compatible(narrow: Iterable[Dict[str, Any]]) -> bool: + # This implementation should agree with the similar function in static/js/hash_utl.js. for element in narrow: operator = element["operator"] if "operand" not in element: