mirror of https://github.com/zulip/zulip.git
message: Make zero invalid value for message_content_delete_limit_seconds.
We make zero invalid value for message_content_delete_limit_seconds and for handling the case of "Allow to delete message any time", the API-level value of message_content_delete_limit_seconds is "anytime" and "None" as the DB-level value. We also use these values for message retention setting, so it helps maintain consistency.
This commit is contained in:
parent
4368b9d186
commit
b13bfa09c5
|
@ -125,7 +125,7 @@ run_test("get_editability", ({override}) => {
|
||||||
run_test("get_deletability", () => {
|
run_test("get_deletability", () => {
|
||||||
page_params.is_admin = true;
|
page_params.is_admin = true;
|
||||||
page_params.realm_allow_message_deleting = false;
|
page_params.realm_allow_message_deleting = false;
|
||||||
page_params.realm_message_content_delete_limit_seconds = 0;
|
page_params.realm_message_content_delete_limit_seconds = null;
|
||||||
const message = {
|
const message = {
|
||||||
sent_by_me: false,
|
sent_by_me: false,
|
||||||
locally_echoed: true,
|
locally_echoed: true,
|
||||||
|
|
|
@ -171,7 +171,7 @@ export function get_deletability(message) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_params.realm_message_content_delete_limit_seconds === 0) {
|
if (page_params.realm_message_content_delete_limit_seconds === null) {
|
||||||
// This means no time limit for message deletion.
|
// This means no time limit for message deletion.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,6 +162,9 @@ function get_property_value(property_name) {
|
||||||
if (!page_params.realm_allow_message_deleting) {
|
if (!page_params.realm_allow_message_deleting) {
|
||||||
return "never";
|
return "never";
|
||||||
}
|
}
|
||||||
|
if (page_params.realm_message_content_delete_limit_seconds === null) {
|
||||||
|
return "any_time";
|
||||||
|
}
|
||||||
for (const [value, elem] of settings_config.msg_delete_limit_dropdown_values) {
|
for (const [value, elem] of settings_config.msg_delete_limit_dropdown_values) {
|
||||||
if (elem.seconds === page_params.realm_message_content_delete_limit_seconds) {
|
if (elem.seconds === page_params.realm_message_content_delete_limit_seconds) {
|
||||||
return value;
|
return value;
|
||||||
|
@ -776,14 +779,17 @@ export function build_page() {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "any_time": {
|
||||||
|
data.allow_message_deleting = true;
|
||||||
|
data.message_content_delete_limit_seconds = JSON.stringify("unlimited");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "custom_limit": {
|
case "custom_limit": {
|
||||||
data.message_content_delete_limit_seconds = parse_time_limit(
|
data.message_content_delete_limit_seconds = parse_time_limit(
|
||||||
$("#id_realm_message_content_delete_limit_minutes"),
|
$("#id_realm_message_content_delete_limit_minutes"),
|
||||||
);
|
);
|
||||||
// Disable deleting if the parsed time limit is 0 seconds
|
data.allow_message_deleting = true;
|
||||||
data.allow_message_deleting = Boolean(
|
|
||||||
data.message_content_delete_limit_seconds,
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,15 @@ below features are supported.
|
||||||
|
|
||||||
## Changes in Zulip 5.0
|
## Changes in Zulip 5.0
|
||||||
|
|
||||||
|
**Feature level 100**
|
||||||
|
|
||||||
|
* [`POST /register`](/api/register-queue), [`GET
|
||||||
|
/events`](/api/get-events): `message_content_delete_limit_seconds`
|
||||||
|
now represents no limit using `null`, instead of the integer 0.
|
||||||
|
* `PATCH /realm`: One now sets `message_content_delete_limit_seconds`
|
||||||
|
to no limit by passing the string `unlimited`, rather than the
|
||||||
|
integer 0.
|
||||||
|
|
||||||
**Feature level 99**
|
**Feature level 99**
|
||||||
|
|
||||||
* [`PATCH /realm/user_settings_defaults`](/api/update-realm-user-settings-defaults),
|
* [`PATCH /realm/user_settings_defaults`](/api/update-realm-user-settings-defaults),
|
||||||
|
|
|
@ -15,6 +15,10 @@ def check_pyflakes(files: List[str], options: argparse.Namespace) -> bool:
|
||||||
"zerver/views/realm.py",
|
"zerver/views/realm.py",
|
||||||
"local variable 'message_retention_days' is assigned to but never used",
|
"local variable 'message_retention_days' is assigned to but never used",
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"zerver/views/realm.py",
|
||||||
|
"local variable 'message_content_delete_limit_seconds' is assigned to but never used",
|
||||||
|
),
|
||||||
("settings.py", "settings import *' used; unable to detect undefined names"),
|
("settings.py", "settings import *' used; unable to detect undefined names"),
|
||||||
(
|
(
|
||||||
"settings.py",
|
"settings.py",
|
||||||
|
|
|
@ -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 = 99
|
API_FEATURE_LEVEL = 100
|
||||||
|
|
||||||
# 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
|
||||||
|
|
|
@ -2,7 +2,7 @@ import copy
|
||||||
import datetime
|
import datetime
|
||||||
import zlib
|
import zlib
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple
|
from typing import Any, Dict, List, Mapping, Optional, Sequence, Set, Tuple, Union
|
||||||
|
|
||||||
import ahocorasick
|
import ahocorasick
|
||||||
import orjson
|
import orjson
|
||||||
|
@ -28,6 +28,7 @@ from zerver.lib.exceptions import JsonableError, MissingAuthenticationError
|
||||||
from zerver.lib.markdown import MessageRenderingResult, markdown_convert, topic_links
|
from zerver.lib.markdown import MessageRenderingResult, markdown_convert, topic_links
|
||||||
from zerver.lib.markdown import version as markdown_version
|
from zerver.lib.markdown import version as markdown_version
|
||||||
from zerver.lib.mention import MentionData
|
from zerver.lib.mention import MentionData
|
||||||
|
from zerver.lib.request import RequestVariableConversionError
|
||||||
from zerver.lib.stream_subscription import (
|
from zerver.lib.stream_subscription import (
|
||||||
get_stream_subscriptions_for_user,
|
get_stream_subscriptions_for_user,
|
||||||
get_subscribed_stream_recipient_ids_for_user,
|
get_subscribed_stream_recipient_ids_for_user,
|
||||||
|
@ -1470,3 +1471,15 @@ def wildcard_mention_allowed(sender: UserProfile, stream: Stream) -> bool:
|
||||||
return not sender.is_guest
|
return not sender.is_guest
|
||||||
|
|
||||||
raise AssertionError("Invalid wildcard mention policy")
|
raise AssertionError("Invalid wildcard mention policy")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_message_content_delete_limit(
|
||||||
|
value: Union[int, str],
|
||||||
|
special_values_map: Mapping[str, Optional[int]],
|
||||||
|
) -> Optional[int]:
|
||||||
|
if isinstance(value, str) and value in special_values_map.keys():
|
||||||
|
return special_values_map[value]
|
||||||
|
if isinstance(value, str) or value <= 0:
|
||||||
|
raise RequestVariableConversionError("message_content_delete_limit_seconds", value)
|
||||||
|
assert isinstance(value, int)
|
||||||
|
return value
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
# Generated by Django 3.2.4 on 2021-06-14 12:12
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
from django.db.backends.postgresql.schema import DatabaseSchemaEditor
|
||||||
|
from django.db.migrations.state import StateApps
|
||||||
|
|
||||||
|
|
||||||
|
def make_zero_invalid_for_message_delete_limit(
|
||||||
|
apps: StateApps, schema_editor: DatabaseSchemaEditor
|
||||||
|
) -> None:
|
||||||
|
Realm = apps.get_model("zerver", "Realm")
|
||||||
|
Realm.DEFAULT_MESSAGE_CONTENT_DELETE_LIMIT_SECONDS = 600
|
||||||
|
|
||||||
|
Realm.objects.filter(
|
||||||
|
allow_message_deleting=True, message_content_delete_limit_seconds=0
|
||||||
|
).update(message_content_delete_limit_seconds=None)
|
||||||
|
|
||||||
|
Realm.objects.filter(
|
||||||
|
allow_message_deleting=False, message_content_delete_limit_seconds=0
|
||||||
|
).update(
|
||||||
|
message_content_delete_limit_seconds=Realm.DEFAULT_MESSAGE_CONTENT_DELETE_LIMIT_SECONDS
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def reverse_make_zero_invalid_for_message_delete_limit(
|
||||||
|
apps: StateApps, schema_editor: DatabaseSchemaEditor
|
||||||
|
) -> None:
|
||||||
|
Realm = apps.get_model("zerver", "Realm")
|
||||||
|
Realm.DEFAULT_MESSAGE_CONTENT_DELETE_LIMIT_SECONDS = 600
|
||||||
|
|
||||||
|
Realm.objects.filter(
|
||||||
|
allow_message_deleting=True, message_content_delete_limit_seconds=None
|
||||||
|
).update(message_content_delete_limit_seconds=0)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("zerver", "0353_remove_realm_default_twenty_four_hour_time"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="realm",
|
||||||
|
name="message_content_delete_limit_seconds",
|
||||||
|
field=models.IntegerField(default=600, null=True),
|
||||||
|
),
|
||||||
|
migrations.RunPython(
|
||||||
|
make_zero_invalid_for_message_delete_limit,
|
||||||
|
reverse_code=reverse_make_zero_invalid_for_message_delete_limit,
|
||||||
|
elidable=True,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="realm",
|
||||||
|
name="message_content_delete_limit_seconds",
|
||||||
|
field=models.PositiveIntegerField(default=600, null=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -371,8 +371,11 @@ class Realm(models.Model):
|
||||||
DEFAULT_MESSAGE_CONTENT_DELETE_LIMIT_SECONDS = (
|
DEFAULT_MESSAGE_CONTENT_DELETE_LIMIT_SECONDS = (
|
||||||
600 # if changed, also change in admin.js, setting_org.js
|
600 # if changed, also change in admin.js, setting_org.js
|
||||||
)
|
)
|
||||||
message_content_delete_limit_seconds: int = models.IntegerField(
|
MESSAGE_CONTENT_DELETE_LIMIT_SPECIAL_VALUES_MAP = {
|
||||||
default=DEFAULT_MESSAGE_CONTENT_DELETE_LIMIT_SECONDS,
|
"unlimited": None,
|
||||||
|
}
|
||||||
|
message_content_delete_limit_seconds: int = models.PositiveIntegerField(
|
||||||
|
default=DEFAULT_MESSAGE_CONTENT_DELETE_LIMIT_SECONDS, null=True
|
||||||
)
|
)
|
||||||
|
|
||||||
allow_message_editing: bool = models.BooleanField(default=True)
|
allow_message_editing: bool = models.BooleanField(default=True)
|
||||||
|
@ -629,7 +632,7 @@ class Realm(models.Model):
|
||||||
private_message_policy=int,
|
private_message_policy=int,
|
||||||
user_group_edit_policy=int,
|
user_group_edit_policy=int,
|
||||||
default_code_block_language=(str, type(None)),
|
default_code_block_language=(str, type(None)),
|
||||||
message_content_delete_limit_seconds=int,
|
message_content_delete_limit_seconds=(int, type(None)),
|
||||||
wildcard_mention_policy=int,
|
wildcard_mention_policy=int,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -3556,10 +3556,17 @@ paths:
|
||||||
in this organization. Null if no default has been set.
|
in this organization. Null if no default has been set.
|
||||||
message_content_delete_limit_seconds:
|
message_content_delete_limit_seconds:
|
||||||
type: integer
|
type: integer
|
||||||
|
nullable: true
|
||||||
description: |
|
description: |
|
||||||
Messages sent more than this many seconds ago cannot be deleted
|
Messages sent more than this many seconds ago cannot be deleted
|
||||||
with this organization's
|
with this organization's
|
||||||
[message deletion policy](/help/configure-message-editing-and-deletion).
|
[message deletion policy](/help/configure-message-editing-and-deletion).
|
||||||
|
|
||||||
|
A 'null' value means no limit: messages can be deleted
|
||||||
|
regardless of how long ago they were sent.
|
||||||
|
|
||||||
|
**Changes**: No limit was represented using the
|
||||||
|
special value `0` before Zulip 5.0 (feature level 100).
|
||||||
authentication_methods:
|
authentication_methods:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
|
@ -10599,12 +10606,19 @@ paths:
|
||||||
in this organization. Null if no default has been set.
|
in this organization. Null if no default has been set.
|
||||||
realm_message_content_delete_limit_seconds:
|
realm_message_content_delete_limit_seconds:
|
||||||
type: integer
|
type: integer
|
||||||
|
nullable: true
|
||||||
description: |
|
description: |
|
||||||
Present if `realm` is present in `fetch_event_types`.
|
Present if `realm` is present in `fetch_event_types`.
|
||||||
|
|
||||||
Messages sent more than this many seconds ago cannot be deleted
|
Messages sent more than this many seconds ago cannot be deleted
|
||||||
with this organization's
|
with this organization's
|
||||||
[message deletion policy](/help/configure-message-editing-and-deletion).
|
[message deletion policy](/help/configure-message-editing-and-deletion).
|
||||||
|
|
||||||
|
A 'null' value means no limit: messages can be deleted
|
||||||
|
regardless of how long ago they were sent.
|
||||||
|
|
||||||
|
**Changes**: No limit was represented using the
|
||||||
|
special value `0` before Zulip 5.0 (feature level 100).
|
||||||
realm_authentication_methods:
|
realm_authentication_methods:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import datetime
|
import datetime
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import orjson
|
import orjson
|
||||||
|
@ -2142,14 +2142,16 @@ class DeleteMessageTest(ZulipTestCase):
|
||||||
|
|
||||||
def test_delete_message_by_user(self) -> None:
|
def test_delete_message_by_user(self) -> None:
|
||||||
def set_message_deleting_params(
|
def set_message_deleting_params(
|
||||||
allow_message_deleting: bool, message_content_delete_limit_seconds: int
|
allow_message_deleting: bool, message_content_delete_limit_seconds: Union[int, str]
|
||||||
) -> None:
|
) -> None:
|
||||||
self.login("iago")
|
self.login("iago")
|
||||||
result = self.client_patch(
|
result = self.client_patch(
|
||||||
"/json/realm",
|
"/json/realm",
|
||||||
{
|
{
|
||||||
"allow_message_deleting": orjson.dumps(allow_message_deleting).decode(),
|
"allow_message_deleting": orjson.dumps(allow_message_deleting).decode(),
|
||||||
"message_content_delete_limit_seconds": message_content_delete_limit_seconds,
|
"message_content_delete_limit_seconds": orjson.dumps(
|
||||||
|
message_content_delete_limit_seconds
|
||||||
|
).decode(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
|
@ -2170,7 +2172,7 @@ class DeleteMessageTest(ZulipTestCase):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Test if message deleting is not allowed(default).
|
# Test if message deleting is not allowed(default).
|
||||||
set_message_deleting_params(False, 0)
|
set_message_deleting_params(False, "unlimited")
|
||||||
hamlet = self.example_user("hamlet")
|
hamlet = self.example_user("hamlet")
|
||||||
self.login_user(hamlet)
|
self.login_user(hamlet)
|
||||||
msg_id = self.send_stream_message(hamlet, "Scotland")
|
msg_id = self.send_stream_message(hamlet, "Scotland")
|
||||||
|
@ -2185,8 +2187,8 @@ class DeleteMessageTest(ZulipTestCase):
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
|
|
||||||
# Test if message deleting is allowed.
|
# Test if message deleting is allowed.
|
||||||
# Test if time limit is zero(no limit).
|
# Test if time limit is None(no limit).
|
||||||
set_message_deleting_params(True, 0)
|
set_message_deleting_params(True, "unlimited")
|
||||||
msg_id = self.send_stream_message(hamlet, "Scotland")
|
msg_id = self.send_stream_message(hamlet, "Scotland")
|
||||||
message = Message.objects.get(id=msg_id)
|
message = Message.objects.get(id=msg_id)
|
||||||
message.date_sent = message.date_sent - datetime.timedelta(seconds=600)
|
message.date_sent = message.date_sent - datetime.timedelta(seconds=600)
|
||||||
|
|
|
@ -1005,18 +1005,34 @@ class RealmAPITest(ZulipTestCase):
|
||||||
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'."""
|
||||||
self.set_up_db("allow_message_deleting", True)
|
self.set_up_db("allow_message_deleting", True)
|
||||||
self.set_up_db("message_content_delete_limit_seconds", 0)
|
|
||||||
realm = self.update_with_api("allow_message_deleting", False)
|
realm = self.update_with_api("allow_message_deleting", False)
|
||||||
self.assertEqual(realm.allow_message_deleting, False)
|
self.assertEqual(realm.allow_message_deleting, False)
|
||||||
self.assertEqual(realm.message_content_delete_limit_seconds, 0)
|
self.assertEqual(realm.message_content_delete_limit_seconds, 600)
|
||||||
realm = self.update_with_api("allow_message_deleting", True)
|
realm = self.update_with_api("allow_message_deleting", True)
|
||||||
realm = self.update_with_api("message_content_delete_limit_seconds", 100)
|
realm = self.update_with_api("message_content_delete_limit_seconds", 100)
|
||||||
self.assertEqual(realm.allow_message_deleting, True)
|
self.assertEqual(realm.allow_message_deleting, True)
|
||||||
self.assertEqual(realm.message_content_delete_limit_seconds, 100)
|
self.assertEqual(realm.message_content_delete_limit_seconds, 100)
|
||||||
|
realm = self.update_with_api(
|
||||||
|
"message_content_delete_limit_seconds", orjson.dumps("unlimited").decode()
|
||||||
|
)
|
||||||
|
self.assertEqual(realm.allow_message_deleting, True)
|
||||||
|
self.assertEqual(realm.message_content_delete_limit_seconds, None)
|
||||||
realm = self.update_with_api("message_content_delete_limit_seconds", 600)
|
realm = self.update_with_api("message_content_delete_limit_seconds", 600)
|
||||||
self.assertEqual(realm.allow_message_deleting, True)
|
self.assertEqual(realm.allow_message_deleting, True)
|
||||||
self.assertEqual(realm.message_content_delete_limit_seconds, 600)
|
self.assertEqual(realm.message_content_delete_limit_seconds, 600)
|
||||||
|
|
||||||
|
# Test that 0 is invalid value.
|
||||||
|
req = dict(message_content_delete_limit_seconds=orjson.dumps(0).decode())
|
||||||
|
result = self.client_patch("/json/realm", req)
|
||||||
|
self.assert_json_error(result, "Bad value for 'message_content_delete_limit_seconds': 0")
|
||||||
|
|
||||||
|
# Test that only "unlimited" string is valid and others are invalid.
|
||||||
|
req = dict(message_content_delete_limit_seconds=orjson.dumps("invalid").decode())
|
||||||
|
result = self.client_patch("/json/realm", req)
|
||||||
|
self.assert_json_error(
|
||||||
|
result, "Bad value for 'message_content_delete_limit_seconds': invalid"
|
||||||
|
)
|
||||||
|
|
||||||
def test_change_invite_to_realm_policy_by_owners_only(self) -> None:
|
def test_change_invite_to_realm_policy_by_owners_only(self) -> None:
|
||||||
self.login("iago")
|
self.login("iago")
|
||||||
req = {"invite_to_realm_policy": Realm.POLICY_ADMINS_ONLY}
|
req = {"invite_to_realm_policy": Realm.POLICY_ADMINS_ONLY}
|
||||||
|
|
|
@ -137,9 +137,9 @@ def validate_can_delete_message(user_profile: UserProfile, message: Message) ->
|
||||||
# User can not delete message, if message deleting is not allowed in realm.
|
# User can not delete message, if message deleting is not allowed in realm.
|
||||||
raise JsonableError(_("You don't have permission to delete this message"))
|
raise JsonableError(_("You don't have permission to delete this message"))
|
||||||
|
|
||||||
deadline_seconds = user_profile.realm.message_content_delete_limit_seconds
|
deadline_seconds: Optional[int] = user_profile.realm.message_content_delete_limit_seconds
|
||||||
if deadline_seconds == 0:
|
if deadline_seconds is None:
|
||||||
# 0 for no time limit to delete message
|
# None means no time limit to delete message
|
||||||
return
|
return
|
||||||
if (timezone_now() - message.date_sent) > datetime.timedelta(seconds=deadline_seconds):
|
if (timezone_now() - message.date_sent) > datetime.timedelta(seconds=deadline_seconds):
|
||||||
# User can not delete message after deadline time of realm
|
# User can not delete message after deadline time of realm
|
||||||
|
|
|
@ -21,6 +21,7 @@ from zerver.lib.actions import (
|
||||||
)
|
)
|
||||||
from zerver.lib.exceptions import JsonableError, OrganizationOwnerRequired
|
from zerver.lib.exceptions import JsonableError, OrganizationOwnerRequired
|
||||||
from zerver.lib.i18n import get_available_language_codes
|
from zerver.lib.i18n import get_available_language_codes
|
||||||
|
from zerver.lib.message import parse_message_content_delete_limit
|
||||||
from zerver.lib.request import REQ, has_request_variables
|
from zerver.lib.request import REQ, has_request_variables
|
||||||
from zerver.lib.response import json_success
|
from zerver.lib.response import json_success
|
||||||
from zerver.lib.retention import parse_message_retention_days
|
from zerver.lib.retention import parse_message_retention_days
|
||||||
|
@ -67,8 +68,8 @@ def update_realm(
|
||||||
json_validator=check_int_in(Realm.COMMON_POLICY_TYPES), default=None
|
json_validator=check_int_in(Realm.COMMON_POLICY_TYPES), default=None
|
||||||
),
|
),
|
||||||
allow_message_deleting: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
allow_message_deleting: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
message_content_delete_limit_seconds: Optional[int] = REQ(
|
message_content_delete_limit_seconds_raw: Optional[Union[int, str]] = REQ(
|
||||||
converter=to_non_negative_int, default=None
|
"message_content_delete_limit_seconds", json_validator=check_string_or_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),
|
||||||
edit_topic_policy: Optional[int] = REQ(
|
edit_topic_policy: Optional[int] = REQ(
|
||||||
|
@ -157,6 +158,22 @@ def update_realm(
|
||||||
if invite_to_realm_policy is not None and not user_profile.is_realm_owner:
|
if invite_to_realm_policy is not None and not user_profile.is_realm_owner:
|
||||||
raise OrganizationOwnerRequired()
|
raise OrganizationOwnerRequired()
|
||||||
|
|
||||||
|
data: Dict[str, Any] = {}
|
||||||
|
|
||||||
|
message_content_delete_limit_seconds: Optional[int] = None
|
||||||
|
if message_content_delete_limit_seconds_raw is not None:
|
||||||
|
message_content_delete_limit_seconds = parse_message_content_delete_limit(
|
||||||
|
message_content_delete_limit_seconds_raw,
|
||||||
|
Realm.MESSAGE_CONTENT_DELETE_LIMIT_SPECIAL_VALUES_MAP,
|
||||||
|
)
|
||||||
|
do_set_realm_property(
|
||||||
|
realm,
|
||||||
|
"message_content_delete_limit_seconds",
|
||||||
|
message_content_delete_limit_seconds,
|
||||||
|
acting_user=user_profile,
|
||||||
|
)
|
||||||
|
data["message_content_delete_limit_seconds"] = message_content_delete_limit_seconds
|
||||||
|
|
||||||
# The user of `locals()` here is a bit of a code smell, but it's
|
# The user of `locals()` here is a bit of a code smell, but it's
|
||||||
# restricted to the elements present in realm.property_types.
|
# restricted to the elements present in realm.property_types.
|
||||||
#
|
#
|
||||||
|
@ -164,7 +181,6 @@ def update_realm(
|
||||||
# further by some more advanced usage of the
|
# further by some more advanced usage of the
|
||||||
# `REQ/has_request_variables` extraction.
|
# `REQ/has_request_variables` extraction.
|
||||||
req_vars = {k: v for k, v in list(locals().items()) if k in realm.property_types}
|
req_vars = {k: v for k, v in list(locals().items()) if k in realm.property_types}
|
||||||
data: Dict[str, Any] = {}
|
|
||||||
|
|
||||||
for k, v in list(req_vars.items()):
|
for k, v in list(req_vars.items()):
|
||||||
if v is not None and getattr(realm, k) != v:
|
if v is not None and getattr(realm, k) != v:
|
||||||
|
|
Loading…
Reference in New Issue