Support non-search queries in /json/messages/matches_narrow.

For filters like has:link, where the web app doesn't necessarily
want to guess whether incoming messages meet the criteria of the
filter, the server is asked to query rows that match the query.

Usually these queries are search queries, which have fields for
content_matches and subject_matches.  Our logic was handling those
correctly.

Non-search queries were throwing an exception related to tuple
unpacking.  Now we recognize when those fields are absent and
do the proper thing.

There are probably situations where the web app should stop hitting
this endpoint and just use its own filters.  We are making the most
defensive fix first.

Fixes #6118
This commit is contained in:
Steve Howell 2017-08-18 09:50:54 -04:00 committed by Tim Abbott
parent be0b523b72
commit 2b4faaa847
2 changed files with 50 additions and 3 deletions

View File

@ -983,6 +983,42 @@ class GetOldMessagesTest(ZulipTestCase):
self.assertEqual(link_search_result['messages'][0]['match_content'],
'<p><a href="https://google.com" target="_blank" title="https://google.com"><span class="highlight">https://google.com</span></a></p>')
def test_messages_in_narrow_for_non_search(self):
# type: () -> None
email = self.example_email("cordelia")
self.login(email)
def send(content):
# type: (Text) -> int
msg_id = self.send_message(
sender_name=email,
raw_recipients="Verona",
message_type=Recipient.STREAM,
subject='test_topic',
content=content,
)
return msg_id
good_id = send('http://foo.com')
bad_id = send('no link here')
msg_ids = [good_id, bad_id]
send('http://bar.com but not in msg_ids')
narrow = [
dict(operator='has', operand='link'),
]
raw_params = dict(msg_ids=msg_ids, narrow=narrow)
params = {k: ujson.dumps(v) for k, v in raw_params.items()}
result = self.client_get('/json/messages/matches_narrow', params)
self.assert_json_success(result)
messages = result.json()['messages']
self.assertEqual(len(list(messages.keys())), 1)
message = messages[str(good_id)]
self.assertIn('a href=', message['match_content'])
self.assertIn('http://foo.com', message['match_content'])
self.assertEqual(message['match_subject'], 'test_topic')
def test_get_messages_with_only_searching_anchor(self):
# type: () -> None
"""

View File

@ -1198,8 +1198,19 @@ def messages_in_narrow_backend(request, user_profile,
search_fields = dict()
for row in query_result:
(message_id, subject, rendered_content, content_matches, subject_matches) = row
search_fields[message_id] = get_search_fields(rendered_content, subject,
content_matches, subject_matches)
message_id = row['message_id']
subject = row['subject']
rendered_content = row['rendered_content']
if 'content_matches' in row:
content_matches = row['content_matches']
subject_matches = row['subject_matches']
search_fields[message_id] = get_search_fields(rendered_content, subject,
content_matches, subject_matches)
else:
search_fields[message_id] = dict(
match_content=rendered_content,
match_subject=subject
)
return json_success({"messages": search_fields})