register: Include folder data for web public streams for spectators.

Spectators would only receive data for channel folders that have
at least one web-public stream.
This commit is contained in:
Sahil Batra
2025-05-16 15:36:28 +05:30
committed by Tim Abbott
parent 509a84403b
commit 222ccac765
4 changed files with 51 additions and 6 deletions

View File

@@ -4,6 +4,7 @@ from django.utils.translation import gettext as _
from zerver.lib.exceptions import JsonableError
from zerver.lib.markdown import markdown_convert
from zerver.lib.streams import get_web_public_streams_queryset
from zerver.lib.string_validation import check_string_is_printable
from zerver.lib.timestamp import datetime_to_timestamp
from zerver.models import ChannelFolder, Realm, UserProfile
@@ -71,3 +72,12 @@ def get_channel_folder_by_id(channel_folder_id: int, realm: Realm) -> ChannelFol
return channel_folder
except ChannelFolder.DoesNotExist:
raise JsonableError(_("Invalid channel folder ID"))
def get_channel_folders_for_spectators(realm: Realm) -> list[ChannelFolderDict]:
folder_ids_for_web_public_streams = set(
get_web_public_streams_queryset(realm).values_list("folder_id", flat=True)
)
folders = ChannelFolder.objects.filter(id__in=folder_ids_for_web_public_streams)
channel_folders = [get_channel_folder_dict(channel_folder) for channel_folder in folders]
return sorted(channel_folders, key=lambda folder: folder["id"])

View File

@@ -19,7 +19,10 @@ from zerver.lib import emoji
from zerver.lib.alert_words import user_alert_words
from zerver.lib.avatar import avatar_url
from zerver.lib.bot_config import load_bot_config_template
from zerver.lib.channel_folders import get_channel_folders_in_realm
from zerver.lib.channel_folders import (
get_channel_folders_for_spectators,
get_channel_folders_in_realm,
)
from zerver.lib.compatibility import is_outdated_server
from zerver.lib.default_streams import get_default_stream_ids_for_realm
from zerver.lib.exceptions import JsonableError
@@ -765,10 +768,11 @@ def fetch_initial_state_data(
state["unsubscribed"] = sub_info.unsubscribed
state["never_subscribed"] = sub_info.never_subscribed
if want("channel_folders") and user_profile is not None:
# TODO: Spectators should get the channel folders that
# contain atleast one web-public channel.
state["channel_folders"] = get_channel_folders_in_realm(user_profile.realm, True)
if want("channel_folders"):
if user_profile is None:
state["channel_folders"] = get_channel_folders_for_spectators(realm)
else:
state["channel_folders"] = get_channel_folders_in_realm(user_profile.realm, True)
if want("update_message_flags") and want("message"):
# Keeping unread_msgs updated requires both message flag updates and

View File

@@ -15915,6 +15915,9 @@ paths:
An array of dictionaries where each dictionary describes one
of the channel folders in the organization.
Only channel folders with one or more public web channels are
visible to spectators.
**Changes**: New in Zulip 11.0 (feature level ZF-392de9).
unread_msgs:
type: object

View File

@@ -11,9 +11,11 @@ from django.test import override_settings
from django.utils.timezone import now as timezone_now
from typing_extensions import override
from zerver.actions.channel_folders import check_add_channel_folder
from zerver.actions.custom_profile_fields import try_update_realm_custom_profile_field
from zerver.actions.message_send import check_send_message
from zerver.actions.presence import do_update_user_presence
from zerver.actions.streams import do_change_stream_folder
from zerver.actions.user_settings import do_change_user_setting
from zerver.actions.users import do_change_user_role
from zerver.lib.event_schema import check_web_reload_client_event
@@ -171,7 +173,7 @@ class EventsEndpointTest(ZulipTestCase):
status_code=401,
)
with self.assert_database_query_count(14):
with self.assert_database_query_count(15):
result = self.client_post("/json/register")
result_dict = self.assert_json_success(result)
self.assertEqual(result_dict["queue_id"], None)
@@ -198,6 +200,32 @@ class EventsEndpointTest(ZulipTestCase):
status_code=400,
)
def test_channel_folders_for_spectators(self) -> None:
realm = get_realm("zulip")
iago = self.example_user("iago")
frontend_folder = check_add_channel_folder("Frontend", "", acting_user=iago)
backend_folder = check_add_channel_folder("Backend", "", acting_user=iago)
result = self.client_post("/json/register")
self.assertEqual(result.status_code, 200)
channel_folders_data = orjson.loads(result.content)["channel_folders"]
self.assert_length(channel_folders_data, 0)
web_public_stream = get_stream("Rome", realm)
do_change_stream_folder(web_public_stream, frontend_folder, acting_user=iago)
public_stream = get_stream("Verona", realm)
do_change_stream_folder(public_stream, backend_folder, acting_user=iago)
result = self.client_post("/json/register")
self.assertEqual(result.status_code, 200)
channel_folders_data = orjson.loads(result.content)["channel_folders"]
self.assert_length(channel_folders_data, 1)
self.assertEqual(channel_folders_data[0]["name"], "Frontend")
def test_events_register_endpoint_all_public_streams_access(self) -> None:
guest_user = self.example_user("polonius")
normal_user = self.example_user("hamlet")