mirror of https://github.com/zulip/zulip.git
topic_mentions: Fix restriction rule for @-topic mentions.
Now, the topic wildcard mention follows the following rules: * If the topic has less than 15 participants , anyone can use @ topic mentions. * For more than 15, the org setting 'wildcard_mention_policy' determines who can use @ topic mentions. Earlier, topic wildcard mentions followed the same restriction as stream wildcard mentions, which was incorrect. Fixes part of #27700.
This commit is contained in:
parent
31a731469d
commit
49388d5d3d
|
@ -20,6 +20,16 @@ format used by the Zulip server that they are interacting with.
|
|||
|
||||
## Changes in Zulip 8.0
|
||||
|
||||
**Feature level 229**
|
||||
|
||||
* [`PATCH /messages/{message_id}`](/api/update-message), [`POST
|
||||
/messages`](/api/send-message): Topic wildcard mentions involving
|
||||
large numbers of participants are now restricted by
|
||||
`wildcard_mention_policy`. The server now uses the
|
||||
`STREAM_WILDCARD_MENTION_NOT_ALLOWED` and
|
||||
`TOPIC_WILDCARD_MENTION_NOT_ALLOWED` error codes when a message is
|
||||
rejected because of `wildcard_mention_policy`.
|
||||
|
||||
**Feature level 228**
|
||||
|
||||
* [`GET /events`](/api/get-events): `realm_user` events with `op: "update"`
|
||||
|
|
|
@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
|
|||
# Changes should be accompanied by documentation explaining what the
|
||||
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
||||
# entries in the endpoint's documentation in `zulip.yaml`.
|
||||
API_FEATURE_LEVEL = 228
|
||||
API_FEATURE_LEVEL = 229
|
||||
|
||||
# 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
|
||||
|
|
|
@ -5,6 +5,7 @@ import $ from "jquery";
|
|||
import _ from "lodash";
|
||||
|
||||
import render_success_message_scheduled_banner from "../templates/compose_banner/success_message_scheduled_banner.hbs";
|
||||
import render_wildcard_mention_not_allowed_error from "../templates/compose_banner/wildcard_mention_not_allowed_error.hbs";
|
||||
|
||||
import * as channel from "./channel";
|
||||
import * as compose_banner from "./compose_banner";
|
||||
|
@ -180,16 +181,26 @@ export function send_message(request = create_message_object()) {
|
|||
send_message_success(request, data);
|
||||
}
|
||||
|
||||
function error(response) {
|
||||
// If we're not local echo'ing messages, or if this message was not
|
||||
// locally echoed, show error in compose box
|
||||
function error(response, server_error_code) {
|
||||
// Error callback for failed message send attempts.
|
||||
if (!locally_echoed) {
|
||||
if (server_error_code === "TOPIC_WILDCARD_MENTION_NOT_ALLOWED") {
|
||||
// The topic wildcard mention permission code path has
|
||||
// a special error.
|
||||
const new_row = render_wildcard_mention_not_allowed_error({
|
||||
banner_type: compose_banner.ERROR,
|
||||
classname: compose_banner.CLASSNAMES.wildcards_not_allowed,
|
||||
});
|
||||
compose_banner.append_compose_banner_to_banner_list(new_row, $("#compose_banners"));
|
||||
} else {
|
||||
compose_banner.show_error_message(
|
||||
response,
|
||||
compose_banner.CLASSNAMES.generic_compose_error,
|
||||
$("#compose_banners"),
|
||||
$("textarea#compose-textarea"),
|
||||
);
|
||||
}
|
||||
|
||||
// For messages that were not locally echoed, we're
|
||||
// responsible for hiding the compose spinner to restore
|
||||
// the compose box so one can send a next message.
|
||||
|
|
|
@ -96,7 +96,7 @@ function resend_message(message, $row, {on_send_message_success, send_message})
|
|||
failed_message_success(message_id);
|
||||
}
|
||||
|
||||
function on_error(response) {
|
||||
function on_error(response, _server_error_code) {
|
||||
message_send_error(message.id, response);
|
||||
setTimeout(() => {
|
||||
hide_retry_spinner($row);
|
||||
|
|
|
@ -85,13 +85,22 @@ function contains_problematic_linkifier({content, get_linkifier_map}) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function contains_topic_wildcard_mention(content) {
|
||||
// If the content has topic wildcard mention (@**topic**) then don't
|
||||
// render it locally. We have only server-side restriction check for
|
||||
// @topic mention. This helps to show the error message (no permission)
|
||||
// via the compose banner and not to local-echo then fail due to restriction.
|
||||
return content.includes("@**topic**");
|
||||
}
|
||||
|
||||
function content_contains_backend_only_syntax({content, get_linkifier_map}) {
|
||||
// Try to guess whether or not a message contains syntax that only the
|
||||
// backend Markdown processor can correctly handle.
|
||||
// If it doesn't, we can immediately render it client-side for local echo.
|
||||
return (
|
||||
contains_preview_link(content) ||
|
||||
contains_problematic_linkifier({content, get_linkifier_map})
|
||||
contains_problematic_linkifier({content, get_linkifier_map}) ||
|
||||
contains_topic_wildcard_mention(content)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import ClipboardJS from "clipboard";
|
|||
import $ from "jquery";
|
||||
|
||||
import * as resolved_topic from "../shared/src/resolved_topic";
|
||||
import render_wildcard_mention_not_allowed_error from "../templates/compose_banner/wildcard_mention_not_allowed_error.hbs";
|
||||
import render_delete_message_modal from "../templates/confirm_dialog/confirm_delete_message.hbs";
|
||||
import render_confirm_moving_messages_modal from "../templates/confirm_dialog/confirm_moving_messages.hbs";
|
||||
import render_message_edit_form from "../templates/message_edit_form.hbs";
|
||||
|
@ -1070,13 +1071,23 @@ export function save_message_row_edit($row) {
|
|||
|
||||
hide_message_edit_spinner($row);
|
||||
if (xhr.readyState !== 0) {
|
||||
const $container = compose_banner.get_compose_banner_container(
|
||||
$row.find("textarea"),
|
||||
);
|
||||
|
||||
if (xhr.responseJSON?.code === "TOPIC_WILDCARD_MENTION_NOT_ALLOWED") {
|
||||
const new_row = render_wildcard_mention_not_allowed_error({
|
||||
banner_type: compose_banner.ERROR,
|
||||
classname: compose_banner.CLASSNAMES.wildcards_not_allowed,
|
||||
});
|
||||
compose_banner.append_compose_banner_to_banner_list(new_row, $container);
|
||||
return;
|
||||
}
|
||||
|
||||
const message = channel.xhr_error_message(
|
||||
$t({defaultMessage: "Error editing message"}),
|
||||
xhr,
|
||||
);
|
||||
const $container = compose_banner.get_compose_banner_container(
|
||||
$row.find("textarea"),
|
||||
);
|
||||
compose_banner.show_error_message(
|
||||
message,
|
||||
compose_banner.CLASSNAMES.generic_compose_error,
|
||||
|
|
|
@ -71,7 +71,7 @@ export function send_message(request, on_success, error) {
|
|||
}
|
||||
|
||||
const response = channel.xhr_error_message("Error sending message", xhr);
|
||||
error(response);
|
||||
error(response, xhr.responseJSON?.code);
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
|
@ -97,7 +97,7 @@ export function reply_message(opts) {
|
|||
// already handles things like reporting times to the server.)
|
||||
}
|
||||
|
||||
function error() {
|
||||
function error(_response, _server_error_code) {
|
||||
// TODO: In our current use case, which is widgets, to meaningfully
|
||||
// handle errors, we would want the widget to provide some
|
||||
// kind of callback to us so it can do some appropriate UI.
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
{{#> compose_banner }}
|
||||
<p class="banner_message">
|
||||
{{#if stream_wildcard_mention}}
|
||||
{{#tr}}You do not have permission to use <b>@{stream_wildcard_mention}</b> mentions in this stream.{{/tr}}
|
||||
{{else}}
|
||||
{{#tr}}You do not have permission to use <b>@topic</b> mentions in this topic.{{/tr}}
|
||||
{{/if}}
|
||||
</p>
|
||||
{{/compose_banner}}
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<label for="realm_wildcard_mention_policy" class="dropdown-title">{{t "Who can use @all/@everyone mentions in large streams" }}
|
||||
<label for="realm_wildcard_mention_policy" class="dropdown-title">{{t "Who can notify a large number of users with a wildcard mention" }}
|
||||
{{> ../help_link_widget link="/help/restrict-wildcard-mentions" }}
|
||||
</label>
|
||||
<select name="realm_wildcard_mention_policy" id="id_realm_wildcard_mention_policy" class="prop-element settings_select bootstrap-focus-style" data-setting-widget-type="number">
|
||||
|
|
|
@ -100,6 +100,34 @@ run_test("transmit_message_ajax_reload_pending", () => {
|
|||
assert.ok(reload_initiated);
|
||||
});
|
||||
|
||||
run_test("topic wildcard mention not allowed", ({override}) => {
|
||||
/* istanbul ignore next */
|
||||
const success = () => {
|
||||
throw new Error("unexpected success");
|
||||
};
|
||||
|
||||
/* istanbul ignore next */
|
||||
const error = (_response, server_error_code) => {
|
||||
assert.equal(server_error_code, "TOPIC_WILDCARD_MENTION_NOT_ALLOWED");
|
||||
};
|
||||
|
||||
override(reload_state, "is_pending", () => false);
|
||||
|
||||
const request = {foo: "bar"};
|
||||
override(channel, "post", (opts) => {
|
||||
assert.equal(opts.url, "/json/messages");
|
||||
assert.equal(opts.data.foo, "bar");
|
||||
const xhr = {
|
||||
responseJSON: {
|
||||
code: "TOPIC_WILDCARD_MENTION_NOT_ALLOWED",
|
||||
},
|
||||
};
|
||||
opts.error(xhr, "bad request");
|
||||
});
|
||||
|
||||
transmit.send_message(request, success, error);
|
||||
});
|
||||
|
||||
run_test("reply_message_stream", ({override}) => {
|
||||
const social_stream_id = 555;
|
||||
stream_data.add_sub({
|
||||
|
|
|
@ -22,7 +22,12 @@ from zerver.actions.message_send import (
|
|||
)
|
||||
from zerver.actions.uploads import check_attachment_reference_change
|
||||
from zerver.actions.user_topics import bulk_do_set_user_topic_visibility_policy
|
||||
from zerver.lib.exceptions import JsonableError, MessageMoveError
|
||||
from zerver.lib.exceptions import (
|
||||
JsonableError,
|
||||
MessageMoveError,
|
||||
StreamWildcardMentionNotAllowedError,
|
||||
TopicWildcardMentionNotAllowedError,
|
||||
)
|
||||
from zerver.lib.markdown import MessageRenderingResult, topic_links
|
||||
from zerver.lib.markdown import version as markdown_version
|
||||
from zerver.lib.mention import MentionBackend, MentionData, silent_mention_syntax_for_user
|
||||
|
@ -31,9 +36,10 @@ from zerver.lib.message import (
|
|||
bulk_access_messages,
|
||||
check_user_group_mention_allowed,
|
||||
normalize_body,
|
||||
stream_wildcard_mention_allowed,
|
||||
topic_wildcard_mention_allowed,
|
||||
truncate_topic,
|
||||
update_to_dict_cache,
|
||||
wildcard_mention_allowed,
|
||||
)
|
||||
from zerver.lib.queue import queue_json_publish
|
||||
from zerver.lib.stream_subscription import get_active_subscriptions_for_stream_id
|
||||
|
@ -51,6 +57,7 @@ from zerver.lib.topic import (
|
|||
TOPIC_LINKS,
|
||||
TOPIC_NAME,
|
||||
messages_for_topic,
|
||||
participants_for_topic,
|
||||
save_message_for_edit_use_case,
|
||||
update_edit_history,
|
||||
update_messages_for_topic_edit,
|
||||
|
@ -1274,12 +1281,19 @@ def check_update_message(
|
|||
)
|
||||
links_for_embed |= rendering_result.links_for_preview
|
||||
|
||||
if message.is_stream_message() and rendering_result.has_wildcard_mention():
|
||||
if message.is_stream_message() and rendering_result.mentions_stream_wildcard:
|
||||
stream = access_stream_by_id(user_profile, message.recipient.type_id)[0]
|
||||
if not wildcard_mention_allowed(message.sender, stream, message.realm):
|
||||
raise JsonableError(
|
||||
_("You do not have permission to use wildcard mentions in this stream.")
|
||||
if not stream_wildcard_mention_allowed(message.sender, stream, message.realm):
|
||||
raise StreamWildcardMentionNotAllowedError
|
||||
|
||||
if message.is_stream_message() and rendering_result.mentions_topic_wildcard:
|
||||
topic_participant_count = len(
|
||||
participants_for_topic(message.realm.id, message.recipient.id, message.topic_name())
|
||||
)
|
||||
if not topic_wildcard_mention_allowed(
|
||||
message.sender, topic_participant_count, message.realm
|
||||
):
|
||||
raise TopicWildcardMentionNotAllowedError
|
||||
|
||||
if rendering_result.mentions_user_group_ids:
|
||||
mentioned_group_ids = list(rendering_result.mentions_user_group_ids)
|
||||
|
|
|
@ -39,7 +39,9 @@ from zerver.lib.exceptions import (
|
|||
JsonableError,
|
||||
MarkdownRenderingError,
|
||||
StreamDoesNotExistError,
|
||||
StreamWildcardMentionNotAllowedError,
|
||||
StreamWithIDDoesNotExistError,
|
||||
TopicWildcardMentionNotAllowedError,
|
||||
ZephyrMessageAlreadySentError,
|
||||
)
|
||||
from zerver.lib.markdown import MessageRenderingResult
|
||||
|
@ -52,9 +54,10 @@ from zerver.lib.message import (
|
|||
normalize_body,
|
||||
render_markdown,
|
||||
set_visibility_policy_possible,
|
||||
stream_wildcard_mention_allowed,
|
||||
topic_wildcard_mention_allowed,
|
||||
truncate_topic,
|
||||
visibility_policy_for_send_message,
|
||||
wildcard_mention_allowed,
|
||||
)
|
||||
from zerver.lib.muted_users import get_muting_users
|
||||
from zerver.lib.notification_data import (
|
||||
|
@ -1710,12 +1713,18 @@ def check_message(
|
|||
|
||||
if (
|
||||
stream is not None
|
||||
and message_send_dict.rendering_result.has_wildcard_mention()
|
||||
and not wildcard_mention_allowed(sender, stream, realm)
|
||||
and message_send_dict.rendering_result.mentions_stream_wildcard
|
||||
and not stream_wildcard_mention_allowed(sender, stream, realm)
|
||||
):
|
||||
raise JsonableError(
|
||||
_("You do not have permission to use wildcard mentions in this stream.")
|
||||
)
|
||||
raise StreamWildcardMentionNotAllowedError
|
||||
|
||||
topic_participant_count = len(message_send_dict.topic_participant_user_ids)
|
||||
if (
|
||||
stream is not None
|
||||
and message_send_dict.rendering_result.mentions_topic_wildcard
|
||||
and not topic_wildcard_mention_allowed(sender, topic_participant_count, realm)
|
||||
):
|
||||
raise TopicWildcardMentionNotAllowedError
|
||||
|
||||
if message_send_dict.rendering_result.mentions_user_group_ids:
|
||||
mentioned_group_ids = list(message_send_dict.rendering_result.mentions_user_group_ids)
|
||||
|
|
|
@ -47,6 +47,8 @@ class ErrorCode(Enum):
|
|||
REACTION_DOES_NOT_EXIST = auto()
|
||||
SERVER_NOT_READY = auto()
|
||||
MISSING_REMOTE_REALM = auto()
|
||||
TOPIC_WILDCARD_MENTION_NOT_ALLOWED = auto()
|
||||
STREAM_WILDCARD_MENTION_NOT_ALLOWED = auto()
|
||||
|
||||
|
||||
class JsonableError(Exception):
|
||||
|
@ -584,3 +586,27 @@ class MissingRemoteRealmError(JsonableError): # nocoverage
|
|||
@override
|
||||
def msg_format() -> str:
|
||||
return _("Organization not registered")
|
||||
|
||||
|
||||
class StreamWildcardMentionNotAllowedError(JsonableError):
|
||||
code: ErrorCode = ErrorCode.STREAM_WILDCARD_MENTION_NOT_ALLOWED
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@override
|
||||
def msg_format() -> str:
|
||||
return _("You do not have permission to use stream wildcard mentions in this stream.")
|
||||
|
||||
|
||||
class TopicWildcardMentionNotAllowedError(JsonableError):
|
||||
code: ErrorCode = ErrorCode.TOPIC_WILDCARD_MENTION_NOT_ALLOWED
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@override
|
||||
def msg_format() -> str:
|
||||
return _("You do not have permission to use topic wildcard mentions in this topic.")
|
||||
|
|
|
@ -134,9 +134,6 @@ class MessageRenderingResult:
|
|||
user_ids_with_alert_words: Set[int]
|
||||
potential_attachment_path_ids: List[str]
|
||||
|
||||
def has_wildcard_mention(self) -> bool:
|
||||
return self.mentions_stream_wildcard or self.mentions_topic_wildcard
|
||||
|
||||
|
||||
@dataclass
|
||||
class DbData:
|
||||
|
|
|
@ -1664,14 +1664,13 @@ def get_recent_private_conversations(user_profile: UserProfile) -> Dict[int, Dic
|
|||
return recipient_map
|
||||
|
||||
|
||||
def wildcard_mention_allowed(sender: UserProfile, stream: Stream, realm: Realm) -> bool:
|
||||
# If there are fewer than Realm.WILDCARD_MENTION_THRESHOLD, we
|
||||
# allow sending. In the future, we may want to make this behavior
|
||||
# a default, and also just allow explicitly setting whether this
|
||||
# applies to a stream as an override.
|
||||
if num_subscribers_for_stream_id(stream.id) <= Realm.WILDCARD_MENTION_THRESHOLD:
|
||||
return True
|
||||
|
||||
def wildcard_mention_policy_authorizes_user(sender: UserProfile, realm: Realm) -> bool:
|
||||
"""Helper function for 'topic_wildcard_mention_allowed' and
|
||||
'stream_wildcard_mention_allowed' to check if the sender is allowed to use
|
||||
wildcard mentions based on the 'wildcard_mention_policy' setting of that realm.
|
||||
This check is used only if the participants count in the topic or the subscribers
|
||||
count in the stream is greater than 'Realm.WILDCARD_MENTION_THRESHOLD'.
|
||||
"""
|
||||
if realm.wildcard_mention_policy == Realm.WILDCARD_MENTION_POLICY_NOBODY:
|
||||
return False
|
||||
|
||||
|
@ -1693,6 +1692,24 @@ def wildcard_mention_allowed(sender: UserProfile, stream: Stream, realm: Realm)
|
|||
raise AssertionError("Invalid wildcard mention policy")
|
||||
|
||||
|
||||
def topic_wildcard_mention_allowed(
|
||||
sender: UserProfile, topic_participant_count: int, realm: Realm
|
||||
) -> bool:
|
||||
if topic_participant_count <= Realm.WILDCARD_MENTION_THRESHOLD:
|
||||
return True
|
||||
return wildcard_mention_policy_authorizes_user(sender, realm)
|
||||
|
||||
|
||||
def stream_wildcard_mention_allowed(sender: UserProfile, stream: Stream, realm: Realm) -> bool:
|
||||
# If there are fewer than Realm.WILDCARD_MENTION_THRESHOLD, we
|
||||
# allow sending. In the future, we may want to make this behavior
|
||||
# a default, and also just allow explicitly setting whether this
|
||||
# applies to a stream as an override.
|
||||
if num_subscribers_for_stream_id(stream.id) <= Realm.WILDCARD_MENTION_THRESHOLD:
|
||||
return True
|
||||
return wildcard_mention_policy_authorizes_user(sender, realm)
|
||||
|
||||
|
||||
def check_user_group_mention_allowed(sender: UserProfile, user_group_ids: List[int]) -> None:
|
||||
user_groups = UserGroup.objects.filter(id__in=user_group_ids).select_related(
|
||||
"can_mention_group"
|
||||
|
|
|
@ -6404,6 +6404,38 @@ paths:
|
|||
description: |
|
||||
A typical failed JSON response for when a direct message is sent to a user
|
||||
that does not exist:
|
||||
- allOf:
|
||||
- $ref: "#/components/schemas/CodedError"
|
||||
- example:
|
||||
{
|
||||
"result": "error",
|
||||
"msg": "You do not have permission to use stream wildcard mentions in this stream.",
|
||||
"code": "STREAM_WILDCARD_MENTION_NOT_ALLOWED",
|
||||
}
|
||||
description: |
|
||||
An example JSON error response for when the message was rejected because
|
||||
of the organization's `wildcard_mention_policy` and large number of
|
||||
subscribers to the stream.
|
||||
|
||||
**Changes**: New in Zulip 8.0 (feature level 229). Previously, this
|
||||
error returned the `"BAD_REQUEST"` code.
|
||||
- allOf:
|
||||
- $ref: "#/components/schemas/CodedError"
|
||||
- example:
|
||||
{
|
||||
"result": "error",
|
||||
"msg": "You do not have permission to use topic wildcard mentions in this topic.",
|
||||
"code": "TOPIC_WILDCARD_MENTION_NOT_ALLOWED",
|
||||
}
|
||||
description: |
|
||||
An example JSON error response for when the message was rejected because
|
||||
the message contains a topic wildcard mention, but the user doesn't have
|
||||
permission to use such a mention in this topic due to the
|
||||
`wildcard_mention_policy` (and large number of participants in this
|
||||
specific topic).
|
||||
|
||||
**Changes**: New in Zulip 8.0 (feature level 229). Previously,
|
||||
`wildcard_mention_policy` was not enforced for topic mentions.
|
||||
/messages/{message_id}/history:
|
||||
get:
|
||||
operationId: get-message-history
|
||||
|
@ -7668,6 +7700,38 @@ paths:
|
|||
dialog.
|
||||
|
||||
**Changes**: New in Zulip 7.0 (feature level 172).
|
||||
- allOf:
|
||||
- $ref: "#/components/schemas/CodedError"
|
||||
- example:
|
||||
{
|
||||
"result": "error",
|
||||
"msg": "You do not have permission to use stream wildcard mentions in this stream.",
|
||||
"code": "STREAM_WILDCARD_MENTION_NOT_ALLOWED",
|
||||
}
|
||||
description: |
|
||||
An example JSON error response for when the message was rejected because
|
||||
of the organization's `wildcard_mention_policy` and large number of
|
||||
subscribers to the stream.
|
||||
|
||||
**Changes**: New in Zulip 8.0 (feature level 229). Previously, this
|
||||
error returned the `"BAD_REQUEST"` code.
|
||||
- allOf:
|
||||
- $ref: "#/components/schemas/CodedError"
|
||||
- example:
|
||||
{
|
||||
"result": "error",
|
||||
"msg": "You do not have permission to use topic wildcard mentions in this topic.",
|
||||
"code": "TOPIC_WILDCARD_MENTION_NOT_ALLOWED",
|
||||
}
|
||||
description: |
|
||||
An example JSON error response for when the message was rejected because
|
||||
the message contains a topic wildcard mention, but the user doesn't have
|
||||
permission to use such a mention in this topic due to the
|
||||
`wildcard_mention_policy` (and large number of participants in this
|
||||
specific topic).
|
||||
|
||||
**Changes**: New in Zulip 8.0 (feature level 229). Previously,
|
||||
`wildcard_mention_policy` was not enforced for topic mentions.
|
||||
delete:
|
||||
operationId: delete-message
|
||||
summary: Delete a message
|
||||
|
|
|
@ -2284,18 +2284,11 @@ class EditMessageTest(EditMessageTestCase):
|
|||
acting_user=None,
|
||||
)
|
||||
|
||||
with mock.patch("zerver.lib.message.num_subscribers_for_stream_id", return_value=17):
|
||||
result = self.client_patch(
|
||||
"/json/messages/" + str(message_id),
|
||||
{
|
||||
"content": "Hello @**topic**",
|
||||
},
|
||||
)
|
||||
self.assert_json_error(
|
||||
result, "You do not have permission to use wildcard mentions in this stream."
|
||||
)
|
||||
|
||||
with mock.patch("zerver.lib.message.num_subscribers_for_stream_id", return_value=14):
|
||||
# Less than 'Realm.WILDCARD_MENTION_THRESHOLD' participants
|
||||
participants_user_ids = set(range(1, 10))
|
||||
with mock.patch(
|
||||
"zerver.actions.message_edit.participants_for_topic", return_value=participants_user_ids
|
||||
):
|
||||
result = self.client_patch(
|
||||
"/json/messages/" + str(message_id),
|
||||
{
|
||||
|
@ -2304,9 +2297,27 @@ class EditMessageTest(EditMessageTestCase):
|
|||
)
|
||||
self.assert_json_success(result)
|
||||
|
||||
# More than 'Realm.WILDCARD_MENTION_THRESHOLD' participants.
|
||||
participants_user_ids = set(range(1, 20))
|
||||
with mock.patch(
|
||||
"zerver.actions.message_edit.participants_for_topic", return_value=participants_user_ids
|
||||
):
|
||||
result = self.client_patch(
|
||||
"/json/messages/" + str(message_id),
|
||||
{
|
||||
"content": "Hello @**topic**",
|
||||
},
|
||||
)
|
||||
self.assert_json_error(
|
||||
result, "You do not have permission to use topic wildcard mentions in this topic."
|
||||
)
|
||||
|
||||
# Shiva is moderator
|
||||
self.login("shiva")
|
||||
message_id = self.send_stream_message(shiva, stream_name, "Hi everyone")
|
||||
with mock.patch("zerver.lib.message.num_subscribers_for_stream_id", return_value=17):
|
||||
with mock.patch(
|
||||
"zerver.actions.message_edit.participants_for_topic", return_value=participants_user_ids
|
||||
):
|
||||
result = self.client_patch(
|
||||
"/json/messages/" + str(message_id),
|
||||
{
|
||||
|
@ -2389,7 +2400,7 @@ class EditMessageTest(EditMessageTestCase):
|
|||
},
|
||||
)
|
||||
self.assert_json_error(
|
||||
result, "You do not have permission to use wildcard mentions in this stream."
|
||||
result, "You do not have permission to use stream wildcard mentions in this stream."
|
||||
)
|
||||
|
||||
with mock.patch("zerver.lib.message.num_subscribers_for_stream_id", return_value=14):
|
||||
|
|
|
@ -1783,11 +1783,14 @@ class StreamMessagesTest(ZulipTestCase):
|
|||
self.assertTrue(user_message.flags.mentioned)
|
||||
|
||||
def send_and_verify_topic_wildcard_mention_message(
|
||||
self, sender_name: str, test_fails: bool = False, sub_count: int = 16
|
||||
self, sender_name: str, test_fails: bool = False, topic_participant_count: int = 20
|
||||
) -> None:
|
||||
sender = self.example_user(sender_name)
|
||||
content = "@**topic** test topic wildcard mention"
|
||||
with mock.patch("zerver.lib.message.num_subscribers_for_stream_id", return_value=sub_count):
|
||||
participants_user_ids = set(range(topic_participant_count))
|
||||
with mock.patch(
|
||||
"zerver.actions.message_send.participants_for_topic", return_value=participants_user_ids
|
||||
):
|
||||
if not test_fails:
|
||||
msg_id = self.send_stream_message(sender, "test_stream", content)
|
||||
result = self.api_get(sender, "/api/v1/messages/" + str(msg_id))
|
||||
|
@ -1796,7 +1799,7 @@ class StreamMessagesTest(ZulipTestCase):
|
|||
else:
|
||||
with self.assertRaisesRegex(
|
||||
JsonableError,
|
||||
"You do not have permission to use wildcard mentions in this stream.",
|
||||
"You do not have permission to use topic wildcard mentions in this topic.",
|
||||
):
|
||||
self.send_stream_message(sender, "test_stream", content)
|
||||
|
||||
|
@ -1828,8 +1831,8 @@ class StreamMessagesTest(ZulipTestCase):
|
|||
acting_user=None,
|
||||
)
|
||||
self.send_and_verify_topic_wildcard_mention_message("polonius", test_fails=True)
|
||||
# There is no restriction on small streams.
|
||||
self.send_and_verify_topic_wildcard_mention_message("polonius", sub_count=10)
|
||||
# There is no restriction on topics with less than 'Realm.WILDCARD_MENTION_THRESHOLD' participants.
|
||||
self.send_and_verify_topic_wildcard_mention_message("polonius", topic_participant_count=10)
|
||||
self.send_and_verify_topic_wildcard_mention_message("cordelia")
|
||||
|
||||
do_set_realm_property(
|
||||
|
@ -1846,7 +1849,7 @@ class StreamMessagesTest(ZulipTestCase):
|
|||
cordelia.date_joined = timezone_now()
|
||||
cordelia.save()
|
||||
self.send_and_verify_topic_wildcard_mention_message("cordelia", test_fails=True)
|
||||
self.send_and_verify_topic_wildcard_mention_message("cordelia", sub_count=10)
|
||||
self.send_and_verify_topic_wildcard_mention_message("cordelia", topic_participant_count=10)
|
||||
# Administrators and moderators can use wildcard mentions even if they are new.
|
||||
self.send_and_verify_topic_wildcard_mention_message("iago")
|
||||
self.send_and_verify_topic_wildcard_mention_message("shiva")
|
||||
|
@ -1862,7 +1865,7 @@ class StreamMessagesTest(ZulipTestCase):
|
|||
acting_user=None,
|
||||
)
|
||||
self.send_and_verify_topic_wildcard_mention_message("cordelia", test_fails=True)
|
||||
self.send_and_verify_topic_wildcard_mention_message("cordelia", sub_count=10)
|
||||
self.send_and_verify_topic_wildcard_mention_message("cordelia", topic_participant_count=10)
|
||||
self.send_and_verify_topic_wildcard_mention_message("shiva")
|
||||
|
||||
cordelia.date_joined = timezone_now()
|
||||
|
@ -1871,15 +1874,15 @@ class StreamMessagesTest(ZulipTestCase):
|
|||
realm, "wildcard_mention_policy", Realm.WILDCARD_MENTION_POLICY_ADMINS, acting_user=None
|
||||
)
|
||||
self.send_and_verify_topic_wildcard_mention_message("shiva", test_fails=True)
|
||||
# There is no restriction on small streams.
|
||||
self.send_and_verify_topic_wildcard_mention_message("shiva", sub_count=10)
|
||||
# There is no restriction on topics with less than 'Realm.WILDCARD_MENTION_THRESHOLD' participants.
|
||||
self.send_and_verify_topic_wildcard_mention_message("shiva", topic_participant_count=10)
|
||||
self.send_and_verify_topic_wildcard_mention_message("iago")
|
||||
|
||||
do_set_realm_property(
|
||||
realm, "wildcard_mention_policy", Realm.WILDCARD_MENTION_POLICY_NOBODY, acting_user=None
|
||||
)
|
||||
self.send_and_verify_topic_wildcard_mention_message("iago", test_fails=True)
|
||||
self.send_and_verify_topic_wildcard_mention_message("iago", sub_count=10)
|
||||
self.send_and_verify_topic_wildcard_mention_message("iago", topic_participant_count=10)
|
||||
|
||||
def send_and_verify_stream_wildcard_mention_message(
|
||||
self, sender_name: str, test_fails: bool = False, sub_count: int = 16
|
||||
|
@ -1895,7 +1898,7 @@ class StreamMessagesTest(ZulipTestCase):
|
|||
else:
|
||||
with self.assertRaisesRegex(
|
||||
JsonableError,
|
||||
"You do not have permission to use wildcard mentions in this stream.",
|
||||
"You do not have permission to use stream wildcard mentions in this stream.",
|
||||
):
|
||||
self.send_stream_message(sender, "test_stream", content)
|
||||
|
||||
|
|
Loading…
Reference in New Issue