mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 21:43:21 +00:00
streams: Remove API support for changing stream_post_policy.
This commit is contained in:
@@ -40,6 +40,10 @@ format used by the Zulip server that they are interacting with.
|
||||
this backwards-compatible `stream_post_policy` value now contains the
|
||||
superset of the true value that best approximates the actual permission
|
||||
setting.
|
||||
* [`POST /users/me/subscriptions`](/api/subscribe),
|
||||
[`PATCH /streams/{stream_id}`](/api/update-stream): Removed
|
||||
`stream_post_policy` and `is_announcement_only` properties, as the permission
|
||||
to post in the channel is now controlled by `can_send_message_group` setting.
|
||||
|
||||
**Feature level 332**
|
||||
|
||||
|
||||
@@ -1355,82 +1355,6 @@ def send_stream_posting_permission_update_notification(
|
||||
)
|
||||
|
||||
|
||||
def send_change_stream_post_policy_notification(
|
||||
stream: Stream, *, old_post_policy: int, new_post_policy: int, acting_user: UserProfile
|
||||
) -> None:
|
||||
sender = get_system_bot(settings.NOTIFICATION_BOT, acting_user.realm_id)
|
||||
user_mention = silent_mention_syntax_for_user(acting_user)
|
||||
|
||||
with override_language(stream.realm.default_language):
|
||||
notification_string = _(
|
||||
"{user} changed the [posting permissions]({help_link}) "
|
||||
"for this channel:\n\n"
|
||||
"* **Old permissions**: {old_policy}.\n"
|
||||
"* **New permissions**: {new_policy}.\n"
|
||||
)
|
||||
notification_string = notification_string.format(
|
||||
user=user_mention,
|
||||
help_link="/help/channel-posting-policy",
|
||||
old_policy=Stream.POST_POLICIES[old_post_policy],
|
||||
new_policy=Stream.POST_POLICIES[new_post_policy],
|
||||
)
|
||||
internal_send_stream_message(
|
||||
sender, stream, str(Realm.STREAM_EVENTS_NOTIFICATION_TOPIC_NAME), notification_string
|
||||
)
|
||||
|
||||
|
||||
@transaction.atomic(durable=True)
|
||||
def do_change_stream_post_policy(
|
||||
stream: Stream, stream_post_policy: int, *, acting_user: UserProfile
|
||||
) -> None:
|
||||
old_post_policy = stream.stream_post_policy
|
||||
stream.stream_post_policy = stream_post_policy
|
||||
stream.save(update_fields=["stream_post_policy"])
|
||||
RealmAuditLog.objects.create(
|
||||
realm=stream.realm,
|
||||
acting_user=acting_user,
|
||||
modified_stream=stream,
|
||||
event_type=AuditLogEventType.CHANNEL_PROPERTY_CHANGED,
|
||||
event_time=timezone_now(),
|
||||
extra_data={
|
||||
RealmAuditLog.OLD_VALUE: old_post_policy,
|
||||
RealmAuditLog.NEW_VALUE: stream_post_policy,
|
||||
"property": "stream_post_policy",
|
||||
},
|
||||
)
|
||||
|
||||
event = dict(
|
||||
op="update",
|
||||
type="stream",
|
||||
property="stream_post_policy",
|
||||
value=stream_post_policy,
|
||||
stream_id=stream.id,
|
||||
name=stream.name,
|
||||
)
|
||||
send_event_on_commit(stream.realm, event, can_access_stream_user_ids(stream))
|
||||
|
||||
# Backwards-compatibility code: We removed the
|
||||
# is_announcement_only property in early 2020, but we send a
|
||||
# duplicate event for legacy mobile clients that might want the
|
||||
# data.
|
||||
event = dict(
|
||||
op="update",
|
||||
type="stream",
|
||||
property="is_announcement_only",
|
||||
value=stream.stream_post_policy == Stream.STREAM_POST_POLICY_ADMINS,
|
||||
stream_id=stream.id,
|
||||
name=stream.name,
|
||||
)
|
||||
send_event_on_commit(stream.realm, event, can_access_stream_user_ids(stream))
|
||||
|
||||
send_change_stream_post_policy_notification(
|
||||
stream,
|
||||
old_post_policy=old_post_policy,
|
||||
new_post_policy=stream_post_policy,
|
||||
acting_user=acting_user,
|
||||
)
|
||||
|
||||
|
||||
@transaction.atomic(durable=True)
|
||||
def do_rename_stream(stream: Stream, new_name: str, user_profile: UserProfile) -> None:
|
||||
old_name = stream.name
|
||||
|
||||
@@ -804,7 +804,6 @@ def update_stream(client: Client, stream_id: int) -> None:
|
||||
# Update settings for the channel with a given ID.
|
||||
request = {
|
||||
"stream_id": stream_id,
|
||||
"stream_post_policy": 2,
|
||||
"is_private": True,
|
||||
}
|
||||
result = client.update_stream(request)
|
||||
|
||||
@@ -10214,13 +10214,16 @@ paths:
|
||||
Note that the ability to subscribe oneself and/or other users to a specified
|
||||
channel depends on the [channel's privacy settings](/help/channel-permissions).
|
||||
|
||||
**Changes**: Before Zulip 8.0 (feature level 208), if a user
|
||||
specified by the [`principals`][principals-param] parameter was
|
||||
a deactivated user, or did not exist, then an HTTP status code
|
||||
of 403 was returned with `code: "UNAUTHORIZED_PRINCIPAL"` in the
|
||||
error response. As of this feature level, an HTTP status code of
|
||||
400 is returned with `code: "BAD_REQUEST"` in the error response
|
||||
for these cases.
|
||||
**Changes**: Removed `stream_post_policy` and `is_announcement_only`
|
||||
parameters in Zulip 10.0 (feature level 333), as permission to post
|
||||
in the channel is now controlled by `can_send_message_group`.
|
||||
|
||||
Before Zulip 8.0 (feature level 208), if a user specified by the
|
||||
[`principals`][principals-param] parameter was a deactivated user,
|
||||
or did not exist, then an HTTP status code of 403 was returned with
|
||||
`code: "UNAUTHORIZED_PRINCIPAL"` in the error response. As of this
|
||||
feature level, an HTTP status code of 400 is returned with
|
||||
`code: "BAD_REQUEST"` in the error response for these cases.
|
||||
|
||||
[principals-param]: /api/subscribe#parameter-principals
|
||||
x-curl-examples-parameters:
|
||||
@@ -10347,8 +10350,6 @@ paths:
|
||||
example: true
|
||||
history_public_to_subscribers:
|
||||
$ref: "#/components/schemas/HistoryPublicToSubscribers"
|
||||
stream_post_policy:
|
||||
$ref: "#/components/schemas/ChannelPostPolicy"
|
||||
message_retention_days:
|
||||
$ref: "#/components/schemas/MessageRetentionDays"
|
||||
can_remove_subscribers_group:
|
||||
@@ -10376,8 +10377,6 @@ paths:
|
||||
contentType: application/json
|
||||
history_public_to_subscribers:
|
||||
contentType: application/json
|
||||
stream_post_policy:
|
||||
contentType: application/json
|
||||
can_remove_subscribers_group:
|
||||
contentType: application/json
|
||||
can_administer_channel_group:
|
||||
@@ -19970,6 +19969,10 @@ paths:
|
||||
Note that an organization administrator's ability to change a
|
||||
[private channel's permissions](/help/channel-permissions#private-channels)
|
||||
depends on them being subscribed to the channel.
|
||||
|
||||
**Changes**: Removed `stream_post_policy` and `is_announcement_only`
|
||||
parameters in Zulip 10.0 (feature level 333), as permission to post
|
||||
in the channel is now controlled by `can_send_message_group`.
|
||||
x-curl-examples-parameters:
|
||||
oneOf:
|
||||
- type: include
|
||||
@@ -20017,15 +20020,6 @@ paths:
|
||||
Change whether the channel is a private channel.
|
||||
type: boolean
|
||||
example: true
|
||||
is_announcement_only:
|
||||
deprecated: true
|
||||
description: |
|
||||
Whether the channel is limited to announcements.
|
||||
|
||||
**Changes**: Deprecated in Zulip 3.0 (feature level 1). Clients
|
||||
should use `stream_post_policy` instead.
|
||||
type: boolean
|
||||
example: true
|
||||
is_web_public:
|
||||
description: |
|
||||
Change whether the channel is a web-public channel.
|
||||
@@ -20070,8 +20064,6 @@ paths:
|
||||
could only be changed using the [dedicated API endpoint](/api/add-default-stream).
|
||||
type: boolean
|
||||
example: false
|
||||
stream_post_policy:
|
||||
$ref: "#/components/schemas/ChannelPostPolicy"
|
||||
message_retention_days:
|
||||
$ref: "#/components/schemas/MessageRetentionDays"
|
||||
can_remove_subscribers_group:
|
||||
@@ -20192,16 +20184,12 @@ paths:
|
||||
encoding:
|
||||
is_private:
|
||||
contentType: application/json
|
||||
is_announcement_only:
|
||||
contentType: application/json
|
||||
is_web_public:
|
||||
contentType: application/json
|
||||
history_public_to_subscribers:
|
||||
contentType: application/json
|
||||
is_default_stream:
|
||||
contentType: application/json
|
||||
stream_post_policy:
|
||||
contentType: application/json
|
||||
can_remove_subscribers_group:
|
||||
contentType: application/json
|
||||
can_administer_channel_group:
|
||||
@@ -24677,23 +24665,6 @@ components:
|
||||
throw an error.
|
||||
type: string
|
||||
example: Hello
|
||||
ChannelPostPolicy:
|
||||
description: |
|
||||
[Policy][permission-level] for which users can post messages to the channel.
|
||||
|
||||
- 1 = Any user can post.
|
||||
- 2 = Only administrators can post.
|
||||
- 3 = Only [full members][calc-full-member] can post.
|
||||
- 4 = Only moderators can post.
|
||||
|
||||
**Changes**: New in Zulip 3.0 (feature level 1), replacing the previous
|
||||
`is_announcement_only` boolean.
|
||||
|
||||
[permission-level]: /api/roles-and-permissions#permission-levels
|
||||
[calc-full-member]: /api/roles-and-permissions#determining-if-a-user-is-a-full-member
|
||||
type: integer
|
||||
default: 1
|
||||
example: 2
|
||||
HistoryPublicToSubscribers:
|
||||
description: |
|
||||
Whether the channel's message history should be available to
|
||||
|
||||
@@ -493,7 +493,6 @@ class TestCreateStreams(ZulipTestCase):
|
||||
"invite_only": "false",
|
||||
"announce": "true",
|
||||
"principals": orjson.dumps([iago.id, aaron.id, cordelia.id, hamlet.id]).decode(),
|
||||
"stream_post_policy": "1",
|
||||
}
|
||||
|
||||
response = self.client_post("/json/users/me/subscriptions", data)
|
||||
@@ -2231,127 +2230,6 @@ class StreamAdminTest(ZulipTestCase):
|
||||
)
|
||||
self.assert_json_error(result, "You do not have permission to administer this channel.")
|
||||
|
||||
def test_change_to_stream_post_policy_admins(self) -> None:
|
||||
user_profile = self.example_user("hamlet")
|
||||
self.login_user(user_profile)
|
||||
|
||||
self.subscribe(user_profile, "stream_name1")
|
||||
do_change_user_role(user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
|
||||
|
||||
stream_id = get_stream("stream_name1", user_profile.realm).id
|
||||
result = self.client_patch(
|
||||
f"/json/streams/{stream_id}", {"is_announcement_only": orjson.dumps(True).decode()}
|
||||
)
|
||||
self.assert_json_success(result)
|
||||
stream = get_stream("stream_name1", user_profile.realm)
|
||||
self.assertEqual(stream.stream_post_policy, Stream.STREAM_POST_POLICY_ADMINS)
|
||||
|
||||
messages = get_topic_messages(user_profile, stream, "channel events")
|
||||
expected_notification = (
|
||||
f"@_**{user_profile.full_name}|{user_profile.id}** changed the "
|
||||
"[posting permissions](/help/channel-posting-policy) for this channel:\n\n"
|
||||
"* **Old permissions**: All channel members can post.\n"
|
||||
"* **New permissions**: Only organization administrators can post."
|
||||
)
|
||||
self.assertEqual(messages[-1].content, expected_notification)
|
||||
|
||||
realm_audit_log = RealmAuditLog.objects.filter(
|
||||
event_type=AuditLogEventType.CHANNEL_PROPERTY_CHANGED,
|
||||
modified_stream=stream,
|
||||
).last()
|
||||
assert realm_audit_log is not None
|
||||
expected_extra_data = {
|
||||
RealmAuditLog.OLD_VALUE: Stream.STREAM_POST_POLICY_EVERYONE,
|
||||
RealmAuditLog.NEW_VALUE: Stream.STREAM_POST_POLICY_ADMINS,
|
||||
"property": "stream_post_policy",
|
||||
}
|
||||
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
||||
|
||||
def test_change_stream_post_policy_requires_admin(self) -> None:
|
||||
user_profile = self.example_user("hamlet")
|
||||
self.login_user(user_profile)
|
||||
|
||||
self.make_stream("stream_name1")
|
||||
stream = self.subscribe(user_profile, "stream_name1")
|
||||
|
||||
do_change_user_role(user_profile, UserProfile.ROLE_MEMBER, acting_user=None)
|
||||
|
||||
do_set_realm_property(user_profile.realm, "waiting_period_threshold", 10, acting_user=None)
|
||||
|
||||
def test_non_admin(how_old: int, is_new: bool, policy: int) -> None:
|
||||
user_profile.date_joined = timezone_now() - timedelta(days=how_old)
|
||||
user_profile.save()
|
||||
self.assertEqual(user_profile.is_provisional_member, is_new)
|
||||
stream = get_stream("stream_name1", user_profile.realm)
|
||||
self.assertFalse(is_user_in_group(stream.can_administer_channel_group, user_profile))
|
||||
result = self.client_patch(
|
||||
f"/json/streams/{stream.id}", {"stream_post_policy": orjson.dumps(policy).decode()}
|
||||
)
|
||||
self.assert_json_error(result, "You do not have permission to administer this channel.")
|
||||
|
||||
policies = [
|
||||
Stream.STREAM_POST_POLICY_ADMINS,
|
||||
Stream.STREAM_POST_POLICY_MODERATORS,
|
||||
Stream.STREAM_POST_POLICY_RESTRICT_NEW_MEMBERS,
|
||||
]
|
||||
|
||||
for policy in policies:
|
||||
test_non_admin(how_old=15, is_new=False, policy=policy)
|
||||
test_non_admin(how_old=5, is_new=True, policy=policy)
|
||||
|
||||
do_change_user_role(user_profile, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
|
||||
|
||||
for policy in policies:
|
||||
stream = get_stream("stream_name1", user_profile.realm)
|
||||
old_post_policy = stream.stream_post_policy
|
||||
result = self.client_patch(
|
||||
f"/json/streams/{stream.id}", {"stream_post_policy": orjson.dumps(policy).decode()}
|
||||
)
|
||||
self.assert_json_success(result)
|
||||
stream = get_stream("stream_name1", user_profile.realm)
|
||||
self.assertEqual(stream.stream_post_policy, policy)
|
||||
|
||||
messages = get_topic_messages(user_profile, stream, "channel events")
|
||||
expected_notification = (
|
||||
f"@_**{user_profile.full_name}|{user_profile.id}** changed the "
|
||||
"[posting permissions](/help/channel-posting-policy) for this channel:\n\n"
|
||||
f"* **Old permissions**: {Stream.POST_POLICIES[old_post_policy]}.\n"
|
||||
f"* **New permissions**: {Stream.POST_POLICIES[policy]}."
|
||||
)
|
||||
|
||||
self.assertEqual(messages[-1].content, expected_notification)
|
||||
|
||||
realm_audit_log = RealmAuditLog.objects.filter(
|
||||
event_type=AuditLogEventType.CHANNEL_PROPERTY_CHANGED,
|
||||
modified_stream=stream,
|
||||
).last()
|
||||
assert realm_audit_log is not None
|
||||
expected_extra_data = {
|
||||
RealmAuditLog.OLD_VALUE: old_post_policy,
|
||||
RealmAuditLog.NEW_VALUE: policy,
|
||||
"property": "stream_post_policy",
|
||||
}
|
||||
self.assertEqual(realm_audit_log.extra_data, expected_extra_data)
|
||||
|
||||
# Test non-admin should be able to change policy if they are
|
||||
# part of can_administer_channel_group
|
||||
do_change_user_role(user_profile, UserProfile.ROLE_MEMBER, acting_user=None)
|
||||
user_profile_group = check_add_user_group(
|
||||
user_profile.realm, "user_profile_group", [user_profile], acting_user=user_profile
|
||||
)
|
||||
do_change_stream_group_based_setting(
|
||||
stream,
|
||||
"can_administer_channel_group",
|
||||
user_profile_group,
|
||||
acting_user=None,
|
||||
)
|
||||
stream = get_stream("stream_name1", user_profile.realm)
|
||||
old_post_policy = stream.stream_post_policy
|
||||
result = self.client_patch(
|
||||
f"/json/streams/{stream.id}", {"stream_post_policy": orjson.dumps(policies[0]).decode()}
|
||||
)
|
||||
self.assert_json_success(result)
|
||||
|
||||
def test_change_stream_message_retention_days_notifications(self) -> None:
|
||||
user_profile = self.example_user("desdemona")
|
||||
self.login_user(user_profile)
|
||||
|
||||
@@ -35,7 +35,6 @@ from zerver.actions.streams import (
|
||||
do_change_stream_group_based_setting,
|
||||
do_change_stream_message_retention_days,
|
||||
do_change_stream_permission,
|
||||
do_change_stream_post_policy,
|
||||
do_change_subscription_property,
|
||||
do_deactivate_stream,
|
||||
do_rename_stream,
|
||||
@@ -83,7 +82,7 @@ from zerver.lib.topic import (
|
||||
messages_for_topic,
|
||||
)
|
||||
from zerver.lib.typed_endpoint import ApiParamConfig, PathOnly, typed_endpoint
|
||||
from zerver.lib.typed_endpoint_validators import check_color, check_int_in_validator
|
||||
from zerver.lib.typed_endpoint_validators import check_color
|
||||
from zerver.lib.types import AnonymousSettingGroupDict
|
||||
from zerver.lib.user_groups import (
|
||||
GroupSettingChangeRequest,
|
||||
@@ -254,15 +253,7 @@ def update_stream_backend(
|
||||
description: Annotated[str, StringConstraints(max_length=Stream.MAX_DESCRIPTION_LENGTH)]
|
||||
| None = None,
|
||||
is_private: Json[bool] | None = None,
|
||||
is_announcement_only: Json[bool] | None = None,
|
||||
is_default_stream: Json[bool] | None = None,
|
||||
stream_post_policy: Json[
|
||||
Annotated[
|
||||
int,
|
||||
check_int_in_validator(Stream.STREAM_POST_POLICY_TYPES),
|
||||
]
|
||||
]
|
||||
| None = None,
|
||||
history_public_to_subscribers: Json[bool] | None = None,
|
||||
is_web_public: Json[bool] | None = None,
|
||||
new_name: str | None = None,
|
||||
@@ -390,16 +381,6 @@ def update_stream_backend(
|
||||
# are only changing the casing of the stream name).
|
||||
check_stream_name_available(user_profile.realm, new_name)
|
||||
do_rename_stream(stream, new_name, user_profile)
|
||||
if is_announcement_only is not None:
|
||||
# is_announcement_only is a legacy way to specify
|
||||
# stream_post_policy. We can probably just delete this code,
|
||||
# since we're not aware of clients that used it, but we're
|
||||
# keeping it for backwards-compatibility for now.
|
||||
stream_post_policy = Stream.STREAM_POST_POLICY_EVERYONE
|
||||
if is_announcement_only:
|
||||
stream_post_policy = Stream.STREAM_POST_POLICY_ADMINS
|
||||
if stream_post_policy is not None:
|
||||
do_change_stream_post_policy(stream, stream_post_policy, acting_user=user_profile)
|
||||
|
||||
request_settings_dict = locals()
|
||||
for setting_name, permission_configuration in Stream.stream_permission_group_settings.items():
|
||||
@@ -591,9 +572,6 @@ def add_subscriptions_backend(
|
||||
invite_only: Json[bool] = False,
|
||||
is_web_public: Json[bool] = False,
|
||||
is_default_stream: Json[bool] = False,
|
||||
stream_post_policy: Json[
|
||||
Annotated[int, check_int_in_validator(Stream.STREAM_POST_POLICY_TYPES)]
|
||||
] = Stream.STREAM_POST_POLICY_EVERYONE,
|
||||
history_public_to_subscribers: Json[bool] | None = None,
|
||||
message_retention_days: Json[str] | Json[int] = RETENTION_DEFAULT,
|
||||
can_administer_channel_group: Json[int | AnonymousSettingGroupDict] | None = None,
|
||||
@@ -653,7 +631,6 @@ def add_subscriptions_backend(
|
||||
|
||||
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(
|
||||
message_retention_days, Stream.MESSAGE_RETENTION_SPECIAL_VALUES_MAP
|
||||
|
||||
Reference in New Issue
Block a user