update_stream_backend: Add ability to make streams web public.

We allow clients to make existing streams web public via the API.

This feature is still disabled via settings in production
environments, because we may have additional policy rules or UI
warnings we wish to add to this sort of conversion.
This commit is contained in:
Aman Agrawal 2020-11-10 18:45:04 +05:30 committed by Tim Abbott
parent 6a78112940
commit 5138652810
5 changed files with 102 additions and 2 deletions

View File

@ -15,6 +15,8 @@ below features are supported.
* [`POST /subscribe`](/api/subscribe): Added `is_web_public` parameter
for requesting the creation of a web-public stream.
* [`PATCH /streams/{stream_id}`](/api/update-stream): Added
`is_web_public` parameter for converting a stream into a web-public stream.
**Feature level 97**

View File

@ -4823,6 +4823,20 @@ def do_make_stream_web_public(stream: Stream) -> None:
stream.save(update_fields=["invite_only", "history_public_to_subscribers", "is_web_public"])
def do_change_stream_permission(
stream: Stream,
invite_only: Optional[bool] = None,
history_public_to_subscribers: Optional[bool] = None,
is_web_public: Optional[bool] = None,
) -> None:
# TODO: Ideally this would be just merged with do_change_stream_invite_only.
if is_web_public:
do_make_stream_web_public(stream)
else:
assert invite_only is not None
do_change_stream_invite_only(stream, invite_only, history_public_to_subscribers)
def do_change_stream_post_policy(stream: Stream, stream_post_policy: int) -> None:
stream.stream_post_policy = stream_post_policy
stream.save(update_fields=["stream_post_policy"])

View File

@ -12638,6 +12638,22 @@ paths:
type: boolean
example: true
required: false
- name: is_web_public
in: query
description: |
Change whether the stream is a web-public stream.
Note that creating web public streams requires the
`WEB_PUBLIC_STREAMS_ENABLED` [server setting][server-settings]
to be enabled on the Zulip server in question.
[server-settings]: https://zulip.readthedocs.io/en/stable/production/settings.html
**Changes**: New in Zulip 5.0 (feature level 98).
schema:
type: boolean
example: true
required: false
- $ref: "#/components/parameters/StreamPostPolicy"
- $ref: "#/components/parameters/HistoryPublicToSubscribers"
- $ref: "#/components/parameters/MessageRetentionDays"

View File

@ -544,6 +544,59 @@ class StreamAdminTest(ZulipTestCase):
self.assertTrue(stream.invite_only)
self.assertTrue(stream.history_public_to_subscribers)
def test_make_stream_web_public(self) -> None:
user_profile = self.example_user("hamlet")
self.login_user(user_profile)
realm = user_profile.realm
self.make_stream("test_stream", realm=realm)
stream_id = get_stream("test_stream", realm).id
params = {
"stream_name": orjson.dumps("test_stream").decode(),
"is_web_public": orjson.dumps(True).decode(),
"history_public_to_subscribers": orjson.dumps(True).decode(),
}
result = self.client_patch(f"/json/streams/{stream_id}", params)
self.assert_json_error(result, "Must be an organization or stream administrator")
do_change_user_role(user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
result = self.client_patch(f"/json/streams/{stream_id}", params)
self.assert_json_error(result, "Must be an organization owner")
do_change_user_role(user_profile, UserProfile.ROLE_REALM_OWNER, acting_user=None)
with self.settings(WEB_PUBLIC_STREAMS_ENABLED=False):
result = self.client_patch(f"/json/streams/{stream_id}", params)
self.assert_json_error(result, "Web public streams are not enabled.")
bad_params = {
"stream_name": orjson.dumps("test_stream").decode(),
"is_web_public": orjson.dumps(True).decode(),
"is_private": orjson.dumps(True).decode(),
"history_public_to_subscribers": orjson.dumps(True).decode(),
}
result = self.client_patch(f"/json/streams/{stream_id}", bad_params)
self.assert_json_error(result, "Invalid parameters")
bad_params = {
"stream_name": orjson.dumps("test_stream").decode(),
"is_web_public": orjson.dumps(True).decode(),
"is_private": orjson.dumps(False).decode(),
"history_public_to_subscribers": orjson.dumps(False).decode(),
}
result = self.client_patch(f"/json/streams/{stream_id}", bad_params)
self.assert_json_error(result, "Invalid parameters")
stream = get_stream("test_stream", realm)
self.assertFalse(stream.is_web_public)
result = self.client_patch(f"/json/streams/{stream_id}", params)
self.assert_json_success(result)
stream = get_stream("test_stream", realm)
self.assertTrue(stream.is_web_public)
self.assertFalse(stream.invite_only)
self.assertTrue(stream.history_public_to_subscribers)
def test_try_make_stream_public_with_private_history(self) -> None:
user_profile = self.example_user("hamlet")
self.login_user(user_profile)

View File

@ -25,8 +25,8 @@ from zerver.lib.actions import (
do_change_default_stream_group_description,
do_change_default_stream_group_name,
do_change_stream_description,
do_change_stream_invite_only,
do_change_stream_message_retention_days,
do_change_stream_permission,
do_change_stream_post_policy,
do_change_subscription_property,
do_create_default_stream_group,
@ -258,6 +258,7 @@ def update_stream_backend(
json_validator=check_int_in(Stream.STREAM_POST_POLICY_TYPES), default=None
),
history_public_to_subscribers: Optional[bool] = REQ(json_validator=check_bool, default=None),
is_web_public: Optional[bool] = REQ(json_validator=check_bool, default=None),
new_name: Optional[str] = REQ(default=None),
message_retention_days: Optional[Union[int, str]] = REQ(
json_validator=check_string_or_int, default=None
@ -308,7 +309,21 @@ def update_stream_backend(
(stream, sub) = access_stream_by_id(user_profile, stream_id)
if is_private and stream.id in default_stream_ids:
raise JsonableError(_("Default streams cannot be made private."))
do_change_stream_invite_only(stream, is_private, history_public_to_subscribers)
if is_web_public:
# Enforce restrictions on creating web-public streams.
if not user_profile.realm.web_public_streams_enabled():
raise JsonableError(_("Web public streams are not enabled."))
if not user_profile.is_realm_owner:
raise OrganizationOwnerRequired()
# Forbid parameter combinations that are inconsistent
if is_private or history_public_to_subscribers is False:
raise JsonableError(_("Invalid parameters"))
if is_private is not None or is_web_public is not None:
do_change_stream_permission(
stream, is_private, history_public_to_subscribers, is_web_public
)
return json_success()