mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	streams: Grant guest users access to web-public streams.
In this commit, we grant guest users access to stream history, send message and common stream data of web-public streams. This is part of PR #14638 that aims to allow guest users to browse and subscribe to web-public streams.
This commit is contained in:
		@@ -163,6 +163,10 @@ def access_stream_for_send_message(sender: UserProfile,
 | 
				
			|||||||
        elif sender.is_new_member:
 | 
					        elif sender.is_new_member:
 | 
				
			||||||
            raise JsonableError(_("New members cannot send to this stream."))
 | 
					            raise JsonableError(_("New members cannot send to this stream."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if stream.is_web_public:
 | 
				
			||||||
 | 
					        # Even guest users can write to web-public streams.
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if not (stream.invite_only or sender.is_guest):
 | 
					    if not (stream.invite_only or sender.is_guest):
 | 
				
			||||||
        # This is a public stream and sender is not a guest user
 | 
					        # This is a public stream and sender is not a guest user
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
@@ -242,6 +246,10 @@ def access_stream_common(user_profile: UserProfile, stream: Stream,
 | 
				
			|||||||
    except Subscription.DoesNotExist:
 | 
					    except Subscription.DoesNotExist:
 | 
				
			||||||
        sub = None
 | 
					        sub = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Any realm user, even guests, can access web_public streams.
 | 
				
			||||||
 | 
					    if stream.is_web_public:
 | 
				
			||||||
 | 
					        return (recipient, sub)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # If the stream is in your realm and public, you can access it.
 | 
					    # If the stream is in your realm and public, you can access it.
 | 
				
			||||||
    if stream.is_public() and not user_profile.is_guest:
 | 
					    if stream.is_public() and not user_profile.is_guest:
 | 
				
			||||||
        return (recipient, sub)
 | 
					        return (recipient, sub)
 | 
				
			||||||
@@ -353,6 +361,9 @@ def can_access_stream_history(user_profile: UserProfile, stream: Stream) -> bool
 | 
				
			|||||||
    access_stream is being called elsewhere to confirm that the user
 | 
					    access_stream is being called elsewhere to confirm that the user
 | 
				
			||||||
    can actually see this stream.
 | 
					    can actually see this stream.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					    if stream.is_web_public:
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if stream.is_history_realm_public() and not user_profile.is_guest:
 | 
					    if stream.is_history_realm_public() and not user_profile.is_guest:
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1889,6 +1889,25 @@ class CheckMessageTest(ZulipTestCase):
 | 
				
			|||||||
        ret = check_message(sender, client, addressee, message_content)
 | 
					        ret = check_message(sender, client, addressee, message_content)
 | 
				
			||||||
        self.assertEqual(ret['message'].sender.id, sender.id)
 | 
					        self.assertEqual(ret['message'].sender.id, sender.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_guest_user_can_send_message(self) -> None:
 | 
				
			||||||
 | 
					        # Guest users can write to web_public streams.
 | 
				
			||||||
 | 
					        sender = self.example_user("polonius")
 | 
				
			||||||
 | 
					        client = make_client(name="test suite")
 | 
				
			||||||
 | 
					        rome_stream = get_stream("Rome", sender.realm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        is_sender_subscriber = Subscription.objects.filter(
 | 
				
			||||||
 | 
					            user_profile=sender,
 | 
				
			||||||
 | 
					            recipient__type_id=rome_stream.id,
 | 
				
			||||||
 | 
					        ).exists()
 | 
				
			||||||
 | 
					        self.assertFalse(is_sender_subscriber)
 | 
				
			||||||
 | 
					        self.assertTrue(rome_stream.is_web_public)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        topic_name = 'issue'
 | 
				
			||||||
 | 
					        message_content = 'whatever'
 | 
				
			||||||
 | 
					        addressee = Addressee.for_stream_name(rome_stream.name, topic_name)
 | 
				
			||||||
 | 
					        ret = check_message(sender, client, addressee, message_content)
 | 
				
			||||||
 | 
					        self.assertEqual(ret['message'].sender.id, sender.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_bot_pm_feature(self) -> None:
 | 
					    def test_bot_pm_feature(self) -> None:
 | 
				
			||||||
        """We send a PM to a bot's owner if their bot sends a message to
 | 
					        """We send a PM to a bot's owner if their bot sends a message to
 | 
				
			||||||
        an unsubscribed stream"""
 | 
					        an unsubscribed stream"""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,6 +53,7 @@ from zerver.lib.stream_subscription import (
 | 
				
			|||||||
from zerver.lib.streams import (
 | 
					from zerver.lib.streams import (
 | 
				
			||||||
    access_stream_by_id,
 | 
					    access_stream_by_id,
 | 
				
			||||||
    access_stream_by_name,
 | 
					    access_stream_by_name,
 | 
				
			||||||
 | 
					    can_access_stream_history,
 | 
				
			||||||
    create_streams_if_needed,
 | 
					    create_streams_if_needed,
 | 
				
			||||||
    filter_stream_authorization,
 | 
					    filter_stream_authorization,
 | 
				
			||||||
    list_to_streams,
 | 
					    list_to_streams,
 | 
				
			||||||
@@ -199,6 +200,11 @@ class TestCreateStreams(ZulipTestCase):
 | 
				
			|||||||
                "name": "publicstream",
 | 
					                "name": "publicstream",
 | 
				
			||||||
                "description": "Public stream with public history",
 | 
					                "description": "Public stream with public history",
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "name": "webpublicstream",
 | 
				
			||||||
 | 
					                "description": "Web public stream",
 | 
				
			||||||
 | 
					                "is_web_public": True
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                "name": "privatestream",
 | 
					                "name": "privatestream",
 | 
				
			||||||
                "description": "Private stream with non-public history",
 | 
					                "description": "Private stream with non-public history",
 | 
				
			||||||
@@ -220,11 +226,13 @@ class TestCreateStreams(ZulipTestCase):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        created, existing = create_streams_if_needed(realm, stream_dicts)
 | 
					        created, existing = create_streams_if_needed(realm, stream_dicts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(len(created), 4)
 | 
					        self.assertEqual(len(created), 5)
 | 
				
			||||||
        self.assertEqual(len(existing), 0)
 | 
					        self.assertEqual(len(existing), 0)
 | 
				
			||||||
        for stream in created:
 | 
					        for stream in created:
 | 
				
			||||||
            if stream.name == 'publicstream':
 | 
					            if stream.name == 'publicstream':
 | 
				
			||||||
                self.assertTrue(stream.history_public_to_subscribers)
 | 
					                self.assertTrue(stream.history_public_to_subscribers)
 | 
				
			||||||
 | 
					            if stream.name == 'webpublicstream':
 | 
				
			||||||
 | 
					                self.assertTrue(stream.history_public_to_subscribers)
 | 
				
			||||||
            if stream.name == 'privatestream':
 | 
					            if stream.name == 'privatestream':
 | 
				
			||||||
                self.assertFalse(stream.history_public_to_subscribers)
 | 
					                self.assertFalse(stream.history_public_to_subscribers)
 | 
				
			||||||
            if stream.name == 'privatewithhistory':
 | 
					            if stream.name == 'privatewithhistory':
 | 
				
			||||||
@@ -4289,6 +4297,14 @@ class AccessStreamTest(ZulipTestCase):
 | 
				
			|||||||
        self.assertEqual(sub_ret.recipient, rec_ret)
 | 
					        self.assertEqual(sub_ret.recipient, rec_ret)
 | 
				
			||||||
        self.assertEqual(sub_ret.recipient.type_id, stream.id)
 | 
					        self.assertEqual(sub_ret.recipient.type_id, stream.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        stream_name = "web_public_stream"
 | 
				
			||||||
 | 
					        stream = self.make_stream(stream_name, guest_user_profile.realm, is_web_public=True)
 | 
				
			||||||
 | 
					        # Guest users have access to web public streams even if they aren't subscribed.
 | 
				
			||||||
 | 
					        (stream_ret, rec_ret, sub_ret) = access_stream_by_id(guest_user_profile, stream.id)
 | 
				
			||||||
 | 
					        self.assertTrue(can_access_stream_history(guest_user_profile, stream))
 | 
				
			||||||
 | 
					        assert sub_ret is None
 | 
				
			||||||
 | 
					        self.assertEqual(stream.id, stream_ret.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class StreamTrafficTest(ZulipTestCase):
 | 
					class StreamTrafficTest(ZulipTestCase):
 | 
				
			||||||
    def test_average_weekly_stream_traffic_calculation(self) -> None:
 | 
					    def test_average_weekly_stream_traffic_calculation(self) -> None:
 | 
				
			||||||
        # No traffic data for the stream
 | 
					        # No traffic data for the stream
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user