markdown: Fix invalid mention bug for user group mention.

Modifies `UserGroupMentionPattern` to inherit from InlineProcessor
instead of Pattern. This change is done because Pattern
stopped checking for matching patterns as soon as it found
a match which was not a valid user group. Due to this all
the subsequent user group mention failed, even if they were
valid. This bug was only present in backend renderring due to
markdown.inlinepatterns.Pattern.

This was reported as issue #17535.

These changes were tested locally in dev server and by adding
some new markdown tests to test these.
This commit is contained in:
m-e-l-u-h-a-n 2021-03-18 16:04:49 +05:30 committed by Tim Abbott
parent c8979a5100
commit dadbba0c25
2 changed files with 30 additions and 7 deletions

View File

@ -1844,11 +1844,13 @@ class UserMentionPattern(markdown.inlinepatterns.InlineProcessor):
return None, None, None return None, None, None
class UserGroupMentionPattern(markdown.inlinepatterns.Pattern): class UserGroupMentionPattern(markdown.inlinepatterns.InlineProcessor):
def handleMatch(self, m: Match[str]) -> Optional[Element]: def handleMatch( # type: ignore[override] # supertype incompatible with supersupertype
match = m.group(2) self, m: Match[str], data: str
) -> Union[Tuple[None, None, None], Tuple[Element, int, int]]:
match = m.group(1)
db_data = self.md.zulip_db_data db_data = self.md.zulip_db_data
if self.md.zulip_message and db_data is not None: if self.md.zulip_message and db_data is not None:
name = extract_user_group(match) name = extract_user_group(match)
user_group = db_data["mention_data"].get_user_group(name) user_group = db_data["mention_data"].get_user_group(name)
@ -1859,15 +1861,15 @@ class UserGroupMentionPattern(markdown.inlinepatterns.Pattern):
else: else:
# Don't highlight @-mentions that don't refer to a valid user # Don't highlight @-mentions that don't refer to a valid user
# group. # group.
return None return None, None, None
el = Element("span") el = Element("span")
el.set("class", "user-group-mention") el.set("class", "user-group-mention")
el.set("data-user-group-id", user_group_id) el.set("data-user-group-id", user_group_id)
text = f"@{name}" text = f"@{name}"
el.text = markdown.util.AtomicString(text) el.text = markdown.util.AtomicString(text)
return el return el, m.start(), m.end()
return None return None, None, None
class StreamPattern(CompiledPattern): class StreamPattern(CompiledPattern):

View File

@ -2056,6 +2056,27 @@ class MarkdownTest(ZulipTestCase):
self.assertEqual(msg.mentions_user_ids, {user_profile.id}) self.assertEqual(msg.mentions_user_ids, {user_profile.id})
self.assertEqual(msg.mentions_user_group_ids, {user_group.id}) self.assertEqual(msg.mentions_user_group_ids, {user_group.id})
def test_invalid_user_group_followed_by_valid_mention_single(self) -> None:
sender_user_profile = self.example_user("othello")
user_profile = self.example_user("hamlet")
msg = Message(sender=sender_user_profile, sending_client=get_client("test"))
user_id = user_profile.id
user_group = self.create_user_group_for_test("support")
content = "@**King Hamlet** @*Invalid user group* @*support*"
self.assertEqual(
render_markdown(msg, content),
'<p><span class="user-mention" '
f'data-user-id="{user_id}">'
"@King Hamlet</span> "
"@<em>Invalid user group</em> "
'<span class="user-group-mention" '
f'data-user-group-id="{user_group.id}">'
"@support</span></p>",
)
self.assertEqual(msg.mentions_user_ids, {user_profile.id})
self.assertEqual(msg.mentions_user_group_ids, {user_group.id})
def test_user_group_mention_atomic_string(self) -> None: def test_user_group_mention_atomic_string(self) -> None:
sender_user_profile = self.example_user("othello") sender_user_profile = self.example_user("othello")
realm = get_realm("zulip") realm = get_realm("zulip")