mirror of https://github.com/zulip/zulip.git
settings: Add `can_move_messages_between_topics_group` realm setting.
Added `can_move_messages_between_topics_group` realm setting to replace `edit_topic_policy`.
This commit is contained in:
parent
1edf507be9
commit
ed5638ec3c
|
@ -20,6 +20,15 @@ format used by the Zulip server that they are interacting with.
|
||||||
|
|
||||||
## Changes in Zulip 10.0
|
## Changes in Zulip 10.0
|
||||||
|
|
||||||
|
**Feature level 316**
|
||||||
|
|
||||||
|
* `PATCH /realm`, [`GET /events`](/api/get-events),
|
||||||
|
[`POST /register`](/api/register-queue):
|
||||||
|
Added `can_move_messages_between_topics_group` realm setting which is a
|
||||||
|
[group-setting value](/api/group-setting-values) describing the set of users
|
||||||
|
with permission to move messages from one topic to another within a channel
|
||||||
|
in the organization.
|
||||||
|
|
||||||
**Feature level 315**
|
**Feature level 315**
|
||||||
|
|
||||||
* [POST /register](/api/register-queue), [`GET
|
* [POST /register](/api/register-queue), [`GET
|
||||||
|
|
|
@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
|
||||||
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
||||||
# entries in the endpoint's documentation in `zulip.yaml`.
|
# entries in the endpoint's documentation in `zulip.yaml`.
|
||||||
|
|
||||||
API_FEATURE_LEVEL = 315 # Last bumped for `is_archived`
|
API_FEATURE_LEVEL = 316 # Last bumped for `can_move_messages_between_topics_group`
|
||||||
|
|
||||||
# Bump the minor PROVISION_VERSION to indicate that folks should provision
|
# 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
|
# only when going from an old version of the code to a newer version. Bump
|
||||||
|
|
|
@ -111,8 +111,8 @@ export function is_topic_editable(message: Message, edit_limit_seconds_buffer =
|
||||||
}
|
}
|
||||||
|
|
||||||
// Organization admins and moderators can edit message topics indefinitely,
|
// Organization admins and moderators can edit message topics indefinitely,
|
||||||
// irrespective of the topic editing deadline, if edit_topic_policy allows
|
// irrespective of the topic editing deadline, if they are in the
|
||||||
// them to do so.
|
// can_move_messages_between_topics_group.
|
||||||
if (current_user.is_admin || current_user.is_moderator) {
|
if (current_user.is_admin || current_user.is_moderator) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,7 +208,6 @@ export function dispatch_normal_event(event) {
|
||||||
const realm_settings = {
|
const realm_settings = {
|
||||||
allow_edit_history: noop,
|
allow_edit_history: noop,
|
||||||
allow_message_editing: noop,
|
allow_message_editing: noop,
|
||||||
edit_topic_policy: noop,
|
|
||||||
avatar_changes_disabled: settings_account.update_avatar_change_display,
|
avatar_changes_disabled: settings_account.update_avatar_change_display,
|
||||||
bot_creation_policy: settings_bots.update_bot_permissions_ui,
|
bot_creation_policy: settings_bots.update_bot_permissions_ui,
|
||||||
can_delete_any_message_group: noop,
|
can_delete_any_message_group: noop,
|
||||||
|
@ -323,7 +322,7 @@ export function dispatch_normal_event(event) {
|
||||||
compose_recipient.check_posting_policy_for_compose_box();
|
compose_recipient.check_posting_policy_for_compose_box();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === "edit_topic_policy") {
|
if (key === "can_move_messages_between_topics_group") {
|
||||||
message_live_update.rerender_messages_view();
|
message_live_update.rerender_messages_view();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,6 @@ export const simple_dropdown_realm_settings_schema = realm_schema.pick({
|
||||||
realm_invite_to_stream_policy: true,
|
realm_invite_to_stream_policy: true,
|
||||||
realm_invite_to_realm_policy: true,
|
realm_invite_to_realm_policy: true,
|
||||||
realm_wildcard_mention_policy: true,
|
realm_wildcard_mention_policy: true,
|
||||||
realm_edit_topic_policy: true,
|
|
||||||
realm_org_type: true,
|
realm_org_type: true,
|
||||||
});
|
});
|
||||||
export type SimpleDropdownRealmSettings = z.infer<typeof simple_dropdown_realm_settings_schema>;
|
export type SimpleDropdownRealmSettings = z.infer<typeof simple_dropdown_realm_settings_schema>;
|
||||||
|
@ -484,6 +483,7 @@ const dropdown_widget_map = new Map<string, DropdownWidget | null>([
|
||||||
["realm_can_delete_any_message_group", null],
|
["realm_can_delete_any_message_group", null],
|
||||||
["realm_can_delete_own_message_group", null],
|
["realm_can_delete_own_message_group", null],
|
||||||
["realm_can_move_messages_between_channels_group", null],
|
["realm_can_move_messages_between_channels_group", null],
|
||||||
|
["realm_can_move_messages_between_topics_group", null],
|
||||||
["realm_direct_message_initiator_group", null],
|
["realm_direct_message_initiator_group", null],
|
||||||
["realm_direct_message_permission_group", null],
|
["realm_direct_message_permission_group", null],
|
||||||
]);
|
]);
|
||||||
|
@ -802,6 +802,7 @@ export function check_realm_settings_property_changed(elem: HTMLElement): boolea
|
||||||
case "realm_can_delete_any_message_group":
|
case "realm_can_delete_any_message_group":
|
||||||
case "realm_can_delete_own_message_group":
|
case "realm_can_delete_own_message_group":
|
||||||
case "realm_can_move_messages_between_channels_group":
|
case "realm_can_move_messages_between_channels_group":
|
||||||
|
case "realm_can_move_messages_between_topics_group":
|
||||||
case "realm_direct_message_initiator_group":
|
case "realm_direct_message_initiator_group":
|
||||||
case "realm_direct_message_permission_group":
|
case "realm_direct_message_permission_group":
|
||||||
proposed_val = get_dropdown_list_widget_setting_value($elem);
|
proposed_val = get_dropdown_list_widget_setting_value($elem);
|
||||||
|
@ -1054,6 +1055,7 @@ export function populate_data_for_realm_settings_request(
|
||||||
"can_delete_any_message_group",
|
"can_delete_any_message_group",
|
||||||
"can_delete_own_message_group",
|
"can_delete_own_message_group",
|
||||||
"can_move_messages_between_channels_group",
|
"can_move_messages_between_channels_group",
|
||||||
|
"can_move_messages_between_topics_group",
|
||||||
"create_multiuse_invite_group",
|
"create_multiuse_invite_group",
|
||||||
"direct_message_initiator_group",
|
"direct_message_initiator_group",
|
||||||
"direct_message_permission_group",
|
"direct_message_permission_group",
|
||||||
|
|
|
@ -311,43 +311,6 @@ export const wildcard_mention_policy_values = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const common_message_policy_values = {
|
|
||||||
by_everyone: {
|
|
||||||
order: 1,
|
|
||||||
code: 5,
|
|
||||||
description: $t({defaultMessage: "Admins, moderators, members and guests"}),
|
|
||||||
},
|
|
||||||
by_members: {
|
|
||||||
order: 2,
|
|
||||||
code: 1,
|
|
||||||
description: $t({defaultMessage: "Admins, moderators and members"}),
|
|
||||||
},
|
|
||||||
by_full_members: {
|
|
||||||
order: 3,
|
|
||||||
code: 3,
|
|
||||||
description: $t({defaultMessage: "Admins, moderators and full members"}),
|
|
||||||
},
|
|
||||||
by_moderators_only: {
|
|
||||||
order: 4,
|
|
||||||
code: 4,
|
|
||||||
description: $t({defaultMessage: "Admins and moderators"}),
|
|
||||||
},
|
|
||||||
by_admins_only: {
|
|
||||||
order: 5,
|
|
||||||
code: 2,
|
|
||||||
description: $t({defaultMessage: "Admins only"}),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const edit_topic_policy_values = {
|
|
||||||
...common_message_policy_values,
|
|
||||||
nobody: {
|
|
||||||
order: 6,
|
|
||||||
code: 6,
|
|
||||||
description: $t({defaultMessage: "Nobody"}),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const time_limit_dropdown_values = [
|
export const time_limit_dropdown_values = [
|
||||||
{
|
{
|
||||||
text: $t({defaultMessage: "Any time"}),
|
text: $t({defaultMessage: "Any time"}),
|
||||||
|
|
|
@ -71,18 +71,7 @@ function user_has_permission(policy_value: number): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_params.is_spectator) {
|
if (page_params.is_spectator || current_user.is_guest) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* At present, by_everyone is not present in common_policy_values,
|
|
||||||
* but we include a check for it here, so that code using
|
|
||||||
* common_message_policy_values or other supersets can use this function. */
|
|
||||||
if (policy_value === settings_config.common_message_policy_values.by_everyone.code) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_user.is_guest) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +251,11 @@ export function user_can_add_custom_emoji(): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function user_can_move_messages_to_another_topic(): boolean {
|
export function user_can_move_messages_to_another_topic(): boolean {
|
||||||
return user_has_permission(realm.realm_edit_topic_policy);
|
return user_has_permission_for_group_setting(
|
||||||
|
realm.realm_can_move_messages_between_topics_group,
|
||||||
|
"can_move_messages_between_topics_group",
|
||||||
|
"realm",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function user_can_delete_any_message(): boolean {
|
export function user_can_delete_any_message(): boolean {
|
||||||
|
|
|
@ -161,9 +161,7 @@ export function enable_or_disable_group_permission_settings(): void {
|
||||||
type OrganizationSettingsOptions = {
|
type OrganizationSettingsOptions = {
|
||||||
common_policy_values: SettingOptionValueWithKey[];
|
common_policy_values: SettingOptionValueWithKey[];
|
||||||
wildcard_mention_policy_values: SettingOptionValueWithKey[];
|
wildcard_mention_policy_values: SettingOptionValueWithKey[];
|
||||||
common_message_policy_values: SettingOptionValueWithKey[];
|
|
||||||
invite_to_realm_policy_values: SettingOptionValueWithKey[];
|
invite_to_realm_policy_values: SettingOptionValueWithKey[];
|
||||||
edit_topic_policy_values: SettingOptionValueWithKey[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function get_organization_settings_options(): OrganizationSettingsOptions {
|
export function get_organization_settings_options(): OrganizationSettingsOptions {
|
||||||
|
@ -174,15 +172,9 @@ export function get_organization_settings_options(): OrganizationSettingsOptions
|
||||||
wildcard_mention_policy_values: settings_components.get_sorted_options_list(
|
wildcard_mention_policy_values: settings_components.get_sorted_options_list(
|
||||||
settings_config.wildcard_mention_policy_values,
|
settings_config.wildcard_mention_policy_values,
|
||||||
),
|
),
|
||||||
common_message_policy_values: settings_components.get_sorted_options_list(
|
|
||||||
settings_config.common_message_policy_values,
|
|
||||||
),
|
|
||||||
invite_to_realm_policy_values: settings_components.get_sorted_options_list(
|
invite_to_realm_policy_values: settings_components.get_sorted_options_list(
|
||||||
settings_config.email_invite_to_realm_policy_values,
|
settings_config.email_invite_to_realm_policy_values,
|
||||||
),
|
),
|
||||||
edit_topic_policy_values: settings_components.get_sorted_options_list(
|
|
||||||
settings_config.edit_topic_policy_values,
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,27 +273,9 @@ function set_msg_edit_limit_dropdown(): void {
|
||||||
|
|
||||||
function message_move_limit_setting_enabled(
|
function message_move_limit_setting_enabled(
|
||||||
related_setting_name:
|
related_setting_name:
|
||||||
| "realm_edit_topic_policy"
|
| "realm_can_move_messages_between_topics_group"
|
||||||
| "realm_can_move_messages_between_channels_group",
|
| "realm_can_move_messages_between_channels_group",
|
||||||
): boolean {
|
): boolean {
|
||||||
if (related_setting_name === "realm_edit_topic_policy") {
|
|
||||||
const setting_value_string = $<HTMLSelectOneElement>(
|
|
||||||
`select:not(multiple)#id_${CSS.escape(related_setting_name)}`,
|
|
||||||
).val();
|
|
||||||
assert(setting_value_string !== undefined);
|
|
||||||
const setting_value = Number.parseInt(setting_value_string, 10);
|
|
||||||
const settings_options = settings_config.edit_topic_policy_values;
|
|
||||||
|
|
||||||
if (
|
|
||||||
setting_value === settings_options.by_admins_only.code ||
|
|
||||||
setting_value === settings_options.by_moderators_only.code ||
|
|
||||||
setting_value === settings_options.nobody.code
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const user_group_id = settings_components.get_dropdown_list_widget_setting_value(
|
const user_group_id = settings_components.get_dropdown_list_widget_setting_value(
|
||||||
$(`#id_${related_setting_name}`),
|
$(`#id_${related_setting_name}`),
|
||||||
);
|
);
|
||||||
|
@ -334,7 +308,9 @@ function set_msg_move_limit_setting(property_name: MessageMoveTimeLimitSetting):
|
||||||
|
|
||||||
let disable_setting;
|
let disable_setting;
|
||||||
if (property_name === "realm_move_messages_within_stream_limit_seconds") {
|
if (property_name === "realm_move_messages_within_stream_limit_seconds") {
|
||||||
disable_setting = message_move_limit_setting_enabled("realm_edit_topic_policy");
|
disable_setting = message_move_limit_setting_enabled(
|
||||||
|
"realm_can_move_messages_between_topics_group",
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
disable_setting = message_move_limit_setting_enabled(
|
disable_setting = message_move_limit_setting_enabled(
|
||||||
"realm_can_move_messages_between_channels_group",
|
"realm_can_move_messages_between_channels_group",
|
||||||
|
@ -559,6 +535,9 @@ function update_dependent_subsettings(property_name: string): void {
|
||||||
case "realm_can_move_messages_between_channels_group":
|
case "realm_can_move_messages_between_channels_group":
|
||||||
set_msg_move_limit_setting("realm_move_messages_between_streams_limit_seconds");
|
set_msg_move_limit_setting("realm_move_messages_between_streams_limit_seconds");
|
||||||
break;
|
break;
|
||||||
|
case "realm_can_move_messages_between_topics_group":
|
||||||
|
set_msg_move_limit_setting("realm_move_messages_within_stream_limit_seconds");
|
||||||
|
break;
|
||||||
case "realm_org_join_restrictions":
|
case "realm_org_join_restrictions":
|
||||||
set_org_join_restrictions_dropdown();
|
set_org_join_restrictions_dropdown();
|
||||||
break;
|
break;
|
||||||
|
@ -612,6 +591,7 @@ export function discard_realm_property_element_changes(elem: HTMLElement): void
|
||||||
case "realm_can_delete_any_message_group":
|
case "realm_can_delete_any_message_group":
|
||||||
case "realm_can_delete_own_message_group":
|
case "realm_can_delete_own_message_group":
|
||||||
case "realm_can_move_messages_between_channels_group":
|
case "realm_can_move_messages_between_channels_group":
|
||||||
|
case "realm_can_move_messages_between_topics_group":
|
||||||
assert(typeof property_value === "string" || typeof property_value === "number");
|
assert(typeof property_value === "string" || typeof property_value === "number");
|
||||||
settings_components.set_dropdown_list_widget_setting_value(
|
settings_components.set_dropdown_list_widget_setting_value(
|
||||||
property_name,
|
property_name,
|
||||||
|
@ -1018,6 +998,13 @@ export function set_up_dropdown_widget_for_realm_group_settings(): void {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "can_move_messages_between_topics_group": {
|
||||||
|
dropdown_list_item_click_callback = () => {
|
||||||
|
set_msg_move_limit_setting("realm_move_messages_within_stream_limit_seconds");
|
||||||
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
// No default
|
// No default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1338,30 +1325,6 @@ export function build_page(): void {
|
||||||
update_message_edit_sub_settings(this.checked);
|
update_message_edit_sub_settings(this.checked);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#org-moving-msgs").on(
|
|
||||||
"change",
|
|
||||||
".move-message-policy-setting",
|
|
||||||
function (this: HTMLElement) {
|
|
||||||
const $policy_dropdown_elem = $(this);
|
|
||||||
const property_name = z
|
|
||||||
.enum(["realm_edit_topic_policy", "realm_can_move_messages_between_channels_group"])
|
|
||||||
.parse(settings_components.extract_property_name($policy_dropdown_elem));
|
|
||||||
const disable_time_limit_setting = message_move_limit_setting_enabled(property_name);
|
|
||||||
|
|
||||||
let time_limit_setting_name: MessageMoveTimeLimitSetting;
|
|
||||||
if (property_name === "realm_edit_topic_policy") {
|
|
||||||
time_limit_setting_name = "realm_move_messages_within_stream_limit_seconds";
|
|
||||||
} else {
|
|
||||||
time_limit_setting_name = "realm_move_messages_between_streams_limit_seconds";
|
|
||||||
}
|
|
||||||
|
|
||||||
enable_or_disable_related_message_move_time_limit_setting(
|
|
||||||
time_limit_setting_name,
|
|
||||||
disable_time_limit_setting,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
$("#id_realm_org_join_restrictions").on("click", (e) => {
|
$("#id_realm_org_join_restrictions").on("click", (e) => {
|
||||||
// This prevents the disappearance of modal when there are
|
// This prevents the disappearance of modal when there are
|
||||||
// no allowed domains otherwise it gets closed due to
|
// no allowed domains otherwise it gets closed due to
|
||||||
|
|
|
@ -296,6 +296,7 @@ export const realm_schema = z.object({
|
||||||
realm_can_delete_own_message_group: z.number(),
|
realm_can_delete_own_message_group: z.number(),
|
||||||
realm_can_manage_all_groups: group_setting_value_schema,
|
realm_can_manage_all_groups: group_setting_value_schema,
|
||||||
realm_can_move_messages_between_channels_group: z.number(),
|
realm_can_move_messages_between_channels_group: z.number(),
|
||||||
|
realm_can_move_messages_between_topics_group: z.number(),
|
||||||
realm_create_multiuse_invite_group: group_setting_value_schema,
|
realm_create_multiuse_invite_group: group_setting_value_schema,
|
||||||
realm_date_created: z.number(),
|
realm_date_created: z.number(),
|
||||||
realm_default_code_block_language: z.string(),
|
realm_default_code_block_language: z.string(),
|
||||||
|
@ -321,7 +322,6 @@ export const realm_schema = z.object({
|
||||||
allow_subdomains: z.boolean(),
|
allow_subdomains: z.boolean(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
realm_edit_topic_policy: z.number(),
|
|
||||||
realm_email_auth_enabled: z.boolean(),
|
realm_email_auth_enabled: z.boolean(),
|
||||||
realm_email_changes_disabled: z.boolean(),
|
realm_email_changes_disabled: z.boolean(),
|
||||||
realm_emails_restricted_to_domains: z.boolean(),
|
realm_emails_restricted_to_domains: z.boolean(),
|
||||||
|
|
|
@ -355,7 +355,7 @@ export async function build_move_topic_to_stream_popover(
|
||||||
// When the modal is opened for moving the whole topic from left sidebar,
|
// When the modal is opened for moving the whole topic from left sidebar,
|
||||||
// we do not have any message object and so we disable the stream input
|
// we do not have any message object and so we disable the stream input
|
||||||
// based on the can_move_messages_between_channels_group setting and topic
|
// based on the can_move_messages_between_channels_group setting and topic
|
||||||
// input based on edit_topic_policy. In other cases, message object is
|
// input based on can_move_messages_between_topics_group. In other cases, message object is
|
||||||
// available and thus we check the time-based permissions as well in the
|
// available and thus we check the time-based permissions as well in the
|
||||||
// below if block to enable or disable the stream and topic input.
|
// below if block to enable or disable the stream and topic input.
|
||||||
let disable_stream_input = !settings_data.user_can_move_messages_between_streams();
|
let disable_stream_input = !settings_data.user_can_move_messages_between_streams();
|
||||||
|
|
|
@ -191,12 +191,11 @@
|
||||||
</h3>
|
</h3>
|
||||||
{{> settings_save_discard_widget section_name="moving-msgs" }}
|
{{> settings_save_discard_widget section_name="moving-msgs" }}
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group">
|
|
||||||
<label for="realm_edit_topic_policy" class="settings-field-label">{{t "Who can move messages to another topic" }}</label>
|
{{> ../dropdown_widget_with_label
|
||||||
<select name="realm_edit_topic_policy" id="id_realm_edit_topic_policy" class="prop-element move-message-policy-setting settings_select bootstrap-focus-style" data-setting-widget-type="number">
|
widget_name="realm_can_move_messages_between_topics_group"
|
||||||
{{> dropdown_options_widget option_values=edit_topic_policy_values}}
|
label=(t 'Who can move messages to another topic')
|
||||||
</select>
|
value_type="number" }}
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="input-group time-limit-setting">
|
<div class="input-group time-limit-setting">
|
||||||
<label for="realm_move_messages_within_stream_limit_seconds" class="settings-field-label">{{t "Time limit for editing topics" }} <i>({{t "does not apply to moderators and administrators" }})</i></label>
|
<label for="realm_move_messages_within_stream_limit_seconds" class="settings-field-label">{{t "Time limit for editing topics" }} <i>({{t "does not apply to moderators and administrators" }})</i></label>
|
||||||
|
|
|
@ -588,10 +588,10 @@ run_test("realm settings", ({override}) => {
|
||||||
override(realm, "realm_create_multiuse_invite_group", 1);
|
override(realm, "realm_create_multiuse_invite_group", 1);
|
||||||
override(realm, "realm_allow_message_editing", false);
|
override(realm, "realm_allow_message_editing", false);
|
||||||
override(realm, "realm_message_content_edit_limit_seconds", 0);
|
override(realm, "realm_message_content_edit_limit_seconds", 0);
|
||||||
override(realm, "realm_edit_topic_policy", 3);
|
|
||||||
override(realm, "realm_authentication_methods", {Google: {enabled: false, available: true}});
|
override(realm, "realm_authentication_methods", {Google: {enabled: false, available: true}});
|
||||||
override(realm, "realm_can_add_custom_emoji_group", 1);
|
override(realm, "realm_can_add_custom_emoji_group", 1);
|
||||||
override(realm, "realm_can_create_public_channel_group", 1);
|
override(realm, "realm_can_create_public_channel_group", 1);
|
||||||
|
override(realm, "realm_can_move_messages_between_topics_group", 1);
|
||||||
override(realm, "realm_direct_message_permission_group", 1);
|
override(realm, "realm_direct_message_permission_group", 1);
|
||||||
override(realm, "realm_plan_type", 2);
|
override(realm, "realm_plan_type", 2);
|
||||||
override(realm, "realm_upload_quota_mib", 5000);
|
override(realm, "realm_upload_quota_mib", 5000);
|
||||||
|
@ -601,12 +601,12 @@ run_test("realm settings", ({override}) => {
|
||||||
assert_same(realm.realm_create_multiuse_invite_group, 3);
|
assert_same(realm.realm_create_multiuse_invite_group, 3);
|
||||||
assert_same(realm.realm_allow_message_editing, true);
|
assert_same(realm.realm_allow_message_editing, true);
|
||||||
assert_same(realm.realm_message_content_edit_limit_seconds, 5);
|
assert_same(realm.realm_message_content_edit_limit_seconds, 5);
|
||||||
assert_same(realm.realm_edit_topic_policy, 4);
|
|
||||||
assert_same(realm.realm_authentication_methods, {
|
assert_same(realm.realm_authentication_methods, {
|
||||||
Google: {enabled: true, available: true},
|
Google: {enabled: true, available: true},
|
||||||
});
|
});
|
||||||
assert_same(realm.realm_can_add_custom_emoji_group, 3);
|
assert_same(realm.realm_can_add_custom_emoji_group, 3);
|
||||||
assert_same(realm.realm_can_create_public_channel_group, 3);
|
assert_same(realm.realm_can_create_public_channel_group, 3);
|
||||||
|
assert_same(realm.realm_can_move_messages_between_topics_group, 3);
|
||||||
assert_same(realm.realm_direct_message_permission_group, 3);
|
assert_same(realm.realm_direct_message_permission_group, 3);
|
||||||
assert_same(realm.realm_plan_type, 3);
|
assert_same(realm.realm_plan_type, 3);
|
||||||
assert_same(realm.realm_upload_quota_mib, 50000);
|
assert_same(realm.realm_upload_quota_mib, 50000);
|
||||||
|
|
|
@ -365,13 +365,13 @@ exports.fixtures = {
|
||||||
data: {
|
data: {
|
||||||
allow_message_editing: true,
|
allow_message_editing: true,
|
||||||
message_content_edit_limit_seconds: 5,
|
message_content_edit_limit_seconds: 5,
|
||||||
edit_topic_policy: 4,
|
|
||||||
create_multiuse_invite_group: 3,
|
create_multiuse_invite_group: 3,
|
||||||
authentication_methods: {
|
authentication_methods: {
|
||||||
Google: {enabled: true, available: true},
|
Google: {enabled: true, available: true},
|
||||||
},
|
},
|
||||||
can_add_custom_emoji_group: 3,
|
can_add_custom_emoji_group: 3,
|
||||||
can_create_public_channel_group: 3,
|
can_create_public_channel_group: 3,
|
||||||
|
can_move_messages_between_topics_group: 3,
|
||||||
direct_message_permission_group: 3,
|
direct_message_permission_group: 3,
|
||||||
plan_type: 3,
|
plan_type: 3,
|
||||||
upload_quota_mib: 50000,
|
upload_quota_mib: 50000,
|
||||||
|
|
|
@ -142,7 +142,6 @@ function set_page_params_no_edit_restrictions({override}) {
|
||||||
override(realm, "realm_allow_edit_history", true);
|
override(realm, "realm_allow_edit_history", true);
|
||||||
override(realm, "realm_message_content_delete_limit_seconds", null);
|
override(realm, "realm_message_content_delete_limit_seconds", null);
|
||||||
override(realm, "realm_enable_read_receipts", true);
|
override(realm, "realm_enable_read_receipts", true);
|
||||||
override(realm, "realm_edit_topic_policy", 5);
|
|
||||||
override(realm, "realm_move_messages_within_stream_limit_seconds", null);
|
override(realm, "realm_move_messages_within_stream_limit_seconds", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +167,7 @@ test("my_message_all_actions", ({override}) => {
|
||||||
set_page_params_no_edit_restrictions({override});
|
set_page_params_no_edit_restrictions({override});
|
||||||
override(realm, "realm_can_delete_any_message_group", everyone.id);
|
override(realm, "realm_can_delete_any_message_group", everyone.id);
|
||||||
override(realm, "realm_can_delete_own_message_group", everyone.id);
|
override(realm, "realm_can_delete_own_message_group", everyone.id);
|
||||||
|
override(realm, "realm_can_move_messages_between_topics_group", everyone.id);
|
||||||
override(current_user, "user_id", me.user_id);
|
override(current_user, "user_id", me.user_id);
|
||||||
// Get message with maximum permissions available
|
// Get message with maximum permissions available
|
||||||
// Initialize message list
|
// Initialize message list
|
||||||
|
@ -259,6 +259,8 @@ test("not_my_message_view_actions", ({override}) => {
|
||||||
test("not_my_message_view_source_and_move", ({override}) => {
|
test("not_my_message_view_source_and_move", ({override}) => {
|
||||||
set_page_params_no_edit_restrictions({override});
|
set_page_params_no_edit_restrictions({override});
|
||||||
override(realm, "realm_can_delete_any_message_group", everyone.id);
|
override(realm, "realm_can_delete_any_message_group", everyone.id);
|
||||||
|
override(realm, "realm_can_move_messages_between_topics_group", everyone.id);
|
||||||
|
override(current_user, "user_id", me.user_id);
|
||||||
// Get message that is movable with viewable source
|
// Get message that is movable with viewable source
|
||||||
|
|
||||||
const list = init_message_list();
|
const list = init_message_list();
|
||||||
|
|
|
@ -163,66 +163,6 @@ test_policy(
|
||||||
settings_data.user_can_invite_users_by_email,
|
settings_data.user_can_invite_users_by_email,
|
||||||
);
|
);
|
||||||
|
|
||||||
function test_message_policy(label, policy, validation_func) {
|
|
||||||
run_test(label, ({override}) => {
|
|
||||||
override(current_user, "is_admin", true);
|
|
||||||
override(realm, policy, settings_config.common_message_policy_values.by_admins_only.code);
|
|
||||||
assert.equal(validation_func(), true);
|
|
||||||
|
|
||||||
override(current_user, "is_admin", false);
|
|
||||||
override(current_user, "is_moderator", true);
|
|
||||||
assert.equal(validation_func(), false);
|
|
||||||
|
|
||||||
override(
|
|
||||||
realm,
|
|
||||||
policy,
|
|
||||||
settings_config.common_message_policy_values.by_moderators_only.code,
|
|
||||||
);
|
|
||||||
assert.equal(validation_func(), true);
|
|
||||||
|
|
||||||
override(current_user, "is_moderator", false);
|
|
||||||
assert.equal(validation_func(), false);
|
|
||||||
|
|
||||||
override(current_user, "is_guest", true);
|
|
||||||
override(realm, policy, settings_config.common_message_policy_values.by_everyone.code);
|
|
||||||
assert.equal(validation_func(), true);
|
|
||||||
|
|
||||||
override(realm, policy, settings_config.common_message_policy_values.by_members.code);
|
|
||||||
assert.equal(validation_func(), false);
|
|
||||||
|
|
||||||
override(current_user, "is_guest", false);
|
|
||||||
assert.equal(validation_func(), true);
|
|
||||||
|
|
||||||
override(realm, policy, settings_config.common_message_policy_values.by_full_members.code);
|
|
||||||
override(current_user, "user_id", 30);
|
|
||||||
isaac.date_joined = new Date(Date.now());
|
|
||||||
override(realm, "realm_waiting_period_threshold", 10);
|
|
||||||
settings_data.initialize(isaac.date_joined);
|
|
||||||
assert.equal(validation_func(), false);
|
|
||||||
|
|
||||||
isaac.date_joined = new Date(Date.now() - 20 * 86400000);
|
|
||||||
settings_data.initialize(isaac.date_joined);
|
|
||||||
assert.equal(validation_func(), true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
test_message_policy(
|
|
||||||
"user_can_move_messages_to_another_topic",
|
|
||||||
"realm_edit_topic_policy",
|
|
||||||
settings_data.user_can_move_messages_to_another_topic,
|
|
||||||
);
|
|
||||||
|
|
||||||
run_test("user_can_move_messages_to_another_topic_nobody_case", ({override}) => {
|
|
||||||
override(current_user, "is_admin", true);
|
|
||||||
override(current_user, "is_guest", false);
|
|
||||||
override(
|
|
||||||
realm,
|
|
||||||
"realm_edit_topic_policy",
|
|
||||||
settings_config.edit_topic_policy_values.nobody.code,
|
|
||||||
);
|
|
||||||
assert.equal(settings_data.user_can_move_messages_to_another_topic(), false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test_realm_group_settings(
|
test_realm_group_settings(
|
||||||
"realm_can_add_custom_emoji_group",
|
"realm_can_add_custom_emoji_group",
|
||||||
settings_data.user_can_add_custom_emoji,
|
settings_data.user_can_add_custom_emoji,
|
||||||
|
@ -243,6 +183,11 @@ test_realm_group_settings(
|
||||||
settings_data.user_can_move_messages_between_streams,
|
settings_data.user_can_move_messages_between_streams,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test_realm_group_settings(
|
||||||
|
"realm_can_move_messages_between_topics_group",
|
||||||
|
settings_data.user_can_move_messages_to_another_topic,
|
||||||
|
);
|
||||||
|
|
||||||
run_test("using_dark_theme", ({override}) => {
|
run_test("using_dark_theme", ({override}) => {
|
||||||
override(user_settings, "color_scheme", settings_config.color_scheme_values.dark.code);
|
override(user_settings, "color_scheme", settings_config.color_scheme_values.dark.code);
|
||||||
assert.equal(settings_data.using_dark_theme(), true);
|
assert.equal(settings_data.using_dark_theme(), true);
|
||||||
|
|
|
@ -439,19 +439,11 @@ function test_discard_changes_button({override}, discard_changes) {
|
||||||
};
|
};
|
||||||
|
|
||||||
override(realm, "realm_allow_edit_history", true);
|
override(realm, "realm_allow_edit_history", true);
|
||||||
override(
|
|
||||||
realm,
|
|
||||||
"realm_edit_topic_policy",
|
|
||||||
settings_config.common_message_policy_values.by_everyone.code,
|
|
||||||
);
|
|
||||||
override(realm, "realm_allow_message_editing", true);
|
override(realm, "realm_allow_message_editing", true);
|
||||||
override(realm, "realm_message_content_edit_limit_seconds", 3600);
|
override(realm, "realm_message_content_edit_limit_seconds", 3600);
|
||||||
override(realm, "realm_message_content_delete_limit_seconds", 120);
|
override(realm, "realm_message_content_delete_limit_seconds", 120);
|
||||||
|
|
||||||
const $allow_edit_history = $("#id_realm_allow_edit_history").prop("checked", false);
|
const $allow_edit_history = $("#id_realm_allow_edit_history").prop("checked", false);
|
||||||
const $edit_topic_policy = $("#id_realm_edit_topic_policy").val(
|
|
||||||
settings_config.common_message_policy_values.by_admins_only.code,
|
|
||||||
);
|
|
||||||
const $msg_edit_limit_setting = $("#id_realm_message_content_edit_limit_seconds").val(
|
const $msg_edit_limit_setting = $("#id_realm_message_content_edit_limit_seconds").val(
|
||||||
"custom_period",
|
"custom_period",
|
||||||
);
|
);
|
||||||
|
@ -468,7 +460,6 @@ function test_discard_changes_button({override}, discard_changes) {
|
||||||
$allow_edit_history.attr("id", "id_realm_allow_edit_history");
|
$allow_edit_history.attr("id", "id_realm_allow_edit_history");
|
||||||
$msg_edit_limit_setting.attr("id", "id_realm_message_content_edit_limit_seconds");
|
$msg_edit_limit_setting.attr("id", "id_realm_message_content_edit_limit_seconds");
|
||||||
$msg_delete_limit_setting.attr("id", "id_realm_message_content_delete_limit_seconds");
|
$msg_delete_limit_setting.attr("id", "id_realm_message_content_delete_limit_seconds");
|
||||||
$edit_topic_policy.attr("id", "id_realm_edit_topic_policy");
|
|
||||||
$message_content_edit_limit_minutes.attr("id", "id_realm_message_content_edit_limit_minutes");
|
$message_content_edit_limit_minutes.attr("id", "id_realm_message_content_edit_limit_minutes");
|
||||||
$message_content_delete_limit_minutes.attr(
|
$message_content_delete_limit_minutes.attr(
|
||||||
"id",
|
"id",
|
||||||
|
@ -480,7 +471,6 @@ function test_discard_changes_button({override}, discard_changes) {
|
||||||
$allow_edit_history,
|
$allow_edit_history,
|
||||||
$msg_edit_limit_setting,
|
$msg_edit_limit_setting,
|
||||||
$msg_delete_limit_setting,
|
$msg_delete_limit_setting,
|
||||||
$edit_topic_policy,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const {$discard_button, $save_button_controls, props} = createSaveButtons("msg-editing");
|
const {$discard_button, $save_button_controls, props} = createSaveButtons("msg-editing");
|
||||||
|
@ -494,10 +484,6 @@ function test_discard_changes_button({override}, discard_changes) {
|
||||||
discard_changes.call({to_$: () => $(".save-discard-widget-button.discard-button")}, ev);
|
discard_changes.call({to_$: () => $(".save-discard-widget-button.discard-button")}, ev);
|
||||||
|
|
||||||
assert.equal($allow_edit_history.prop("checked"), true);
|
assert.equal($allow_edit_history.prop("checked"), true);
|
||||||
assert.equal(
|
|
||||||
$edit_topic_policy.val(),
|
|
||||||
settings_config.common_message_policy_values.by_everyone.code,
|
|
||||||
);
|
|
||||||
assert.equal($msg_edit_limit_setting.val(), "3600");
|
assert.equal($msg_edit_limit_setting.val(), "3600");
|
||||||
assert.equal($message_content_edit_limit_minutes.val(), "60");
|
assert.equal($message_content_edit_limit_minutes.val(), "60");
|
||||||
assert.equal($msg_delete_limit_setting.val(), "120");
|
assert.equal($msg_delete_limit_setting.val(), "120");
|
||||||
|
|
|
@ -1078,6 +1078,7 @@ group_setting_update_data_type = DictType(
|
||||||
("can_delete_own_message_group", group_setting_type),
|
("can_delete_own_message_group", group_setting_type),
|
||||||
("can_manage_all_groups", group_setting_type),
|
("can_manage_all_groups", group_setting_type),
|
||||||
("can_move_messages_between_channels_group", group_setting_type),
|
("can_move_messages_between_channels_group", group_setting_type),
|
||||||
|
("can_move_messages_between_topics_group", group_setting_type),
|
||||||
("direct_message_initiator_group", group_setting_type),
|
("direct_message_initiator_group", group_setting_type),
|
||||||
("direct_message_permission_group", group_setting_type),
|
("direct_message_permission_group", group_setting_type),
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 5.0.9 on 2024-10-25 14:21
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("zerver", "0617_remove_prefix_from_archived_streams"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="realm",
|
||||||
|
name="can_move_messages_between_topics_group",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.RESTRICT,
|
||||||
|
related_name="+",
|
||||||
|
to="zerver.usergroup",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Generated by Django 4.2.1 on 2023-06-12 10:47
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||||
|
from django.db.migrations.state import StateApps
|
||||||
|
from django.db.models import OuterRef
|
||||||
|
|
||||||
|
|
||||||
|
def set_default_value_for_can_move_messages_between_topics_group(
|
||||||
|
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
|
||||||
|
) -> None:
|
||||||
|
Realm = apps.get_model("zerver", "Realm")
|
||||||
|
NamedUserGroup = apps.get_model("zerver", "NamedUserGroup")
|
||||||
|
|
||||||
|
edit_topic_policy_to_group_name = {
|
||||||
|
1: "role:members",
|
||||||
|
2: "role:administrators",
|
||||||
|
3: "role:fullmembers",
|
||||||
|
4: "role:moderators",
|
||||||
|
5: "role:everyone",
|
||||||
|
6: "role:nobody",
|
||||||
|
}
|
||||||
|
|
||||||
|
for id, group_name in edit_topic_policy_to_group_name.items():
|
||||||
|
Realm.objects.filter(
|
||||||
|
can_move_messages_between_topics_group=None, edit_topic_policy=id
|
||||||
|
).update(
|
||||||
|
can_move_messages_between_topics_group=NamedUserGroup.objects.filter(
|
||||||
|
name=group_name, realm=OuterRef("id"), is_system_group=True
|
||||||
|
).values("pk")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
atomic = False
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("zerver", "0618_realm_can_move_messages_between_topics_group"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
set_default_value_for_can_move_messages_between_topics_group,
|
||||||
|
elidable=True,
|
||||||
|
reverse_code=migrations.RunPython.noop,
|
||||||
|
)
|
||||||
|
]
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 5.0.9 on 2024-10-25 14:25
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("zerver", "0619_set_default_value_for_can_move_messages_between_topics_group"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="realm",
|
||||||
|
name="can_move_messages_between_topics_group",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.RESTRICT,
|
||||||
|
related_name="+",
|
||||||
|
to="zerver.usergroup",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -306,6 +306,11 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
|
||||||
"UserGroup", on_delete=models.RESTRICT, related_name="+"
|
"UserGroup", on_delete=models.RESTRICT, related_name="+"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# UserGroup which is allowed to move messages between topics.
|
||||||
|
can_move_messages_between_topics_group = models.ForeignKey(
|
||||||
|
"UserGroup", on_delete=models.RESTRICT, related_name="+"
|
||||||
|
)
|
||||||
|
|
||||||
# Who in the organization is allowed to edit topics of any message.
|
# Who in the organization is allowed to edit topics of any message.
|
||||||
edit_topic_policy = models.PositiveSmallIntegerField(default=EditTopicPolicyEnum.EVERYONE)
|
edit_topic_policy = models.PositiveSmallIntegerField(default=EditTopicPolicyEnum.EVERYONE)
|
||||||
|
|
||||||
|
@ -787,6 +792,15 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
|
||||||
default_group_name=SystemGroups.MEMBERS,
|
default_group_name=SystemGroups.MEMBERS,
|
||||||
id_field_name="can_move_messages_between_channels_group_id",
|
id_field_name="can_move_messages_between_channels_group_id",
|
||||||
),
|
),
|
||||||
|
can_move_messages_between_topics_group=GroupPermissionSetting(
|
||||||
|
require_system_group=not settings.ALLOW_GROUP_VALUED_SETTINGS,
|
||||||
|
allow_internet_group=False,
|
||||||
|
allow_owners_group=False,
|
||||||
|
allow_nobody_group=True,
|
||||||
|
allow_everyone_group=True,
|
||||||
|
default_group_name=SystemGroups.EVERYONE,
|
||||||
|
id_field_name="can_move_messages_between_topics_group_id",
|
||||||
|
),
|
||||||
direct_message_initiator_group=GroupPermissionSetting(
|
direct_message_initiator_group=GroupPermissionSetting(
|
||||||
require_system_group=not settings.ALLOW_GROUP_VALUED_SETTINGS,
|
require_system_group=not settings.ALLOW_GROUP_VALUED_SETTINGS,
|
||||||
allow_internet_group=False,
|
allow_internet_group=False,
|
||||||
|
@ -1203,6 +1217,8 @@ def get_realm_with_settings(realm_id: int) -> Realm:
|
||||||
"can_manage_all_groups__named_user_group",
|
"can_manage_all_groups__named_user_group",
|
||||||
"can_move_messages_between_channels_group",
|
"can_move_messages_between_channels_group",
|
||||||
"can_move_messages_between_channels_group__named_user_group",
|
"can_move_messages_between_channels_group__named_user_group",
|
||||||
|
"can_move_messages_between_topics_group",
|
||||||
|
"can_move_messages_between_topics_group__named_user_group",
|
||||||
"direct_message_initiator_group",
|
"direct_message_initiator_group",
|
||||||
"direct_message_initiator_group__named_user_group",
|
"direct_message_initiator_group__named_user_group",
|
||||||
"direct_message_permission_group",
|
"direct_message_permission_group",
|
||||||
|
|
|
@ -897,7 +897,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin, UserBaseSettings):
|
||||||
return self.has_permission("can_manage_all_groups")
|
return self.has_permission("can_manage_all_groups")
|
||||||
|
|
||||||
def can_move_messages_to_another_topic(self) -> bool:
|
def can_move_messages_to_another_topic(self) -> bool:
|
||||||
return self.has_permission("edit_topic_policy")
|
return self.has_permission("can_move_messages_between_topics_group")
|
||||||
|
|
||||||
def can_add_custom_emoji(self) -> bool:
|
def can_add_custom_emoji(self) -> bool:
|
||||||
return self.has_permission("can_add_custom_emoji_group")
|
return self.has_permission("can_add_custom_emoji_group")
|
||||||
|
|
|
@ -4515,6 +4515,20 @@ paths:
|
||||||
In Zulip 7.0 (feature level 159), `Nobody` was added as an option to
|
In Zulip 7.0 (feature level 159), `Nobody` was added as an option to
|
||||||
`move_messages_between_streams_policy` enum.
|
`move_messages_between_streams_policy` enum.
|
||||||
- $ref: "#/components/schemas/GroupSettingValue"
|
- $ref: "#/components/schemas/GroupSettingValue"
|
||||||
|
can_move_messages_between_topics_group:
|
||||||
|
allOf:
|
||||||
|
- description: |
|
||||||
|
A [group-setting value](/api/group-setting-values) defining the set of
|
||||||
|
users who have permission to move messages from one topic to another
|
||||||
|
within a channel in the organization.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 10.0 (feature level 316). Previously, this
|
||||||
|
permission was controlled by the enum `edit_topic_policy`. Values were
|
||||||
|
1=Members, 2=Admins, 3=Full members, 4=Moderators, 5=Everyone, 6=Nobody.
|
||||||
|
|
||||||
|
In Zulip 7.0 (feature level 159), `Nobody` was added as an option to
|
||||||
|
`edit_topic_policy` enum.
|
||||||
|
- $ref: "#/components/schemas/GroupSettingValue"
|
||||||
can_manage_all_groups:
|
can_manage_all_groups:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: "#/components/schemas/GroupSettingValue"
|
- $ref: "#/components/schemas/GroupSettingValue"
|
||||||
|
@ -8303,7 +8317,7 @@ paths:
|
||||||
|
|
||||||
- `allow_message_editing`
|
- `allow_message_editing`
|
||||||
- `can_move_messages_between_channels_group`
|
- `can_move_messages_between_channels_group`
|
||||||
- `edit_topic_policy`
|
- `can_move_messages_between_topics_group`
|
||||||
- `message_content_edit_limit_seconds`
|
- `message_content_edit_limit_seconds`
|
||||||
- `move_messages_within_stream_limit_seconds`
|
- `move_messages_within_stream_limit_seconds`
|
||||||
- `move_messages_between_streams_limit_seconds`
|
- `move_messages_between_streams_limit_seconds`
|
||||||
|
@ -8313,6 +8327,10 @@ paths:
|
||||||
of the [`realm op: update_dict`](/api/get-events#realm-update_dict)
|
of the [`realm op: update_dict`](/api/get-events#realm-update_dict)
|
||||||
event in [`GET /events`](/api/get-events).
|
event in [`GET /events`](/api/get-events).
|
||||||
|
|
||||||
|
**Changes**: In Zulip 10.0 (feature level 316), `edit_topic_policy`
|
||||||
|
was removed and replaced by `can_move_messages_between_topics_group`
|
||||||
|
realm setting.
|
||||||
|
|
||||||
**Changes**: In Zulip 10.0 (feature level 310), `move_messages_between_streams_policy`
|
**Changes**: In Zulip 10.0 (feature level 310), `move_messages_between_streams_policy`
|
||||||
was removed and replaced by `can_move_messages_between_channels_group`
|
was removed and replaced by `can_move_messages_between_channels_group`
|
||||||
realm setting.
|
realm setting.
|
||||||
|
@ -16351,6 +16369,22 @@ paths:
|
||||||
In Zulip 7.0 (feature level 159), `Nobody` was added as an option to
|
In Zulip 7.0 (feature level 159), `Nobody` was added as an option to
|
||||||
`move_messages_between_streams_policy` enum.
|
`move_messages_between_streams_policy` enum.
|
||||||
- $ref: "#/components/schemas/GroupSettingValue"
|
- $ref: "#/components/schemas/GroupSettingValue"
|
||||||
|
realm_can_move_messages_between_topics_group:
|
||||||
|
allOf:
|
||||||
|
- description: |
|
||||||
|
Present if `realm` is present in `fetch_event_types`.
|
||||||
|
|
||||||
|
A [group-setting value](/api/group-setting-values) defining the set of
|
||||||
|
users who have permission to move messages from one topic to another
|
||||||
|
within a channel in the organization.
|
||||||
|
|
||||||
|
**Changes**: New in Zulip 10.0 (feature level 316). Previously, this
|
||||||
|
permission was controlled by the enum `edit_topic_policy`. Values were
|
||||||
|
1=Members, 2=Admins, 3=Full members, 4=Moderators, 5=Everyone, 6=Nobody.
|
||||||
|
|
||||||
|
In Zulip 7.0 (feature level 159), `Nobody` was added as an option to
|
||||||
|
`edit_topic_policy` enum.
|
||||||
|
- $ref: "#/components/schemas/GroupSettingValue"
|
||||||
realm_bot_creation_policy:
|
realm_bot_creation_policy:
|
||||||
type: integer
|
type: integer
|
||||||
description: |
|
description: |
|
||||||
|
|
|
@ -31,6 +31,7 @@ from zerver.actions.realm_linkifiers import (
|
||||||
)
|
)
|
||||||
from zerver.actions.realm_playgrounds import check_add_realm_playground, do_remove_realm_playground
|
from zerver.actions.realm_playgrounds import check_add_realm_playground, do_remove_realm_playground
|
||||||
from zerver.actions.realm_settings import (
|
from zerver.actions.realm_settings import (
|
||||||
|
do_change_realm_permission_group_setting,
|
||||||
do_deactivate_realm,
|
do_deactivate_realm,
|
||||||
do_reactivate_realm,
|
do_reactivate_realm,
|
||||||
do_set_realm_authentication_methods,
|
do_set_realm_authentication_methods,
|
||||||
|
@ -89,7 +90,7 @@ from zerver.models.linkifiers import linkifiers_for_realm
|
||||||
from zerver.models.realm_audit_logs import AuditLogEventType
|
from zerver.models.realm_audit_logs import AuditLogEventType
|
||||||
from zerver.models.realm_emoji import EmojiInfo, get_all_custom_emoji_for_realm
|
from zerver.models.realm_emoji import EmojiInfo, get_all_custom_emoji_for_realm
|
||||||
from zerver.models.realm_playgrounds import get_realm_playgrounds
|
from zerver.models.realm_playgrounds import get_realm_playgrounds
|
||||||
from zerver.models.realms import EditTopicPolicyEnum, RealmDomainDict, get_realm, get_realm_domains
|
from zerver.models.realms import RealmDomainDict, get_realm, get_realm_domains
|
||||||
from zerver.models.streams import get_stream
|
from zerver.models.streams import get_stream
|
||||||
|
|
||||||
|
|
||||||
|
@ -546,14 +547,24 @@ class TestRealmAuditLog(ZulipTestCase):
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
administrators_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.ADMINISTRATORS, realm=realm, is_system_group=True
|
||||||
|
)
|
||||||
|
everyone_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.EVERYONE, realm=realm, is_system_group=True
|
||||||
|
)
|
||||||
|
|
||||||
value_expected = {
|
value_expected = {
|
||||||
RealmAuditLog.OLD_VALUE: EditTopicPolicyEnum.EVERYONE,
|
RealmAuditLog.OLD_VALUE: everyone_system_group.id,
|
||||||
RealmAuditLog.NEW_VALUE: EditTopicPolicyEnum.ADMINS_ONLY,
|
RealmAuditLog.NEW_VALUE: administrators_system_group.id,
|
||||||
"property": "edit_topic_policy",
|
"property": "can_move_messages_between_topics_group",
|
||||||
}
|
}
|
||||||
|
|
||||||
do_set_realm_property(
|
do_change_realm_permission_group_setting(
|
||||||
realm, "edit_topic_policy", EditTopicPolicyEnum.ADMINS_ONLY, acting_user=user
|
realm,
|
||||||
|
"can_move_messages_between_topics_group",
|
||||||
|
administrators_system_group,
|
||||||
|
acting_user=user,
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
RealmAuditLog.objects.filter(
|
RealmAuditLog.objects.filter(
|
||||||
|
|
|
@ -138,6 +138,7 @@ class HomeTest(ZulipTestCase):
|
||||||
"realm_can_delete_own_message_group",
|
"realm_can_delete_own_message_group",
|
||||||
"realm_can_manage_all_groups",
|
"realm_can_manage_all_groups",
|
||||||
"realm_can_move_messages_between_channels_group",
|
"realm_can_move_messages_between_channels_group",
|
||||||
|
"realm_can_move_messages_between_topics_group",
|
||||||
"realm_create_multiuse_invite_group",
|
"realm_create_multiuse_invite_group",
|
||||||
"realm_create_private_stream_policy",
|
"realm_create_private_stream_policy",
|
||||||
"realm_create_public_stream_policy",
|
"realm_create_public_stream_policy",
|
||||||
|
|
|
@ -6,7 +6,11 @@ import orjson
|
||||||
from django.utils.timezone import now as timezone_now
|
from django.utils.timezone import now as timezone_now
|
||||||
|
|
||||||
from zerver.actions.message_edit import get_mentions_for_message_updates
|
from zerver.actions.message_edit import get_mentions_for_message_updates
|
||||||
from zerver.actions.realm_settings import do_change_realm_plan_type, do_set_realm_property
|
from zerver.actions.realm_settings import (
|
||||||
|
do_change_realm_permission_group_setting,
|
||||||
|
do_change_realm_plan_type,
|
||||||
|
do_set_realm_property,
|
||||||
|
)
|
||||||
from zerver.actions.streams import do_deactivate_stream
|
from zerver.actions.streams import do_deactivate_stream
|
||||||
from zerver.actions.user_groups import add_subgroups_to_user_group, check_add_user_group
|
from zerver.actions.user_groups import add_subgroups_to_user_group, check_add_user_group
|
||||||
from zerver.actions.user_topics import do_set_user_topic_visibility_policy
|
from zerver.actions.user_topics import do_set_user_topic_visibility_policy
|
||||||
|
@ -18,7 +22,7 @@ from zerver.lib.topic import TOPIC_NAME
|
||||||
from zerver.lib.utils import assert_is_not_none
|
from zerver.lib.utils import assert_is_not_none
|
||||||
from zerver.models import Attachment, Message, NamedUserGroup, Realm, UserProfile, UserTopic
|
from zerver.models import Attachment, Message, NamedUserGroup, Realm, UserProfile, UserTopic
|
||||||
from zerver.models.groups import SystemGroups
|
from zerver.models.groups import SystemGroups
|
||||||
from zerver.models.realms import EditTopicPolicyEnum, WildcardMentionPolicyEnum, get_realm
|
from zerver.models.realms import WildcardMentionPolicyEnum, get_realm
|
||||||
from zerver.models.streams import get_stream
|
from zerver.models.streams import get_stream
|
||||||
|
|
||||||
|
|
||||||
|
@ -892,7 +896,7 @@ class EditMessageTest(ZulipTestCase):
|
||||||
def set_message_editing_params(
|
def set_message_editing_params(
|
||||||
allow_message_editing: bool,
|
allow_message_editing: bool,
|
||||||
message_content_edit_limit_seconds: int | str,
|
message_content_edit_limit_seconds: int | str,
|
||||||
edit_topic_policy: int,
|
can_move_messages_between_topics_group: NamedUserGroup,
|
||||||
) -> None:
|
) -> None:
|
||||||
result = self.client_patch(
|
result = self.client_patch(
|
||||||
"/json/realm",
|
"/json/realm",
|
||||||
|
@ -901,7 +905,11 @@ class EditMessageTest(ZulipTestCase):
|
||||||
"message_content_edit_limit_seconds": orjson.dumps(
|
"message_content_edit_limit_seconds": orjson.dumps(
|
||||||
message_content_edit_limit_seconds
|
message_content_edit_limit_seconds
|
||||||
).decode(),
|
).decode(),
|
||||||
"edit_topic_policy": orjson.dumps(edit_topic_policy).decode(),
|
"can_move_messages_between_topics_group": orjson.dumps(
|
||||||
|
{
|
||||||
|
"new": can_move_messages_between_topics_group.id,
|
||||||
|
}
|
||||||
|
).decode(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
|
@ -949,31 +957,35 @@ class EditMessageTest(ZulipTestCase):
|
||||||
message.date_sent -= timedelta(seconds=180)
|
message.date_sent -= timedelta(seconds=180)
|
||||||
message.save()
|
message.save()
|
||||||
|
|
||||||
|
administrators_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.ADMINISTRATORS, realm=get_realm("zulip"), is_system_group=True
|
||||||
|
)
|
||||||
|
|
||||||
# test the various possible message editing settings
|
# test the various possible message editing settings
|
||||||
# high enough time limit, all edits allowed
|
# high enough time limit, all edits allowed
|
||||||
set_message_editing_params(True, 240, EditTopicPolicyEnum.ADMINS_ONLY)
|
set_message_editing_params(True, 240, administrators_system_group)
|
||||||
do_edit_message_assert_success(id_, "A")
|
do_edit_message_assert_success(id_, "A")
|
||||||
|
|
||||||
# out of time, only topic editing allowed
|
# out of time, only topic editing allowed
|
||||||
set_message_editing_params(True, 120, EditTopicPolicyEnum.ADMINS_ONLY)
|
set_message_editing_params(True, 120, administrators_system_group)
|
||||||
do_edit_message_assert_success(id_, "B", True)
|
do_edit_message_assert_success(id_, "B", True)
|
||||||
do_edit_message_assert_error(id_, "C", "The time limit for editing this message has passed")
|
do_edit_message_assert_error(id_, "C", "The time limit for editing this message has passed")
|
||||||
|
|
||||||
# infinite time, all edits allowed
|
# infinite time, all edits allowed
|
||||||
set_message_editing_params(True, "unlimited", EditTopicPolicyEnum.ADMINS_ONLY)
|
set_message_editing_params(True, "unlimited", administrators_system_group)
|
||||||
do_edit_message_assert_success(id_, "D")
|
do_edit_message_assert_success(id_, "D")
|
||||||
|
|
||||||
# without allow_message_editing, editing content is not allowed but
|
# without allow_message_editing, editing content is not allowed but
|
||||||
# editing topic is allowed if topic-edit time limit has not passed
|
# editing topic is allowed if topic-edit time limit has not passed
|
||||||
# irrespective of content-edit time limit.
|
# irrespective of content-edit time limit.
|
||||||
set_message_editing_params(False, 240, EditTopicPolicyEnum.ADMINS_ONLY)
|
set_message_editing_params(False, 240, administrators_system_group)
|
||||||
do_edit_message_assert_success(id_, "B", True)
|
do_edit_message_assert_success(id_, "B", True)
|
||||||
|
|
||||||
set_message_editing_params(False, 240, EditTopicPolicyEnum.ADMINS_ONLY)
|
set_message_editing_params(False, 240, administrators_system_group)
|
||||||
do_edit_message_assert_success(id_, "E", True)
|
do_edit_message_assert_success(id_, "E", True)
|
||||||
set_message_editing_params(False, 120, EditTopicPolicyEnum.ADMINS_ONLY)
|
set_message_editing_params(False, 120, administrators_system_group)
|
||||||
do_edit_message_assert_success(id_, "F", True)
|
do_edit_message_assert_success(id_, "F", True)
|
||||||
set_message_editing_params(False, "unlimited", EditTopicPolicyEnum.ADMINS_ONLY)
|
set_message_editing_params(False, "unlimited", administrators_system_group)
|
||||||
do_edit_message_assert_success(id_, "G", True)
|
do_edit_message_assert_success(id_, "G", True)
|
||||||
|
|
||||||
def test_edit_message_in_archived_stream(self) -> None:
|
def test_edit_message_in_archived_stream(self) -> None:
|
||||||
|
@ -1003,11 +1015,11 @@ class EditMessageTest(ZulipTestCase):
|
||||||
)
|
)
|
||||||
self.assert_json_error(result, "Invalid message(s)")
|
self.assert_json_error(result, "Invalid message(s)")
|
||||||
|
|
||||||
def test_edit_topic_policy(self) -> None:
|
def test_can_move_messages_between_topics_group(self) -> None:
|
||||||
def set_message_editing_params(
|
def set_message_editing_params(
|
||||||
allow_message_editing: bool,
|
allow_message_editing: bool,
|
||||||
message_content_edit_limit_seconds: int | str,
|
message_content_edit_limit_seconds: int | str,
|
||||||
edit_topic_policy: int,
|
can_move_messages_between_topics_group: NamedUserGroup,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.login("iago")
|
self.login("iago")
|
||||||
result = self.client_patch(
|
result = self.client_patch(
|
||||||
|
@ -1017,7 +1029,11 @@ class EditMessageTest(ZulipTestCase):
|
||||||
"message_content_edit_limit_seconds": orjson.dumps(
|
"message_content_edit_limit_seconds": orjson.dumps(
|
||||||
message_content_edit_limit_seconds
|
message_content_edit_limit_seconds
|
||||||
).decode(),
|
).decode(),
|
||||||
"edit_topic_policy": orjson.dumps(edit_topic_policy).decode(),
|
"can_move_messages_between_topics_group": orjson.dumps(
|
||||||
|
{
|
||||||
|
"new": can_move_messages_between_topics_group.id,
|
||||||
|
}
|
||||||
|
).decode(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
|
@ -1056,30 +1072,51 @@ class EditMessageTest(ZulipTestCase):
|
||||||
|
|
||||||
# Guest user must be subscribed to the stream to access the message.
|
# Guest user must be subscribed to the stream to access the message.
|
||||||
polonius = self.example_user("polonius")
|
polonius = self.example_user("polonius")
|
||||||
|
realm = polonius.realm
|
||||||
self.subscribe(polonius, "Denmark")
|
self.subscribe(polonius, "Denmark")
|
||||||
|
|
||||||
|
administrators_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.ADMINISTRATORS, realm=realm, is_system_group=True
|
||||||
|
)
|
||||||
|
full_members_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.FULL_MEMBERS, realm=realm, is_system_group=True
|
||||||
|
)
|
||||||
|
members_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.MEMBERS, realm=realm, is_system_group=True
|
||||||
|
)
|
||||||
|
moderators_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.MODERATORS, realm=realm, is_system_group=True
|
||||||
|
)
|
||||||
|
everyone_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.EVERYONE, realm=realm, is_system_group=True
|
||||||
|
)
|
||||||
|
nobody_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.NOBODY, realm=realm, is_system_group=True
|
||||||
|
)
|
||||||
|
|
||||||
# any user can edit the topic of a message
|
# any user can edit the topic of a message
|
||||||
set_message_editing_params(True, "unlimited", EditTopicPolicyEnum.EVERYONE)
|
set_message_editing_params(True, "unlimited", everyone_system_group)
|
||||||
do_edit_message_assert_success(id_, "A", "polonius")
|
do_edit_message_assert_success(id_, "A", "polonius")
|
||||||
|
|
||||||
# only members can edit topic of a message
|
# only members can edit topic of a message
|
||||||
set_message_editing_params(True, "unlimited", EditTopicPolicyEnum.MEMBERS_ONLY)
|
set_message_editing_params(True, "unlimited", members_system_group)
|
||||||
do_edit_message_assert_error(
|
do_edit_message_assert_error(
|
||||||
id_, "B", "You don't have permission to edit this message", "polonius"
|
id_, "B", "You don't have permission to edit this message", "polonius"
|
||||||
)
|
)
|
||||||
do_edit_message_assert_success(id_, "B", "cordelia")
|
do_edit_message_assert_success(id_, "B", "cordelia")
|
||||||
|
|
||||||
# only full members can edit topic of a message
|
# only full members can edit topic of a message
|
||||||
set_message_editing_params(True, "unlimited", EditTopicPolicyEnum.FULL_MEMBERS_ONLY)
|
set_message_editing_params(True, "unlimited", full_members_system_group)
|
||||||
|
|
||||||
cordelia = self.example_user("cordelia")
|
cordelia = self.example_user("cordelia")
|
||||||
hamlet = self.example_user("hamlet")
|
hamlet = self.example_user("hamlet")
|
||||||
do_set_realm_property(cordelia.realm, "waiting_period_threshold", 10, acting_user=None)
|
|
||||||
|
|
||||||
cordelia.date_joined = timezone_now() - timedelta(days=9)
|
cordelia.date_joined = timezone_now() - timedelta(days=9)
|
||||||
cordelia.save()
|
cordelia.save()
|
||||||
hamlet.date_joined = timezone_now() - timedelta(days=9)
|
hamlet.date_joined = timezone_now() - timedelta(days=9)
|
||||||
hamlet.save()
|
hamlet.save()
|
||||||
|
|
||||||
|
do_set_realm_property(cordelia.realm, "waiting_period_threshold", 10, acting_user=None)
|
||||||
do_edit_message_assert_error(
|
do_edit_message_assert_error(
|
||||||
id_, "C", "You don't have permission to edit this message", "cordelia"
|
id_, "C", "You don't have permission to edit this message", "cordelia"
|
||||||
)
|
)
|
||||||
|
@ -1089,15 +1126,12 @@ class EditMessageTest(ZulipTestCase):
|
||||||
id_, "C", "You don't have permission to edit this message", "hamlet"
|
id_, "C", "You don't have permission to edit this message", "hamlet"
|
||||||
)
|
)
|
||||||
|
|
||||||
cordelia.date_joined = timezone_now() - timedelta(days=11)
|
do_set_realm_property(cordelia.realm, "waiting_period_threshold", 8, acting_user=None)
|
||||||
cordelia.save()
|
|
||||||
hamlet.date_joined = timezone_now() - timedelta(days=11)
|
|
||||||
hamlet.save()
|
|
||||||
do_edit_message_assert_success(id_, "C", "cordelia")
|
do_edit_message_assert_success(id_, "C", "cordelia")
|
||||||
do_edit_message_assert_success(id_, "CD", "hamlet")
|
do_edit_message_assert_success(id_, "CD", "hamlet")
|
||||||
|
|
||||||
# only moderators can edit topic of a message
|
# only moderators can edit topic of a message
|
||||||
set_message_editing_params(True, "unlimited", EditTopicPolicyEnum.MODERATORS_ONLY)
|
set_message_editing_params(True, "unlimited", moderators_system_group)
|
||||||
do_edit_message_assert_error(
|
do_edit_message_assert_error(
|
||||||
id_, "D", "You don't have permission to edit this message", "cordelia"
|
id_, "D", "You don't have permission to edit this message", "cordelia"
|
||||||
)
|
)
|
||||||
|
@ -1108,14 +1142,14 @@ class EditMessageTest(ZulipTestCase):
|
||||||
do_edit_message_assert_success(id_, "D", "shiva")
|
do_edit_message_assert_success(id_, "D", "shiva")
|
||||||
|
|
||||||
# only admins can edit the topics of messages
|
# only admins can edit the topics of messages
|
||||||
set_message_editing_params(True, "unlimited", EditTopicPolicyEnum.ADMINS_ONLY)
|
set_message_editing_params(True, "unlimited", administrators_system_group)
|
||||||
do_edit_message_assert_error(
|
do_edit_message_assert_error(
|
||||||
id_, "E", "You don't have permission to edit this message", "shiva"
|
id_, "E", "You don't have permission to edit this message", "shiva"
|
||||||
)
|
)
|
||||||
do_edit_message_assert_success(id_, "E", "iago")
|
do_edit_message_assert_success(id_, "E", "iago")
|
||||||
|
|
||||||
# even owners and admins cannot edit the topics of messages
|
# even owners and admins cannot edit the topics of messages
|
||||||
set_message_editing_params(True, "unlimited", EditTopicPolicyEnum.NOBODY)
|
set_message_editing_params(True, "unlimited", nobody_system_group)
|
||||||
do_edit_message_assert_error(
|
do_edit_message_assert_error(
|
||||||
id_, "H", "You don't have permission to edit this message", "desdemona"
|
id_, "H", "You don't have permission to edit this message", "desdemona"
|
||||||
)
|
)
|
||||||
|
@ -1124,14 +1158,14 @@ class EditMessageTest(ZulipTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
# users can edit topics even if allow_message_editing is False
|
# users can edit topics even if allow_message_editing is False
|
||||||
set_message_editing_params(False, "unlimited", EditTopicPolicyEnum.EVERYONE)
|
set_message_editing_params(False, "unlimited", everyone_system_group)
|
||||||
do_edit_message_assert_success(id_, "D", "cordelia")
|
do_edit_message_assert_success(id_, "D", "cordelia")
|
||||||
|
|
||||||
# non-admin users cannot edit topics sent > 1 week ago including
|
# non-admin users cannot edit topics sent > 1 week ago including
|
||||||
# sender of the message.
|
# sender of the message.
|
||||||
message.date_sent -= timedelta(seconds=604900)
|
message.date_sent -= timedelta(seconds=604900)
|
||||||
message.save()
|
message.save()
|
||||||
set_message_editing_params(True, "unlimited", EditTopicPolicyEnum.EVERYONE)
|
set_message_editing_params(True, "unlimited", everyone_system_group)
|
||||||
do_edit_message_assert_success(id_, "E", "iago")
|
do_edit_message_assert_success(id_, "E", "iago")
|
||||||
do_edit_message_assert_success(id_, "F", "shiva")
|
do_edit_message_assert_success(id_, "F", "shiva")
|
||||||
do_edit_message_assert_error(
|
do_edit_message_assert_error(
|
||||||
|
@ -1158,6 +1192,39 @@ class EditMessageTest(ZulipTestCase):
|
||||||
do_edit_message_assert_success(id_, "G", "cordelia")
|
do_edit_message_assert_success(id_, "G", "cordelia")
|
||||||
do_edit_message_assert_success(id_, "H", "hamlet")
|
do_edit_message_assert_success(id_, "H", "hamlet")
|
||||||
|
|
||||||
|
# Test for checking setting for non-system user group.
|
||||||
|
user_group = check_add_user_group(
|
||||||
|
realm, "new_group", [polonius, cordelia], acting_user=cordelia
|
||||||
|
)
|
||||||
|
set_message_editing_params(True, "unlimited", user_group)
|
||||||
|
# Polonius and Cordelia are in the allowed user group, so can move messages.
|
||||||
|
do_edit_message_assert_success(id_, "I", "polonius")
|
||||||
|
do_edit_message_assert_success(id_, "J", "cordelia")
|
||||||
|
# Iago is not in the allowed user group, so cannot move messages.
|
||||||
|
do_edit_message_assert_error(
|
||||||
|
id_, "K", "You don't have permission to edit this message", "iago"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test for checking the setting for anonymous user group.
|
||||||
|
anonymous_user_group = self.create_or_update_anonymous_group_for_setting(
|
||||||
|
[cordelia],
|
||||||
|
[administrators_system_group],
|
||||||
|
)
|
||||||
|
do_change_realm_permission_group_setting(
|
||||||
|
realm,
|
||||||
|
"can_move_messages_between_topics_group",
|
||||||
|
anonymous_user_group,
|
||||||
|
acting_user=None,
|
||||||
|
)
|
||||||
|
# Cordelia is the direct member of the anonymous user group, so can move messages.
|
||||||
|
do_edit_message_assert_success(id_, "K", "cordelia")
|
||||||
|
# Iago is in the `administrators_system_group` subgroup, so can move messages.
|
||||||
|
do_edit_message_assert_success(id_, "L", "iago")
|
||||||
|
# Shiva is not in the anonymous user group, so cannot move messages.
|
||||||
|
do_edit_message_assert_error(
|
||||||
|
id_, "M", "You don't have permission to edit this message", "shiva"
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch("zerver.actions.message_edit.send_event_on_commit")
|
@mock.patch("zerver.actions.message_edit.send_event_on_commit")
|
||||||
def test_topic_wildcard_mention_in_followed_topic(
|
def test_topic_wildcard_mention_in_followed_topic(
|
||||||
self, mock_send_event: mock.MagicMock
|
self, mock_send_event: mock.MagicMock
|
||||||
|
|
|
@ -16,7 +16,7 @@ from zerver.lib.test_helpers import queries_captured
|
||||||
from zerver.lib.url_encoding import near_stream_message_url
|
from zerver.lib.url_encoding import near_stream_message_url
|
||||||
from zerver.models import Message, NamedUserGroup, Stream, UserMessage, UserProfile
|
from zerver.models import Message, NamedUserGroup, Stream, UserMessage, UserProfile
|
||||||
from zerver.models.groups import SystemGroups
|
from zerver.models.groups import SystemGroups
|
||||||
from zerver.models.realms import EditTopicPolicyEnum, get_realm
|
from zerver.models.realms import get_realm
|
||||||
from zerver.models.streams import get_stream
|
from zerver.models.streams import get_stream
|
||||||
|
|
||||||
|
|
||||||
|
@ -1130,10 +1130,19 @@ class MessageMoveStreamTest(ZulipTestCase):
|
||||||
(user_profile, old_stream, new_stream, msg_id, msg_id_later) = self.prepare_move_topics(
|
(user_profile, old_stream, new_stream, msg_id, msg_id_later) = self.prepare_move_topics(
|
||||||
"othello", "old_stream_1", "new_stream_1", "test"
|
"othello", "old_stream_1", "new_stream_1", "test"
|
||||||
)
|
)
|
||||||
|
|
||||||
realm = user_profile.realm
|
realm = user_profile.realm
|
||||||
realm.edit_topic_policy = EditTopicPolicyEnum.ADMINS_ONLY
|
|
||||||
realm.save()
|
administrators_system_group = NamedUserGroup.objects.get(
|
||||||
|
name=SystemGroups.ADMINISTRATORS, realm=realm, is_system_group=True
|
||||||
|
)
|
||||||
|
|
||||||
|
do_change_realm_permission_group_setting(
|
||||||
|
realm,
|
||||||
|
"can_move_messages_between_topics_group",
|
||||||
|
administrators_system_group,
|
||||||
|
acting_user=None,
|
||||||
|
)
|
||||||
|
|
||||||
self.login("cordelia")
|
self.login("cordelia")
|
||||||
|
|
||||||
members_system_group = NamedUserGroup.objects.get(
|
members_system_group = NamedUserGroup.objects.get(
|
||||||
|
@ -1175,7 +1184,7 @@ class MessageMoveStreamTest(ZulipTestCase):
|
||||||
"iago", "test move stream", "new stream", "test"
|
"iago", "test move stream", "new stream", "test"
|
||||||
)
|
)
|
||||||
|
|
||||||
with self.assert_database_query_count(53), self.assert_memcached_count(14):
|
with self.assert_database_query_count(55), self.assert_memcached_count(14):
|
||||||
result = self.client_patch(
|
result = self.client_patch(
|
||||||
f"/json/messages/{msg_id}",
|
f"/json/messages/{msg_id}",
|
||||||
{
|
{
|
||||||
|
|
|
@ -266,7 +266,7 @@ class MessageMoveTopicTest(ZulipTestCase):
|
||||||
# state + 1/user with a UserTopic row for the events data)
|
# state + 1/user with a UserTopic row for the events data)
|
||||||
# beyond what is typical were there not UserTopic records to
|
# beyond what is typical were there not UserTopic records to
|
||||||
# update. Ideally, we'd eliminate the per-user component.
|
# update. Ideally, we'd eliminate the per-user component.
|
||||||
with self.assert_database_query_count(25):
|
with self.assert_database_query_count(27):
|
||||||
check_update_message(
|
check_update_message(
|
||||||
user_profile=hamlet,
|
user_profile=hamlet,
|
||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
|
@ -426,7 +426,7 @@ class MessageMoveTopicTest(ZulipTestCase):
|
||||||
set_topic_visibility_policy(desdemona, muted_topics, UserTopic.VisibilityPolicy.MUTED)
|
set_topic_visibility_policy(desdemona, muted_topics, UserTopic.VisibilityPolicy.MUTED)
|
||||||
set_topic_visibility_policy(cordelia, muted_topics, UserTopic.VisibilityPolicy.MUTED)
|
set_topic_visibility_policy(cordelia, muted_topics, UserTopic.VisibilityPolicy.MUTED)
|
||||||
|
|
||||||
with self.assert_database_query_count(29):
|
with self.assert_database_query_count(31):
|
||||||
check_update_message(
|
check_update_message(
|
||||||
user_profile=desdemona,
|
user_profile=desdemona,
|
||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
|
@ -449,7 +449,7 @@ class MessageMoveTopicTest(ZulipTestCase):
|
||||||
second_message_id = self.send_stream_message(
|
second_message_id = self.send_stream_message(
|
||||||
hamlet, stream_name, topic_name="changed topic name", content="Second message"
|
hamlet, stream_name, topic_name="changed topic name", content="Second message"
|
||||||
)
|
)
|
||||||
with self.assert_database_query_count(23):
|
with self.assert_database_query_count(24):
|
||||||
check_update_message(
|
check_update_message(
|
||||||
user_profile=desdemona,
|
user_profile=desdemona,
|
||||||
message_id=second_message_id,
|
message_id=second_message_id,
|
||||||
|
@ -528,7 +528,7 @@ class MessageMoveTopicTest(ZulipTestCase):
|
||||||
users_to_be_notified_via_muted_topics_event.append(user_topic.user_profile_id)
|
users_to_be_notified_via_muted_topics_event.append(user_topic.user_profile_id)
|
||||||
|
|
||||||
change_all_topic_name = "Topic 1 edited"
|
change_all_topic_name = "Topic 1 edited"
|
||||||
with self.assert_database_query_count(30):
|
with self.assert_database_query_count(32):
|
||||||
check_update_message(
|
check_update_message(
|
||||||
user_profile=hamlet,
|
user_profile=hamlet,
|
||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
|
|
|
@ -143,6 +143,7 @@ def update_realm(
|
||||||
can_create_web_public_channel_group: Json[GroupSettingChangeRequest] | None = None,
|
can_create_web_public_channel_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
can_manage_all_groups: Json[GroupSettingChangeRequest] | None = None,
|
can_manage_all_groups: Json[GroupSettingChangeRequest] | None = None,
|
||||||
can_move_messages_between_channels_group: Json[GroupSettingChangeRequest] | None = None,
|
can_move_messages_between_channels_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
|
can_move_messages_between_topics_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
direct_message_initiator_group: Json[GroupSettingChangeRequest] | None = None,
|
direct_message_initiator_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
direct_message_permission_group: Json[GroupSettingChangeRequest] | None = None,
|
direct_message_permission_group: Json[GroupSettingChangeRequest] | None = None,
|
||||||
invite_to_stream_policy: Json[CommonPolicyEnum] | None = None,
|
invite_to_stream_policy: Json[CommonPolicyEnum] | None = None,
|
||||||
|
|
Loading…
Reference in New Issue