diff --git a/zerver/actions/streams.py b/zerver/actions/streams.py index 39fddbc372..3e0a9513ed 100644 --- a/zerver/actions/streams.py +++ b/zerver/actions/streams.py @@ -1495,7 +1495,9 @@ def do_change_stream_description( ) -> None: old_description = stream.description stream.description = new_description - stream.rendered_description = render_stream_description(new_description, stream.realm) + stream.rendered_description = render_stream_description( + new_description, stream.realm, acting_user=acting_user + ) stream.save(update_fields=["description", "rendered_description"]) RealmAuditLog.objects.create( realm=stream.realm, diff --git a/zerver/lib/streams.py b/zerver/lib/streams.py index 58835c0b36..822289013c 100644 --- a/zerver/lib/streams.py +++ b/zerver/lib/streams.py @@ -128,10 +128,14 @@ def get_default_value_for_history_public_to_subscribers( return history_public_to_subscribers -def render_stream_description(text: str, realm: Realm) -> str: +def render_stream_description( + text: str, realm: Realm, *, acting_user: UserProfile | None = None +) -> str: from zerver.lib.markdown import markdown_convert - return markdown_convert(text, message_realm=realm, no_previews=True).rendered_content + return markdown_convert( + text, message_realm=realm, no_previews=True, acting_user=acting_user + ).rendered_content def send_stream_creation_event( @@ -258,7 +262,9 @@ def create_stream_if_needed( recipient = Recipient.objects.create(type_id=stream.id, type=Recipient.STREAM) stream.recipient = recipient - stream.rendered_description = render_stream_description(stream_description, realm) + stream.rendered_description = render_stream_description( + stream_description, realm, acting_user=acting_user + ) stream.save(update_fields=["recipient", "rendered_description"]) event_time = timezone_now() diff --git a/zerver/tests/test_subs.py b/zerver/tests/test_subs.py index 7ff926207a..9118051e01 100644 --- a/zerver/tests/test_subs.py +++ b/zerver/tests/test_subs.py @@ -395,6 +395,39 @@ class TestCreateStreams(ZulipTestCase): stream = get_stream("new_stream", realm) self.assertEqual(stream.description, "multi line description") + def test_create_api_topic_permalink_description(self) -> None: + user = self.example_user("iago") + realm = user.realm + self.login_user(user) + + hamlet = self.example_user("hamlet") + core_stream = self.make_stream("core", realm, True, history_public_to_subscribers=True) + self.subscribe(hamlet, "core") + msg_id = self.send_stream_message(hamlet, "core", topic_name="testing") + + # Test permalink not generated for description since user has no access to + # the channel. + subscriptions = [{"name": "stream1", "description": "#**core>testing**"}] + result = self.subscribe_via_post(user, subscriptions, subdomain="zulip") + self.assert_json_success(result) + stream = get_stream("stream1", realm) + + self.assertEqual(stream.rendered_description, "
#core>testing
") + + self.subscribe(user, "core") + + # Test permalink generated for the description since user now has access + # to the channel. + subscriptions = [{"name": "stream2", "description": "#**core>testing**"}] + result = self.subscribe_via_post(user, subscriptions, subdomain="zulip") + self.assert_json_success(result) + stream = get_stream("stream2", realm) + + self.assertEqual( + stream.rendered_description, + f'', + ) + def test_history_public_to_subscribers_on_stream_creation(self) -> None: realm = get_realm("zulip") stream_dicts: list[StreamDict] = [ @@ -2434,6 +2467,42 @@ class StreamAdminTest(ZulipTestCase): ) self.assert_json_success(result) + # Verify that we render topic permalinks in the description depending + # on whether the acting_user has access to that channel. + hamlet = self.example_user("hamlet") + core_stream = self.make_stream("core", realm, True, history_public_to_subscribers=True) + + self.subscribe(hamlet, "core") + msg_id = self.send_stream_message(hamlet, "core", topic_name="testing") + + result = self.client_patch( + f"/json/streams/{stream_id}", + {"description": "#**core>testing**"}, + ) + + stream = get_stream("stream_name1", realm) + + # permalink is not rendered since acting_user has no access to channel. + self.assertEqual( + stream.rendered_description, + "#core>testing
", + ) + + self.subscribe(user_profile, "core") + + result = self.client_patch( + f"/json/streams/{stream_id}", + {"description": "#**core>testing**"}, + ) + + stream = get_stream("stream_name1", realm) + + # permalink is rendered since acting_user now has access to channel. + self.assertEqual( + stream.rendered_description, + f'', + ) + def test_change_stream_description_requires_administer_channel_permissions(self) -> None: user_profile = self.example_user("hamlet") self.login_user(user_profile)