mirror of https://github.com/zulip/zulip.git
subscribe: Allow web public stream creation via the API.
User can now create web public stream via the /subscribe API. So, when a web public stream present in the API request does not exist, it will be created now by specifying the is_web_public parameter. The parameter would have been ignored without this commit.
This commit is contained in:
parent
eb62693d26
commit
6a78112940
|
@ -11,6 +11,11 @@ below features are supported.
|
|||
|
||||
## Changes in Zulip 5.0
|
||||
|
||||
**Feature level 98**
|
||||
|
||||
* [`POST /subscribe`](/api/subscribe): Added `is_web_public` parameter
|
||||
for requesting the creation of a web-public stream.
|
||||
|
||||
**Feature level 97**
|
||||
|
||||
* `GET /realm/emoji`, `POST /realm/emoji/{emoji_name}`, [`GET
|
||||
|
|
|
@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.4.3"
|
|||
# Changes should be accompanied by documentation explaining what the
|
||||
# new level means in templates/zerver/api/changelog.md, as well as
|
||||
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
|
||||
API_FEATURE_LEVEL = 97
|
||||
API_FEATURE_LEVEL = 98
|
||||
|
||||
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
||||
# only when going from an old version of the code to a newer version. Bump
|
||||
|
|
|
@ -153,6 +153,7 @@ def create_streams_if_needed(
|
|||
realm,
|
||||
stream_dict["name"],
|
||||
invite_only=stream_dict.get("invite_only", False),
|
||||
is_web_public=stream_dict.get("is_web_public", False),
|
||||
stream_post_policy=stream_dict.get(
|
||||
"stream_post_policy", Stream.STREAM_POST_POLICY_EVERYONE
|
||||
),
|
||||
|
@ -645,6 +646,7 @@ def list_to_streams(
|
|||
check_stream_access_for_delete_or_update(user_profile, stream, sub)
|
||||
|
||||
message_retention_days_not_none = False
|
||||
web_public_stream_requested = False
|
||||
for stream_dict in streams_raw:
|
||||
stream_name = stream_dict["name"]
|
||||
stream = existing_stream_map.get(stream_name.lower())
|
||||
|
@ -652,6 +654,9 @@ def list_to_streams(
|
|||
if stream_dict.get("message_retention_days", None) is not None:
|
||||
message_retention_days_not_none = True
|
||||
missing_stream_dicts.append(stream_dict)
|
||||
|
||||
if autocreate and stream_dict["is_web_public"]:
|
||||
web_public_stream_requested = True
|
||||
else:
|
||||
existing_streams.append(stream)
|
||||
|
||||
|
@ -673,6 +678,14 @@ def list_to_streams(
|
|||
)
|
||||
)
|
||||
|
||||
if web_public_stream_requested:
|
||||
if not user_profile.realm.web_public_streams_enabled():
|
||||
raise JsonableError(_("Web public streams are not enabled."))
|
||||
if not user_profile.is_realm_owner:
|
||||
# We only allow organization owners to create web-public streams,
|
||||
# because of their sensitive nature.
|
||||
raise OrganizationOwnerRequired()
|
||||
|
||||
if message_retention_days_not_none:
|
||||
if not user_profile.is_realm_owner:
|
||||
raise OrganizationOwnerRequired()
|
||||
|
|
|
@ -6688,6 +6688,23 @@ paths:
|
|||
type: boolean
|
||||
default: false
|
||||
example: true
|
||||
- name: is_web_public
|
||||
in: query
|
||||
description: |
|
||||
This parameter determines whether any newly created streams will be
|
||||
web public streams.
|
||||
|
||||
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
|
||||
default: false
|
||||
example: true
|
||||
- $ref: "#/components/parameters/HistoryPublicToSubscribers"
|
||||
- $ref: "#/components/parameters/StreamPostPolicy"
|
||||
- $ref: "#/components/parameters/MessageRetentionDays"
|
||||
|
|
|
@ -463,6 +463,49 @@ class StreamAdminTest(ZulipTestCase):
|
|||
self.assertTrue(stream.invite_only)
|
||||
self.assertFalse(stream.history_public_to_subscribers)
|
||||
|
||||
def test_create_web_public_stream(self) -> None:
|
||||
user_profile = self.example_user("hamlet")
|
||||
owner = self.example_user("desdemona")
|
||||
|
||||
stream_names = ["new1", "new2", "new3"]
|
||||
stream_descriptions = ["des1", "des2", "des3"]
|
||||
streams_raw: List[StreamDict] = [
|
||||
{"name": stream_name, "description": stream_description, "is_web_public": True}
|
||||
for (stream_name, stream_description) in zip(stream_names, stream_descriptions)
|
||||
]
|
||||
|
||||
# Normal user cannot create web-public streams
|
||||
with self.assertRaisesRegex(JsonableError, "Must be an organization owner"):
|
||||
list_to_streams(
|
||||
streams_raw,
|
||||
user_profile,
|
||||
autocreate=True,
|
||||
)
|
||||
|
||||
with self.settings(WEB_PUBLIC_STREAMS_ENABLED=False):
|
||||
with self.assertRaisesRegex(JsonableError, "Web public streams are not enabled."):
|
||||
list_to_streams(
|
||||
streams_raw,
|
||||
owner,
|
||||
autocreate=True,
|
||||
)
|
||||
|
||||
existing_streams, new_streams = list_to_streams(
|
||||
streams_raw,
|
||||
owner,
|
||||
autocreate=True,
|
||||
)
|
||||
|
||||
self.assert_length(new_streams, 3)
|
||||
self.assert_length(existing_streams, 0)
|
||||
|
||||
actual_stream_names = {stream.name for stream in new_streams}
|
||||
self.assertEqual(actual_stream_names, set(stream_names))
|
||||
actual_stream_descriptions = {stream.description for stream in new_streams}
|
||||
self.assertEqual(actual_stream_descriptions, set(stream_descriptions))
|
||||
for stream in new_streams:
|
||||
self.assertTrue(stream.is_web_public)
|
||||
|
||||
def test_make_stream_public_zephyr_mirror(self) -> None:
|
||||
user_profile = self.mit_user("starnine")
|
||||
self.login_user(user_profile)
|
||||
|
@ -1289,6 +1332,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||
{
|
||||
"name": "new_stream",
|
||||
"message_retention_days": 10,
|
||||
"is_web_public": False,
|
||||
}
|
||||
]
|
||||
with self.assertRaisesRegex(JsonableError, "Must be an organization owner"):
|
||||
|
@ -1298,6 +1342,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||
{
|
||||
"name": "new_stream",
|
||||
"message_retention_days": -1,
|
||||
"is_web_public": False,
|
||||
}
|
||||
]
|
||||
with self.assertRaisesRegex(JsonableError, "Must be an organization owner"):
|
||||
|
@ -1307,6 +1352,7 @@ class StreamAdminTest(ZulipTestCase):
|
|||
{
|
||||
"name": "new_stream",
|
||||
"message_retention_days": None,
|
||||
"is_web_public": False,
|
||||
}
|
||||
]
|
||||
result = list_to_streams(streams_raw, admin, autocreate=True)
|
||||
|
@ -1318,9 +1364,20 @@ class StreamAdminTest(ZulipTestCase):
|
|||
owner = self.example_user("desdemona")
|
||||
realm = owner.realm
|
||||
streams_raw = [
|
||||
{"name": "new_stream1", "message_retention_days": 10},
|
||||
{"name": "new_stream2", "message_retention_days": -1},
|
||||
{"name": "new_stream3"},
|
||||
{
|
||||
"name": "new_stream1",
|
||||
"message_retention_days": 10,
|
||||
"is_web_public": False,
|
||||
},
|
||||
{
|
||||
"name": "new_stream2",
|
||||
"message_retention_days": -1,
|
||||
"is_web_public": False,
|
||||
},
|
||||
{
|
||||
"name": "new_stream3",
|
||||
"is_web_public": False,
|
||||
},
|
||||
]
|
||||
|
||||
do_change_plan_type(realm, Realm.LIMITED, acting_user=admin)
|
||||
|
|
|
@ -451,6 +451,7 @@ def add_subscriptions_backend(
|
|||
"subscriptions", json_validator=add_subscriptions_schema
|
||||
),
|
||||
invite_only: bool = REQ(json_validator=check_bool, default=False),
|
||||
is_web_public: bool = REQ(json_validator=check_bool, default=False),
|
||||
stream_post_policy: int = REQ(
|
||||
json_validator=check_int_in(Stream.STREAM_POST_POLICY_TYPES),
|
||||
default=Stream.STREAM_POST_POLICY_EVERYONE,
|
||||
|
@ -483,6 +484,7 @@ def add_subscriptions_backend(
|
|||
stream_dict_copy["description"] = stream_dict["description"].replace("\n", " ")
|
||||
|
||||
stream_dict_copy["invite_only"] = invite_only
|
||||
stream_dict_copy["is_web_public"] = is_web_public
|
||||
stream_dict_copy["stream_post_policy"] = stream_post_policy
|
||||
stream_dict_copy["history_public_to_subscribers"] = history_public_to_subscribers
|
||||
stream_dict_copy["message_retention_days"] = parse_message_retention_days(
|
||||
|
|
Loading…
Reference in New Issue