models: Replace allow_community_topic_editing with edit_topic_policy.

This commit replaces the allow_community_topic_editing boolean with
integer field edit_topic_policy and includes both frontend and
backend changes.

We also update settings_ui.disable_sub_settings_onchange to not
change the color of label as we did previously when the setting
was a checkbox. But now as the setting is dropdown we keep the
label as it is and we don't do anything with label when disabling
dropdowns. Also, this function was used only here so we can safely
change this.
This commit is contained in:
sahil839 2021-05-26 15:51:37 +05:30 committed by Tim Abbott
parent 283a3a5c28
commit 828759d2ba
25 changed files with 219 additions and 100 deletions

View File

@ -9,6 +9,7 @@ const {page_params} = require("../zjsunit/zpage_params");
page_params.realm_community_topic_editing_limit_seconds = 259200; page_params.realm_community_topic_editing_limit_seconds = 259200;
const message_edit = zrequire("message_edit"); const message_edit = zrequire("message_edit");
const settings_config = zrequire("settings_config");
const get_editability = message_edit.get_editability; const get_editability = message_edit.get_editability;
const editability_types = message_edit.editability_types; const editability_types = message_edit.editability_types;
@ -81,7 +82,8 @@ run_test("get_editability", () => {
sent_by_me: false, sent_by_me: false,
type: "stream", type: "stream",
}; };
page_params.realm_allow_community_topic_editing = true; page_params.realm_edit_topic_policy =
settings_config.common_message_policy_values.by_everyone.code;
page_params.realm_allow_message_editing = true; page_params.realm_allow_message_editing = true;
page_params.realm_message_content_edit_limit_seconds = 0; page_params.realm_message_content_edit_limit_seconds = 0;
page_params.realm_community_topic_editing_limit_seconds = 259200; page_params.realm_community_topic_editing_limit_seconds = 259200;
@ -93,15 +95,18 @@ run_test("get_editability", () => {
assert.equal(message_edit.is_topic_editable(message), true); assert.equal(message_edit.is_topic_editable(message), true);
message.sent_by_me = true; message.sent_by_me = true;
page_params.realm_allow_community_topic_editing = false; page_params.realm_edit_topic_policy =
settings_config.common_message_policy_values.by_admins_only.code;
assert.equal(message_edit.is_topic_editable(message), true); assert.equal(message_edit.is_topic_editable(message), true);
message.sent_by_me = false; message.sent_by_me = false;
page_params.realm_allow_community_topic_editing = false; page_params.realm_edit_topic_policy =
settings_config.common_message_policy_values.by_admins_only.code;
assert.equal(message_edit.is_topic_editable(message), false); assert.equal(message_edit.is_topic_editable(message), false);
message.sent_by_me = false; message.sent_by_me = false;
page_params.realm_allow_community_topic_editing = false; page_params.realm_edit_topic_policy =
settings_config.common_message_policy_values.by_admins_only.code;
page_params.is_admin = true; page_params.is_admin = true;
assert.equal(message_edit.is_topic_editable(message), true); assert.equal(message_edit.is_topic_editable(message), true);

View File

@ -583,16 +583,16 @@ function test_discard_changes_button(discard_changes) {
}; };
page_params.realm_allow_edit_history = true; page_params.realm_allow_edit_history = true;
page_params.realm_allow_community_topic_editing = true; page_params.realm_edit_topic_policy =
settings_config.common_message_policy_values.by_everyone.code;
page_params.realm_allow_message_editing = true; page_params.realm_allow_message_editing = true;
page_params.realm_message_content_edit_limit_seconds = 3600; page_params.realm_message_content_edit_limit_seconds = 3600;
page_params.realm_allow_message_deleting = true; page_params.realm_allow_message_deleting = true;
page_params.realm_message_content_delete_limit_seconds = 120; page_params.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 allow_community_topic_editing = $("#id_realm_allow_community_topic_editing").prop( const edit_topic_policy = $("#id_realm_edit_topic_policy").val(
"checked", settings_config.common_message_policy_values.by_admins_only.code,
true,
); );
const msg_edit_limit_setting = $("#id_realm_msg_edit_limit_setting").val("custom_limit"); const msg_edit_limit_setting = $("#id_realm_msg_edit_limit_setting").val("custom_limit");
const message_content_edit_limit_minutes = $( const message_content_edit_limit_minutes = $(
@ -606,7 +606,7 @@ function test_discard_changes_button(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_msg_edit_limit_setting"); msg_edit_limit_setting.attr("id", "id_realm_msg_edit_limit_setting");
msg_delete_limit_setting.attr("id", "id_realm_msg_delete_limit_setting"); msg_delete_limit_setting.attr("id", "id_realm_msg_delete_limit_setting");
allow_community_topic_editing.attr("id", "id_realm_allow_community_topic_editing"); 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",
@ -618,7 +618,7 @@ function test_discard_changes_button(discard_changes) {
allow_edit_history, allow_edit_history,
msg_edit_limit_setting, msg_edit_limit_setting,
msg_delete_limit_setting, msg_delete_limit_setting,
allow_community_topic_editing, edit_topic_policy,
message_content_edit_limit_minutes, message_content_edit_limit_minutes,
message_content_delete_limit_minutes, message_content_delete_limit_minutes,
]; ];
@ -633,7 +633,10 @@ function test_discard_changes_button(discard_changes) {
discard_changes(ev); discard_changes(ev);
assert.equal(allow_edit_history.prop("checked"), true); assert.equal(allow_edit_history.prop("checked"), true);
assert.equal(allow_community_topic_editing.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(), "upto_one_hour"); assert.equal(msg_edit_limit_setting.val(), "upto_one_hour");
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(), "upto_two_min"); assert.equal(msg_delete_limit_setting.val(), "upto_two_min");
@ -685,9 +688,6 @@ test("set_up", ({override}) => {
const waiting_period_parent_elem = $.create("waiting-period-parent-stub"); const waiting_period_parent_elem = $.create("waiting-period-parent-stub");
$("#id_realm_waiting_period_threshold").set_parent(waiting_period_parent_elem); $("#id_realm_waiting_period_threshold").set_parent(waiting_period_parent_elem);
const allow_topic_edit_label_parent = $.create("allow-topic-edit-label-parent");
$("#id_realm_allow_community_topic_editing_label").set_parent(allow_topic_edit_label_parent);
// TEST set_up() here, but this mostly just allows us to // TEST set_up() here, but this mostly just allows us to
// get access to the click handlers. // get access to the click handlers.
override(settings_org, "maybe_disable_widgets", noop); override(settings_org, "maybe_disable_widgets", noop);

View File

@ -18,9 +18,6 @@ import * as settings_toggle from "./settings_toggle";
const admin_settings_label = { const admin_settings_label = {
// Organization settings // Organization settings
realm_allow_community_topic_editing: $t({
defaultMessage: "Users can edit the topic of any message",
}),
realm_allow_edit_history: $t({defaultMessage: "Enable message edit history"}), realm_allow_edit_history: $t({defaultMessage: "Enable message edit history"}),
realm_mandatory_topics: $t({defaultMessage: "Require topics in stream messages"}), realm_mandatory_topics: $t({defaultMessage: "Require topics in stream messages"}),
realm_notifications_stream: $t({defaultMessage: "New stream notifications:"}), realm_notifications_stream: $t({defaultMessage: "New stream notifications:"}),
@ -82,7 +79,6 @@ export function build_page() {
realm_avatar_changes_disabled: page_params.realm_avatar_changes_disabled, realm_avatar_changes_disabled: page_params.realm_avatar_changes_disabled,
realm_add_emoji_by_admins_only: page_params.realm_add_emoji_by_admins_only, realm_add_emoji_by_admins_only: page_params.realm_add_emoji_by_admins_only,
can_add_emojis: settings_emoji.can_add_emoji(), can_add_emojis: settings_emoji.can_add_emoji(),
realm_allow_community_topic_editing: page_params.realm_allow_community_topic_editing,
realm_message_content_edit_limit_minutes: settings_org.get_realm_time_limits_in_minutes( realm_message_content_edit_limit_minutes: settings_org.get_realm_time_limits_in_minutes(
"realm_message_content_edit_limit_seconds", "realm_message_content_edit_limit_seconds",
), ),

View File

@ -24,6 +24,7 @@ import * as overlays from "./overlays";
import {page_params} from "./page_params"; import {page_params} from "./page_params";
import * as resize from "./resize"; import * as resize from "./resize";
import * as rows from "./rows"; import * as rows from "./rows";
import * as settings_config from "./settings_config";
import * as settings_data from "./settings_data"; import * as settings_data from "./settings_data";
import * as stream_bar from "./stream_bar"; import * as stream_bar from "./stream_bar";
import * as stream_data from "./stream_data"; import * as stream_data from "./stream_data";
@ -68,7 +69,10 @@ export function is_topic_editable(message, edit_limit_seconds_buffer = 0) {
return true; return true;
} }
if (!page_params.realm_allow_community_topic_editing) { if (
page_params.realm_edit_topic_policy ===
settings_config.common_message_policy_values.by_admins_only.code
) {
// If you're another non-admin user, you need community topic editing enabled. // If you're another non-admin user, you need community topic editing enabled.
return false; return false;
} }

View File

@ -179,7 +179,7 @@ export function dispatch_normal_event(event) {
allow_edit_history: noop, allow_edit_history: noop,
allow_message_deleting: noop, allow_message_deleting: noop,
allow_message_editing: noop, allow_message_editing: noop,
allow_community_topic_editing: noop, edit_topic_policy: noop,
user_group_edit_policy: noop, user_group_edit_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,

View File

@ -198,6 +198,19 @@ export const wildcard_mention_policy_values = {
}, },
}; };
export const common_message_policy_values = {
by_everyone: {
order: 1,
code: 5,
description: $t({defaultMessage: "Admins, members and guests"}),
},
by_admins_only: {
order: 2,
code: 2,
description: $t({defaultMessage: "Admins only"}),
},
};
const time_limit_dropdown_values = new Map([ const time_limit_dropdown_values = new Map([
[ [
"any_time", "any_time",

View File

@ -104,6 +104,9 @@ export function get_organization_settings_options() {
options.wildcard_mention_policy_values = get_sorted_options_list( options.wildcard_mention_policy_values = get_sorted_options_list(
settings_config.wildcard_mention_policy_values, settings_config.wildcard_mention_policy_values,
); );
options.common_message_policy_values = get_sorted_options_list(
settings_config.common_message_policy_values,
);
return options; return options;
} }
@ -207,6 +210,7 @@ const simple_dropdown_properties = [
"realm_invite_to_realm_policy", "realm_invite_to_realm_policy",
"realm_wildcard_mention_policy", "realm_wildcard_mention_policy",
"realm_move_messages_between_streams_policy", "realm_move_messages_between_streams_policy",
"realm_edit_topic_policy",
]; ];
function set_property_dropdown_value(property_name) { function set_property_dropdown_value(property_name) {
@ -248,11 +252,7 @@ function set_msg_edit_limit_dropdown() {
"id_realm_message_content_edit_limit_minutes", "id_realm_message_content_edit_limit_minutes",
value === "custom_limit", value === "custom_limit",
); );
settings_ui.disable_sub_setting_onchange( settings_ui.disable_sub_setting_onchange(value !== "never", "id_realm_edit_topic_policy", true);
value !== "never",
"id_realm_allow_community_topic_editing",
true,
);
} }
function set_msg_delete_limit_dropdown() { function set_msg_delete_limit_dropdown() {

View File

@ -76,13 +76,7 @@ export function do_settings_change(
export function disable_sub_setting_onchange(is_checked, sub_setting_id, disable_on_uncheck) { export function disable_sub_setting_onchange(is_checked, sub_setting_id, disable_on_uncheck) {
if ((is_checked && disable_on_uncheck) || (!is_checked && !disable_on_uncheck)) { if ((is_checked && disable_on_uncheck) || (!is_checked && !disable_on_uncheck)) {
$(`#${CSS.escape(sub_setting_id)}`).prop("disabled", false); $(`#${CSS.escape(sub_setting_id)}`).prop("disabled", false);
$(`#${CSS.escape(sub_setting_id)}_label`)
.parent()
.removeClass("control-label-disabled");
} else if ((is_checked && !disable_on_uncheck) || (!is_checked && disable_on_uncheck)) { } else if ((is_checked && !disable_on_uncheck) || (!is_checked && disable_on_uncheck)) {
$(`#${CSS.escape(sub_setting_id)}`).prop("disabled", true); $(`#${CSS.escape(sub_setting_id)}`).prop("disabled", true);
$(`#${CSS.escape(sub_setting_id)}_label`)
.parent()
.addClass("control-label-disabled");
} }
} }

View File

@ -143,11 +143,12 @@
</div> </div>
</div> </div>
{{> settings_checkbox <div class="input-group">
setting_name="realm_allow_community_topic_editing" <label for="realm_edit_topic_policy" class="dropdown-title">{{t "Who can edit the topic of any message" }}</label>
prefix="id_" <select name="realm_edit_topic_policy" id="id_realm_edit_topic_policy" class="prop-element" data-setting-widget-type="number">
is_checked=realm_allow_community_topic_editing {{> dropdown_options_widget option_values=common_message_policy_values}}
label=admin_settings_label.realm_allow_community_topic_editing}} </select>
</div>
{{> settings_checkbox {{> settings_checkbox
setting_name="realm_allow_edit_history" setting_name="realm_allow_edit_history"

View File

@ -11,6 +11,11 @@ below features are supported.
## Changes in Zulip 5.0 ## Changes in Zulip 5.0
**Feature level 75**
* [`POST /register`](/api/register-queue), `PATCH /realm`: Replaced `allow_community_topic_editing`
field with an integer field `edit_topic_policy`.
**Feature level 74** **Feature level 74**
* [`POST /register`](/api/register-queue): Added `server_needs_upgrade` * [`POST /register`](/api/register-queue): Added `server_needs_upgrade`

View File

@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.4.3"
# Changes should be accompanied by documentation explaining what the # Changes should be accompanied by documentation explaining what the
# new level means in templates/zerver/api/changelog.md, as well as # new level means in templates/zerver/api/changelog.md, as well as
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`. # "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
API_FEATURE_LEVEL = 74 API_FEATURE_LEVEL = 75
# 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

View File

@ -874,25 +874,25 @@ def do_set_realm_message_editing(
realm: Realm, realm: Realm,
allow_message_editing: bool, allow_message_editing: bool,
message_content_edit_limit_seconds: int, message_content_edit_limit_seconds: int,
allow_community_topic_editing: bool, edit_topic_policy: int,
*, *,
acting_user: Optional[UserProfile], acting_user: Optional[UserProfile],
) -> None: ) -> None:
old_values = dict( old_values = dict(
allow_message_editing=realm.allow_message_editing, allow_message_editing=realm.allow_message_editing,
message_content_edit_limit_seconds=realm.message_content_edit_limit_seconds, message_content_edit_limit_seconds=realm.message_content_edit_limit_seconds,
allow_community_topic_editing=realm.allow_community_topic_editing, edit_topic_policy=realm.edit_topic_policy,
) )
realm.allow_message_editing = allow_message_editing realm.allow_message_editing = allow_message_editing
realm.message_content_edit_limit_seconds = message_content_edit_limit_seconds realm.message_content_edit_limit_seconds = message_content_edit_limit_seconds
realm.allow_community_topic_editing = allow_community_topic_editing realm.edit_topic_policy = edit_topic_policy
event_time = timezone_now() event_time = timezone_now()
updated_properties = dict( updated_properties = dict(
allow_message_editing=allow_message_editing, allow_message_editing=allow_message_editing,
message_content_edit_limit_seconds=message_content_edit_limit_seconds, message_content_edit_limit_seconds=message_content_edit_limit_seconds,
allow_community_topic_editing=allow_community_topic_editing, edit_topic_policy=edit_topic_policy,
) )
for updated_property, updated_value in updated_properties.items(): for updated_property, updated_value in updated_properties.items():
@ -2823,8 +2823,8 @@ def can_edit_content_or_topic(
if user_profile.is_realm_admin: if user_profile.is_realm_admin:
return True return True
# The community_topic_editing setting controls normal users editing topics. # The edit_topic_policy setting controls which users can edit topics.
if user_profile.realm.allow_community_topic_editing: if user_profile.realm.edit_topic_policy == Realm.POLICY_EVERYONE:
return True return True
return False return False

View File

@ -931,7 +931,7 @@ message_edit_data = DictType(
required_keys=[ required_keys=[
("allow_message_editing", bool), ("allow_message_editing", bool),
("message_content_edit_limit_seconds", int), ("message_content_edit_limit_seconds", int),
("allow_community_topic_editing", bool), ("edit_topic_policy", int),
] ]
) )

View File

@ -218,8 +218,8 @@ def fetch_initial_state_data(
state["realm_allow_message_editing"] = ( state["realm_allow_message_editing"] = (
False if user_profile is None else realm.allow_message_editing False if user_profile is None else realm.allow_message_editing
) )
state["realm_allow_community_topic_editing"] = ( state["realm_edit_topic_policy"] = (
False if user_profile is None else realm.allow_community_topic_editing Realm.POLICY_ADMINS_ONLY if user_profile is None else realm.edit_topic_policy
) )
state["realm_allow_message_deleting"] = ( state["realm_allow_message_deleting"] = (
False if user_profile is None else realm.allow_message_deleting False if user_profile is None else realm.allow_message_deleting

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.2 on 2021-05-26 09:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0326_alter_realm_authentication_methods"),
]
operations = [
migrations.AddField(
model_name="realm",
name="edit_topic_policy",
field=models.PositiveSmallIntegerField(default=5),
),
]

View File

@ -0,0 +1,46 @@
# Generated by Django 3.2.2 on 2021-05-26 09:43
from django.db import migrations
from django.db.backends.postgresql.schema import DatabaseSchemaEditor
from django.db.migrations.state import StateApps
def migrate_to_edit_topic_policy(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None:
Realm = apps.get_model("zerver", "Realm")
Realm.POLICY_EVERYONE = 5
Realm.POLICY_ADMINS_ONLY = 2
Realm.objects.filter(allow_community_topic_editing=False).update(
edit_topic_policy=Realm.POLICY_ADMINS_ONLY
)
Realm.objects.filter(allow_community_topic_editing=True).update(
edit_topic_policy=Realm.POLICY_EVERYONE
)
def reverse_migrate_to_edit_topic_policy(
apps: StateApps, schema_editor: DatabaseSchemaEditor
) -> None:
Realm = apps.get_model("zerver", "Realm")
Realm.POLICY_EVERYONE = 5
Realm.POLICY_ADMINS_ONLY = 2
Realm.objects.filter(edit_topic_policy=Realm.POLICY_ADMINS_ONLY).update(
allow_community_topic_editing=False
)
Realm.objects.filter(edit_topic_policy=Realm.POLICY_EVERYONE).update(
allow_community_topic_editing=True
)
class Migration(migrations.Migration):
dependencies = [
("zerver", "0327_realm_edit_topic_policy"),
]
operations = [
migrations.RunPython(
migrate_to_edit_topic_policy,
reverse_code=reverse_migrate_to_edit_topic_policy,
elidable=True,
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 3.2.2 on 2021-05-26 09:48
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("zerver", "0328_migrate_to_edit_topic_policy"),
]
operations = [
migrations.RemoveField(
model_name="realm",
name="allow_community_topic_editing",
),
]

View File

@ -254,6 +254,7 @@ class Realm(models.Model):
POLICY_ADMINS_ONLY = 2 POLICY_ADMINS_ONLY = 2
POLICY_FULL_MEMBERS_ONLY = 3 POLICY_FULL_MEMBERS_ONLY = 3
POLICY_MODERATORS_ONLY = 4 POLICY_MODERATORS_ONLY = 4
POLICY_EVERYONE = 5
COMMON_POLICY_TYPES = [ COMMON_POLICY_TYPES = [
POLICY_MEMBERS_ONLY, POLICY_MEMBERS_ONLY,
@ -262,9 +263,19 @@ class Realm(models.Model):
POLICY_MODERATORS_ONLY, POLICY_MODERATORS_ONLY,
] ]
COMMON_MESSAGE_POLICY_TYPES = [
POLICY_ADMINS_ONLY,
POLICY_EVERYONE,
]
DEFAULT_COMMUNITY_TOPIC_EDITING_LIMIT_SECONDS = 259200
# Who in the organization is allowed to create streams. # Who in the organization is allowed to create streams.
create_stream_policy: int = models.PositiveSmallIntegerField(default=POLICY_MEMBERS_ONLY) create_stream_policy: int = models.PositiveSmallIntegerField(default=POLICY_MEMBERS_ONLY)
# Who in the organization is allowed to edit topics of any message.
edit_topic_policy: int = models.PositiveSmallIntegerField(default=POLICY_EVERYONE)
# Who in the organization is allowed to invite other users to organization. # Who in the organization is allowed to invite other users to organization.
invite_to_realm_policy: int = models.PositiveSmallIntegerField(default=POLICY_MEMBERS_ONLY) invite_to_realm_policy: int = models.PositiveSmallIntegerField(default=POLICY_MEMBERS_ONLY)
@ -362,9 +373,6 @@ class Realm(models.Model):
# Whether users have access to message edit history # Whether users have access to message edit history
allow_edit_history: bool = models.BooleanField(default=True) allow_edit_history: bool = models.BooleanField(default=True)
DEFAULT_COMMUNITY_TOPIC_EDITING_LIMIT_SECONDS = 259200
allow_community_topic_editing: bool = models.BooleanField(default=True)
# Defaults for new users # Defaults for new users
default_twenty_four_hour_time: bool = models.BooleanField(default=False) default_twenty_four_hour_time: bool = models.BooleanField(default=False)
default_language: str = models.CharField(default="en", max_length=MAX_LANGUAGE_ID_LENGTH) default_language: str = models.CharField(default="en", max_length=MAX_LANGUAGE_ID_LENGTH)

View File

@ -3483,11 +3483,16 @@ paths:
description: | description: |
Whether this organizations [message edit policy](/help/configure-message-editing-and-deletion) Whether this organizations [message edit policy](/help/configure-message-editing-and-deletion)
allows editing the content of messages. allows editing the content of messages.
allow_community_topic_editing: edit_topic_policy:
type: boolean type: integer
description: | description: |
Whether [community topic editing](/help/community-topic-edits) is enabled The policy for which users can edit topics of any message.
in this organization.
* 2 = admins only
* 5 = everyone
**Changes**: New in Zulip 5.0 (feature level 75), replacing the
previous `allow_community_topic_editing` boolean.
message_content_edit_limit_seconds: message_content_edit_limit_seconds:
type: integer type: integer
description: | description: |
@ -3780,7 +3785,7 @@ paths:
{ {
"allow_message_editing": false, "allow_message_editing": false,
"message_content_edit_limit_seconds": 0, "message_content_edit_limit_seconds": 0,
"allow_community_topic_editing": false, "edit_topic_policy": 2,
}, },
"id": 0, "id": 0,
} }
@ -8733,13 +8738,18 @@ paths:
Whether this organizations [message edit policy](/help/configure-message-editing-and-deletion) Whether this organizations [message edit policy](/help/configure-message-editing-and-deletion)
allows editing the content of messages. allows editing the content of messages.
realm_allow_community_topic_editing: realm_edit_topic_policy:
type: boolean type: integer
description: | description: |
Present if `realm` is present in `fetch_event_types`. Present if `realm` is present in `fetch_event_types`.
Whether [community topic editing](/help/community-topic-edits) is enabled The policy for which users can edit topics of any message.
in this organization.
* 2 = admins only
* 5 = everyone
**Changes**: New in Zulip 5.0 (feature level 75), replacing the
previous `allow_community_topic_editing` boolean.
realm_message_content_edit_limit_seconds: realm_message_content_edit_limit_seconds:
type: integer type: integer
description: | description: |

View File

@ -41,6 +41,7 @@ from zerver.lib.streams import create_stream_if_needed
from zerver.lib.test_classes import ZulipTestCase from zerver.lib.test_classes import ZulipTestCase
from zerver.models import ( from zerver.models import (
Message, Message,
Realm,
RealmAuditLog, RealmAuditLog,
Recipient, Recipient,
Subscription, Subscription,
@ -412,13 +413,13 @@ class TestRealmAuditLog(ZulipTestCase):
RealmAuditLog.NEW_VALUE: 1000, RealmAuditLog.NEW_VALUE: 1000,
}, },
{ {
"property": "allow_community_topic_editing", "property": "edit_topic_policy",
RealmAuditLog.OLD_VALUE: True, RealmAuditLog.OLD_VALUE: Realm.POLICY_EVERYONE,
RealmAuditLog.NEW_VALUE: False, RealmAuditLog.NEW_VALUE: Realm.POLICY_ADMINS_ONLY,
}, },
] ]
do_set_realm_message_editing(realm, True, 1000, False, acting_user=user) do_set_realm_message_editing(realm, True, 1000, Realm.POLICY_ADMINS_ONLY, acting_user=user)
realm_audit_logs = RealmAuditLog.objects.filter( realm_audit_logs = RealmAuditLog.objects.filter(
realm=realm, realm=realm,
event_type=RealmAuditLog.REALM_PROPERTY_CHANGED, event_type=RealmAuditLog.REALM_PROPERTY_CHANGED,

View File

@ -1241,7 +1241,7 @@ class NormalActionsTest(BaseAction):
self.user_profile.realm, self.user_profile.realm,
allow_message_editing, allow_message_editing,
message_content_edit_limit_seconds, message_content_edit_limit_seconds,
False, Realm.POLICY_ADMINS_ONLY,
acting_user=None, acting_user=None,
) )
) )

View File

@ -138,7 +138,6 @@ class HomeTest(ZulipTestCase):
"prompt_for_invites", "prompt_for_invites",
"queue_id", "queue_id",
"realm_add_emoji_by_admins_only", "realm_add_emoji_by_admins_only",
"realm_allow_community_topic_editing",
"realm_allow_edit_history", "realm_allow_edit_history",
"realm_allow_message_deleting", "realm_allow_message_deleting",
"realm_allow_message_editing", "realm_allow_message_editing",
@ -161,6 +160,7 @@ class HomeTest(ZulipTestCase):
"realm_digest_weekday", "realm_digest_weekday",
"realm_disallow_disposable_email_addresses", "realm_disallow_disposable_email_addresses",
"realm_domains", "realm_domains",
"realm_edit_topic_policy",
"realm_email_address_visibility", "realm_email_address_visibility",
"realm_email_auth_enabled", "realm_email_auth_enabled",
"realm_email_changes_disabled", "realm_email_changes_disabled",

View File

@ -722,16 +722,14 @@ class EditMessageTest(EditMessageTestCase):
def set_message_editing_params( def set_message_editing_params(
allow_message_editing: bool, allow_message_editing: bool,
message_content_edit_limit_seconds: int, message_content_edit_limit_seconds: int,
allow_community_topic_editing: bool, edit_topic_policy: int,
) -> None: ) -> None:
result = self.client_patch( result = self.client_patch(
"/json/realm", "/json/realm",
{ {
"allow_message_editing": orjson.dumps(allow_message_editing).decode(), "allow_message_editing": orjson.dumps(allow_message_editing).decode(),
"message_content_edit_limit_seconds": message_content_edit_limit_seconds, "message_content_edit_limit_seconds": message_content_edit_limit_seconds,
"allow_community_topic_editing": orjson.dumps( "edit_topic_policy": edit_topic_policy,
allow_community_topic_editing
).decode(),
}, },
) )
self.assert_json_success(result) self.assert_json_success(result)
@ -781,46 +779,44 @@ class EditMessageTest(EditMessageTestCase):
# 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, False) set_message_editing_params(True, 240, Realm.POLICY_ADMINS_ONLY)
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, False) set_message_editing_params(True, 120, Realm.POLICY_ADMINS_ONLY)
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, 0, False) set_message_editing_params(True, 0, Realm.POLICY_ADMINS_ONLY)
do_edit_message_assert_success(id_, "D") do_edit_message_assert_success(id_, "D")
# without allow_message_editing, nothing is allowed # without allow_message_editing, nothing is allowed
set_message_editing_params(False, 240, False) set_message_editing_params(False, 240, Realm.POLICY_ADMINS_ONLY)
do_edit_message_assert_error( do_edit_message_assert_error(
id_, "E", "Your organization has turned off message editing", True id_, "E", "Your organization has turned off message editing", True
) )
set_message_editing_params(False, 120, False) set_message_editing_params(False, 120, Realm.POLICY_ADMINS_ONLY)
do_edit_message_assert_error( do_edit_message_assert_error(
id_, "F", "Your organization has turned off message editing", True id_, "F", "Your organization has turned off message editing", True
) )
set_message_editing_params(False, 0, False) set_message_editing_params(False, 0, Realm.POLICY_ADMINS_ONLY)
do_edit_message_assert_error( do_edit_message_assert_error(
id_, "G", "Your organization has turned off message editing", True id_, "G", "Your organization has turned off message editing", True
) )
def test_allow_community_topic_editing(self) -> None: def test_edit_topic_policy(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, message_content_edit_limit_seconds: int,
allow_community_topic_editing: bool, edit_topic_policy: int,
) -> None: ) -> None:
result = self.client_patch( result = self.client_patch(
"/json/realm", "/json/realm",
{ {
"allow_message_editing": orjson.dumps(allow_message_editing).decode(), "allow_message_editing": orjson.dumps(allow_message_editing).decode(),
"message_content_edit_limit_seconds": message_content_edit_limit_seconds, "message_content_edit_limit_seconds": message_content_edit_limit_seconds,
"allow_community_topic_editing": orjson.dumps( "edit_topic_policy": edit_topic_policy,
allow_community_topic_editing
).decode(),
}, },
) )
self.assert_json_success(result) self.assert_json_success(result)
@ -855,21 +851,21 @@ class EditMessageTest(EditMessageTestCase):
message.save() message.save()
# any user can edit the topic of a message # any user can edit the topic of a message
set_message_editing_params(True, 0, True) set_message_editing_params(True, 0, Realm.POLICY_EVERYONE)
# log in as a new user # log in as a new user
self.login("cordelia") self.login("cordelia")
do_edit_message_assert_success(id_, "A") do_edit_message_assert_success(id_, "A")
# only admins can edit the topics of messages # only admins can edit the topics of messages
self.login("iago") self.login("iago")
set_message_editing_params(True, 0, False) set_message_editing_params(True, 0, Realm.POLICY_ADMINS_ONLY)
do_edit_message_assert_success(id_, "B") do_edit_message_assert_success(id_, "B")
self.login("cordelia") self.login("cordelia")
do_edit_message_assert_error(id_, "C", "You don't have permission to edit this message") do_edit_message_assert_error(id_, "C", "You don't have permission to edit this message")
# users cannot edit topics if allow_message_editing is False # users cannot edit topics if allow_message_editing is False
self.login("iago") self.login("iago")
set_message_editing_params(False, 0, True) set_message_editing_params(False, 0, Realm.POLICY_EVERYONE)
self.login("cordelia") self.login("cordelia")
do_edit_message_assert_error(id_, "D", "Your organization has turned off message editing") do_edit_message_assert_error(id_, "D", "Your organization has turned off message editing")
@ -877,7 +873,7 @@ class EditMessageTest(EditMessageTestCase):
message.date_sent = message.date_sent - datetime.timedelta(seconds=290000) message.date_sent = message.date_sent - datetime.timedelta(seconds=290000)
message.save() message.save()
self.login("iago") self.login("iago")
set_message_editing_params(True, 0, True) set_message_editing_params(True, 0, Realm.POLICY_EVERYONE)
do_edit_message_assert_success(id_, "E") do_edit_message_assert_success(id_, "E")
self.login("cordelia") self.login("cordelia")
do_edit_message_assert_error( do_edit_message_assert_error(
@ -1537,7 +1533,7 @@ class EditMessageTest(EditMessageTestCase):
) )
realm = user_profile.realm realm = user_profile.realm
realm.allow_community_topic_editing = False realm.edit_topic_policy = Realm.POLICY_ADMINS_ONLY
realm.save() realm.save()
self.login("cordelia") self.login("cordelia")

View File

@ -910,25 +910,31 @@ class RealmAPITest(ZulipTestCase):
"""Tests updating the realm property 'allow_message_editing'.""" """Tests updating the realm property 'allow_message_editing'."""
self.set_up_db("allow_message_editing", False) self.set_up_db("allow_message_editing", False)
self.set_up_db("message_content_edit_limit_seconds", 0) self.set_up_db("message_content_edit_limit_seconds", 0)
self.set_up_db("allow_community_topic_editing", False) self.set_up_db("edit_topic_policy", Realm.POLICY_ADMINS_ONLY)
realm = self.update_with_api("allow_message_editing", True) realm = self.update_with_api("allow_message_editing", True)
realm = self.update_with_api("message_content_edit_limit_seconds", 100) realm = self.update_with_api("message_content_edit_limit_seconds", 100)
realm = self.update_with_api("allow_community_topic_editing", True) realm = self.update_with_api("edit_topic_policy", Realm.POLICY_EVERYONE)
self.assertEqual(realm.allow_message_editing, True) self.assertEqual(realm.allow_message_editing, True)
self.assertEqual(realm.message_content_edit_limit_seconds, 100) self.assertEqual(realm.message_content_edit_limit_seconds, 100)
self.assertEqual(realm.allow_community_topic_editing, True) self.assertEqual(realm.edit_topic_policy, Realm.POLICY_EVERYONE)
realm = self.update_with_api("allow_message_editing", False) realm = self.update_with_api("allow_message_editing", False)
self.assertEqual(realm.allow_message_editing, False) self.assertEqual(realm.allow_message_editing, False)
self.assertEqual(realm.message_content_edit_limit_seconds, 100) self.assertEqual(realm.message_content_edit_limit_seconds, 100)
self.assertEqual(realm.allow_community_topic_editing, True) self.assertEqual(realm.edit_topic_policy, Realm.POLICY_EVERYONE)
realm = self.update_with_api("message_content_edit_limit_seconds", 200) realm = self.update_with_api("message_content_edit_limit_seconds", 200)
self.assertEqual(realm.allow_message_editing, False) self.assertEqual(realm.allow_message_editing, False)
self.assertEqual(realm.message_content_edit_limit_seconds, 200) self.assertEqual(realm.message_content_edit_limit_seconds, 200)
self.assertEqual(realm.allow_community_topic_editing, True) self.assertEqual(realm.edit_topic_policy, Realm.POLICY_EVERYONE)
realm = self.update_with_api("allow_community_topic_editing", False) realm = self.update_with_api("edit_topic_policy", Realm.POLICY_ADMINS_ONLY)
self.assertEqual(realm.allow_message_editing, False) self.assertEqual(realm.allow_message_editing, False)
self.assertEqual(realm.message_content_edit_limit_seconds, 200) self.assertEqual(realm.message_content_edit_limit_seconds, 200)
self.assertEqual(realm.allow_community_topic_editing, False) self.assertEqual(realm.edit_topic_policy, Realm.POLICY_ADMINS_ONLY)
# Test an invalid value for edit_topic_policy
invalid_edit_topic_policy_value = 10
req = {"edit_topic_policy": orjson.dumps(invalid_edit_topic_policy_value).decode()}
result = self.client_patch("/json/realm", req)
self.assert_json_error(result, "Invalid edit_topic_policy")
def test_update_realm_allow_message_deleting(self) -> None: def test_update_realm_allow_message_deleting(self) -> None:
"""Tests updating the realm property 'allow_message_deleting'.""" """Tests updating the realm property 'allow_message_deleting'."""

View File

@ -66,7 +66,9 @@ def update_realm(
converter=to_non_negative_int, default=None converter=to_non_negative_int, default=None
), ),
allow_message_editing: Optional[bool] = REQ(json_validator=check_bool, default=None), allow_message_editing: Optional[bool] = REQ(json_validator=check_bool, default=None),
allow_community_topic_editing: Optional[bool] = REQ(json_validator=check_bool, default=None), edit_topic_policy: Optional[int] = REQ(
json_validator=check_int_in(Realm.COMMON_MESSAGE_POLICY_TYPES), default=None
),
mandatory_topics: Optional[bool] = REQ(json_validator=check_bool, default=None), mandatory_topics: Optional[bool] = REQ(json_validator=check_bool, default=None),
message_content_edit_limit_seconds: Optional[int] = REQ( message_content_edit_limit_seconds: Optional[int] = REQ(
converter=to_non_negative_int, default=None converter=to_non_negative_int, default=None
@ -181,27 +183,24 @@ def update_realm(
message_content_edit_limit_seconds is not None message_content_edit_limit_seconds is not None
and realm.message_content_edit_limit_seconds != message_content_edit_limit_seconds and realm.message_content_edit_limit_seconds != message_content_edit_limit_seconds
) )
or ( or (edit_topic_policy is not None and realm.edit_topic_policy != edit_topic_policy)
allow_community_topic_editing is not None
and realm.allow_community_topic_editing != allow_community_topic_editing
)
): ):
if allow_message_editing is None: if allow_message_editing is None:
allow_message_editing = realm.allow_message_editing allow_message_editing = realm.allow_message_editing
if message_content_edit_limit_seconds is None: if message_content_edit_limit_seconds is None:
message_content_edit_limit_seconds = realm.message_content_edit_limit_seconds message_content_edit_limit_seconds = realm.message_content_edit_limit_seconds
if allow_community_topic_editing is None: if edit_topic_policy is None:
allow_community_topic_editing = realm.allow_community_topic_editing edit_topic_policy = realm.edit_topic_policy
do_set_realm_message_editing( do_set_realm_message_editing(
realm, realm,
allow_message_editing, allow_message_editing,
message_content_edit_limit_seconds, message_content_edit_limit_seconds,
allow_community_topic_editing, edit_topic_policy,
acting_user=user_profile, acting_user=user_profile,
) )
data["allow_message_editing"] = allow_message_editing data["allow_message_editing"] = allow_message_editing
data["message_content_edit_limit_seconds"] = message_content_edit_limit_seconds data["message_content_edit_limit_seconds"] = message_content_edit_limit_seconds
data["allow_community_topic_editing"] = allow_community_topic_editing data["edit_topic_policy"] = edit_topic_policy
# Realm.notifications_stream and Realm.signup_notifications_stream are not boolean, # Realm.notifications_stream and Realm.signup_notifications_stream are not boolean,
# str or integer field, and thus doesn't fit into the do_set_realm_property framework. # str or integer field, and thus doesn't fit into the do_set_realm_property framework.