diff --git a/frontend_tests/node_tests/settings_org.js b/frontend_tests/node_tests/settings_org.js
index eeae78f2c1..b910e761e6 100644
--- a/frontend_tests/node_tests/settings_org.js
+++ b/frontend_tests/node_tests/settings_org.js
@@ -165,7 +165,8 @@ function test_submit_settings_form(override, submit_form) {
realm_bot_creation_policy: settings_bots.bot_creation_policy_values.restricted.code,
realm_email_address_visibility:
settings_config.email_address_visibility_values.admins_only.code,
- realm_add_emoji_by_admins_only: true,
+ realm_add_custom_emoji_policy:
+ settings_config.add_custom_emoji_policy_values.by_admins_only.code,
realm_create_stream_by_admins_only: true,
realm_waiting_period_threshold: 1,
realm_default_language: '"es"',
@@ -210,9 +211,10 @@ function test_submit_settings_form(override, submit_form) {
create_stream_policy_elem.attr("id", "id_realm_create_stream_policy");
create_stream_policy_elem.data = () => "number";
- const add_emoji_by_admins_only_elem = $("#id_realm_add_emoji_by_admins_only");
- add_emoji_by_admins_only_elem.val("by_anyone");
- add_emoji_by_admins_only_elem.attr("id", "id_realm_add_emoji_by_admins_only");
+ const add_custom_emoji_policy_elem = $("#id_realm_add_custom_emoji_policy");
+ add_custom_emoji_policy_elem.val("1");
+ add_custom_emoji_policy_elem.attr("id", "id_realm_add_custom_emoji_policy");
+ add_custom_emoji_policy_elem.data = () => "number";
const bot_creation_policy_elem = $("#id_realm_bot_creation_policy");
bot_creation_policy_elem.val("1");
@@ -233,7 +235,7 @@ function test_submit_settings_form(override, submit_form) {
subsection_elem.set_find_results(".prop-element", [
bot_creation_policy_elem,
email_address_visibility_elem,
- add_emoji_by_admins_only_elem,
+ add_custom_emoji_policy_elem,
create_stream_policy_elem,
invite_to_stream_policy_elem,
]);
@@ -246,7 +248,7 @@ function test_submit_settings_form(override, submit_form) {
bot_creation_policy: 1,
invite_to_stream_policy: 1,
email_address_visibility: 1,
- add_emoji_by_admins_only: false,
+ add_custom_emoji_policy: 1,
create_stream_policy: 2,
};
assert.deepEqual(data, expected_value);
diff --git a/static/js/admin.js b/static/js/admin.js
index 4b8ce60762..d6a97c7206 100644
--- a/static/js/admin.js
+++ b/static/js/admin.js
@@ -76,8 +76,10 @@ export function build_page() {
realm_name_changes_disabled: page_params.realm_name_changes_disabled,
realm_email_changes_disabled: page_params.realm_email_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_custom_emoji_policy: page_params.realm_add_custom_emoji_policy,
can_add_emojis: settings_emoji.can_add_emoji(),
+ ADD_CUSTOM_EMOJI_POLICY_ADMINS_ONLY:
+ settings_config.add_custom_emoji_policy_values.by_admins_only.code,
realm_message_content_edit_limit_minutes: settings_org.get_realm_time_limits_in_minutes(
"realm_message_content_edit_limit_seconds",
),
diff --git a/static/js/server_events_dispatch.js b/static/js/server_events_dispatch.js
index 8f4c035d1c..fe06bdbce3 100644
--- a/static/js/server_events_dispatch.js
+++ b/static/js/server_events_dispatch.js
@@ -176,7 +176,7 @@ export function dispatch_normal_event(event) {
case "realm": {
const realm_settings = {
- add_emoji_by_admins_only: settings_emoji.update_custom_emoji_ui,
+ add_custom_emoji_policy: settings_emoji.update_custom_emoji_ui,
allow_edit_history: noop,
allow_message_deleting: noop,
allow_message_editing: noop,
diff --git a/static/js/settings_config.js b/static/js/settings_config.js
index 53a22c8489..f070bf4913 100644
--- a/static/js/settings_config.js
+++ b/static/js/settings_config.js
@@ -158,6 +158,19 @@ export const invite_to_realm_policy_values = {
},
};
+export const add_custom_emoji_policy_values = {
+ by_admins_only: {
+ order: 1,
+ code: 2,
+ description: $t({defaultMessage: "Admins"}),
+ },
+ by_members: {
+ order: 2,
+ code: 1,
+ description: $t({defaultMessage: "Admins and members"}),
+ },
+};
+
export const private_message_policy_values = {
by_anyone: {
order: 1,
diff --git a/static/js/settings_emoji.js b/static/js/settings_emoji.js
index e48fa06554..1f6ed78dac 100644
--- a/static/js/settings_emoji.js
+++ b/static/js/settings_emoji.js
@@ -13,6 +13,7 @@ import * as ListWidget from "./list_widget";
import * as loading from "./loading";
import {page_params} from "./page_params";
import * as people from "./people";
+import * as settings_config from "./settings_config";
import * as ui from "./ui";
import * as ui_report from "./ui_report";
import * as upload_widget from "./upload_widget";
@@ -31,7 +32,10 @@ export function can_add_emoji() {
}
// for normal users, we depend on the setting
- return !page_params.realm_add_emoji_by_admins_only;
+ return (
+ page_params.realm_add_custom_emoji_policy ===
+ settings_config.add_custom_emoji_policy_values.by_members.code
+ );
}
function can_delete_emoji(emoji) {
@@ -50,10 +54,15 @@ function can_delete_emoji(emoji) {
export function update_custom_emoji_ui() {
const rendered_tip = render_settings_emoji_settings_tip({
- realm_add_emoji_by_admins_only: page_params.realm_add_emoji_by_admins_only,
+ ADD_CUSTOM_EMOJI_POLICY_ADMINS_ONLY:
+ settings_config.add_custom_emoji_policy_values.by_admins_only.code,
});
$("#emoji-settings").find(".emoji-settings-tip-container").html(rendered_tip);
- if (page_params.realm_add_emoji_by_admins_only && !page_params.is_admin) {
+ if (
+ page_params.realm_add_custom_emoji_policy ===
+ settings_config.add_custom_emoji_policy_values.by_admins_only.code &&
+ !page_params.is_admin
+ ) {
$(".add-emoji-text").hide();
$(".admin-emoji-form").hide();
} else {
diff --git a/static/js/settings_org.js b/static/js/settings_org.js
index 848c19bb61..c1c4e48cb7 100644
--- a/static/js/settings_org.js
+++ b/static/js/settings_org.js
@@ -108,6 +108,9 @@ export function get_organization_settings_options() {
options.invite_to_realm_policy_values = get_sorted_options_list(
settings_config.invite_to_realm_policy_values,
);
+ options.add_custom_emoji_policy_values = get_sorted_options_list(
+ settings_config.add_custom_emoji_policy_values,
+ );
return options;
}
@@ -138,13 +141,6 @@ function get_property_value(property_name) {
return "custom_days";
}
- if (property_name === "realm_add_emoji_by_admins_only") {
- if (page_params.realm_add_emoji_by_admins_only) {
- return "by_admins_only";
- }
- return "by_anyone";
- }
-
if (property_name === "realm_msg_edit_limit_setting") {
if (!page_params.realm_allow_message_editing) {
return "never";
@@ -207,7 +203,7 @@ const simple_dropdown_properties = [
"realm_invite_to_stream_policy",
"realm_user_group_edit_policy",
"realm_private_message_policy",
- "realm_add_emoji_by_admins_only",
+ "realm_add_custom_emoji_policy",
"realm_invite_to_realm_policy",
"realm_wildcard_mention_policy",
"realm_move_messages_between_streams_policy",
@@ -831,18 +827,6 @@ export function build_page() {
data.default_code_block_language = code_block_language_value;
break;
}
- case "other_permissions": {
- const add_emoji_permission = $("#id_realm_add_emoji_by_admins_only").val();
- switch (add_emoji_permission) {
- case "by_admins_only":
- data.add_emoji_by_admins_only = true;
- break;
- case "by_anyone":
- data.add_emoji_by_admins_only = false;
- break;
- }
- break;
- }
case "org_join": {
const org_join_restrictions = $("#id_realm_org_join_restrictions").val();
switch (org_join_restrictions) {
diff --git a/static/styles/settings.css b/static/styles/settings.css
index eba350912c..94101e5640 100644
--- a/static/styles/settings.css
+++ b/static/styles/settings.css
@@ -1566,7 +1566,7 @@ body:not(.night-mode) #settings_page .custom_user_field .datepicker {
#id_realm_create_stream_policy,
#id_realm_invite_to_stream_policy,
#id_realm_private_message_policy,
-#id_realm_add_emoji_by_admins_only,
+#id_realm_add_custom_emoji_policy,
#id_realm_user_group_edit_policy,
#id_realm_email_address_visibility,
#id_realm_wildcard_mention_policy,
diff --git a/static/templates/settings/emoji_settings_tip.hbs b/static/templates/settings/emoji_settings_tip.hbs
index 6f6f914243..9eebae9093 100644
--- a/static/templates/settings/emoji_settings_tip.hbs
+++ b/static/templates/settings/emoji_settings_tip.hbs
@@ -1,7 +1,7 @@
{{#if is_guest}}
{{t "Guests cannot edit custom emoji." }}
{{else}}
- {{#if realm_add_emoji_by_admins_only}}
+ {{#if (eq realm_add_custom_emoji_policy ADD_CUSTOM_EMOJI_POLICY_ADMINS_ONLY) }}
{{t "Only organization administrators can add custom emoji in this organization." }}
{{else}}
{{t "Any member of this organization can add custom emoji." }}
diff --git a/static/templates/settings/organization_permissions_admin.hbs b/static/templates/settings/organization_permissions_admin.hbs
index 8e252fd32d..57194052d2 100644
--- a/static/templates/settings/organization_permissions_admin.hbs
+++ b/static/templates/settings/organization_permissions_admin.hbs
@@ -212,10 +212,9 @@
-
-
diff --git a/templates/zerver/api/changelog.md b/templates/zerver/api/changelog.md
index 6e92ea9659..d6e82a4b9a 100644
--- a/templates/zerver/api/changelog.md
+++ b/templates/zerver/api/changelog.md
@@ -11,6 +11,11 @@ below features are supported.
## Changes in Zulip 5.0
+**Feature level 85**
+
+* [`POST /register`](/api/register-queue), `PATCH /realm`: Replaced `add_emoji_by_admins_only`
+ field with an integer field `add_custom_emoji_policy`.
+
**Feature level 84**
* [`POST /register`](/api/register-queue): The `enter_sends` setting
diff --git a/version.py b/version.py
index 46baeeb265..91980c443c 100644
--- a/version.py
+++ b/version.py
@@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.4.3"
# Changes should be accompanied by documentation explaining what the
# new level means in templates/zerver/api/changelog.md, as well as
# "**Changes**" entries in the endpoint's documentation in `zulip.yaml`.
-API_FEATURE_LEVEL = 84
+API_FEATURE_LEVEL = 85
# 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
diff --git a/zerver/lib/emoji.py b/zerver/lib/emoji.py
index 35fde38f54..12b4646c5d 100644
--- a/zerver/lib/emoji.py
+++ b/zerver/lib/emoji.py
@@ -90,7 +90,7 @@ def check_add_emoji_admin(user_profile: UserProfile) -> None:
# Realm administrators can always add emoji
if user_profile.is_realm_admin:
return
- if user_profile.realm.add_emoji_by_admins_only:
+ if user_profile.realm.add_custom_emoji_policy == Realm.ADD_CUSTOM_EMOJI_ADMINS_ONLY:
raise OrganizationAdministratorRequired()
diff --git a/zerver/migrations/0337_realm_add_custom_emoji_policy.py b/zerver/migrations/0337_realm_add_custom_emoji_policy.py
new file mode 100644
index 0000000000..89a3aa881f
--- /dev/null
+++ b/zerver/migrations/0337_realm_add_custom_emoji_policy.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.2 on 2021-05-15 18:00
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("zerver", "0336_userstatus_status_emoji"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="realm",
+ name="add_custom_emoji_policy",
+ field=models.PositiveSmallIntegerField(default=1),
+ ),
+ ]
diff --git a/zerver/migrations/0338_migrate_to_add_custom_emoji_policy.py b/zerver/migrations/0338_migrate_to_add_custom_emoji_policy.py
new file mode 100644
index 0000000000..1ebf4b557c
--- /dev/null
+++ b/zerver/migrations/0338_migrate_to_add_custom_emoji_policy.py
@@ -0,0 +1,48 @@
+# Generated by Django 3.2.2 on 2021-05-15 18:01
+
+from django.db import migrations
+from django.db.backends.postgresql.schema import DatabaseSchemaEditor
+from django.db.migrations.state import StateApps
+
+
+def migrate_to_add_custom_emoji_policy(
+ apps: StateApps, schema_editor: DatabaseSchemaEditor
+) -> None:
+ Realm = apps.get_model("zerver", "Realm")
+ Realm.ADD_CUSTOM_EMOJI_MEMBERS_ONLY = 1
+ Realm.ADD_CUSTOM_EMOJI_ADMINS_ONLY = 2
+ Realm.objects.filter(add_emoji_by_admins_only=False).update(
+ add_custom_emoji_policy=Realm.ADD_CUSTOM_EMOJI_MEMBERS_ONLY
+ )
+ Realm.objects.filter(add_emoji_by_admins_only=True).update(
+ add_custom_emoji_policy=Realm.ADD_CUSTOM_EMOJI_ADMINS_ONLY
+ )
+
+
+def reverse_migrate_to_add_custom_emoji_policy(
+ apps: StateApps, schema_editor: DatabaseSchemaEditor
+) -> None:
+ Realm = apps.get_model("zerver", "Realm")
+ Realm.ADD_CUSTOM_EMOJI_MEMBERS_ONLY = 1
+ Realm.ADD_CUSTOM_EMOJI_ADMINS_ONLY = 2
+ Realm.objects.filter(add_custom_emoji_policy=Realm.ADD_CUSTOM_EMOJI_MEMBERS_ONLY).update(
+ add_emoji_by_admins_only=False
+ )
+ Realm.objects.filter(add_custom_emoji_policy=Realm.ADD_CUSTOM_EMOJI_ADMINS_ONLY).update(
+ add_emoji_by_admins_only=True
+ )
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("zerver", "0337_realm_add_custom_emoji_policy"),
+ ]
+
+ operations = [
+ migrations.RunPython(
+ migrate_to_add_custom_emoji_policy,
+ reverse_code=reverse_migrate_to_add_custom_emoji_policy,
+ elidable=True,
+ ),
+ ]
diff --git a/zerver/migrations/0339_remove_realm_add_emoji_by_admins_only.py b/zerver/migrations/0339_remove_realm_add_emoji_by_admins_only.py
new file mode 100644
index 0000000000..b88c3ce9bc
--- /dev/null
+++ b/zerver/migrations/0339_remove_realm_add_emoji_by_admins_only.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.2 on 2021-05-15 18:05
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("zerver", "0338_migrate_to_add_custom_emoji_policy"),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name="realm",
+ name="add_emoji_by_admins_only",
+ ),
+ ]
diff --git a/zerver/models.py b/zerver/models.py
index a807dead17..dba49673ff 100644
--- a/zerver/models.py
+++ b/zerver/models.py
@@ -245,8 +245,17 @@ class Realm(models.Model):
send_welcome_emails: bool = models.BooleanField(default=True)
message_content_allowed_in_email_notifications: bool = models.BooleanField(default=True)
+ ADD_CUSTOM_EMOJI_MEMBERS_ONLY = 1
+ ADD_CUSTOM_EMOJI_ADMINS_ONLY = 2
+ ADD_CUSTOM_EMOJI_POLICY_TYPES = [
+ ADD_CUSTOM_EMOJI_MEMBERS_ONLY,
+ ADD_CUSTOM_EMOJI_ADMINS_ONLY,
+ ]
+
mandatory_topics: bool = models.BooleanField(default=False)
- add_emoji_by_admins_only: bool = models.BooleanField(default=False)
+ add_custom_emoji_policy: int = models.PositiveSmallIntegerField(
+ default=ADD_CUSTOM_EMOJI_MEMBERS_ONLY
+ )
name_changes_disabled: bool = models.BooleanField(default=False)
email_changes_disabled: bool = models.BooleanField(default=False)
avatar_changes_disabled: bool = models.BooleanField(default=False)
@@ -590,7 +599,7 @@ class Realm(models.Model):
# Define the types of the various automatically managed properties
property_types: Dict[str, Union[type, Tuple[type, ...]]] = dict(
- add_emoji_by_admins_only=bool,
+ add_custom_emoji_policy=int,
allow_edit_history=bool,
allow_message_deleting=bool,
bot_creation_policy=int,
diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml
index d676b3d71f..90211dcd2e 100644
--- a/zerver/openapi/zulip.yaml
+++ b/zerver/openapi/zulip.yaml
@@ -8729,13 +8729,19 @@ paths:
type: string
description: |
The text describing the emojiset.
- realm_add_emoji_by_admins_only:
- type: boolean
+ realm_add_custom_emoji_policy:
+ type: integer
description: |
Present if `realm` is present in `fetch_event_types`.
- Whether the organization is configured to only allow administrators
- to upload new custom emoji.
+ The policy for which users can upload new custom emoji in this
+ organization.
+
+ * 1 = Members only
+ * 2 = Administrators only
+
+ **Changes**: New in Zulip 5.0 (feature level 85) replacing the
+ previous `realm_add_emoji_by_admins_only` boolean.
realm_allow_edit_history:
type: boolean
description: |
diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py
index 52e3fd90b8..3e542583d9 100644
--- a/zerver/tests/test_events.py
+++ b/zerver/tests/test_events.py
@@ -2047,6 +2047,7 @@ class RealmPropertyActionTest(BaseAction):
message_content_delete_limit_seconds=[1000, 1100, 1200],
invite_to_realm_policy=[6, 4, 3, 2, 1],
move_messages_between_streams_policy=[4, 3, 2, 1],
+ add_custom_emoji_policy=[2, 1],
)
vals = test_values.get(name)
diff --git a/zerver/tests/test_home.py b/zerver/tests/test_home.py
index 9455688187..dd7669abf4 100644
--- a/zerver/tests/test_home.py
+++ b/zerver/tests/test_home.py
@@ -129,7 +129,7 @@ class HomeTest(ZulipTestCase):
"promote_sponsoring_zulip",
"prompt_for_invites",
"queue_id",
- "realm_add_emoji_by_admins_only",
+ "realm_add_custom_emoji_policy",
"realm_allow_edit_history",
"realm_allow_message_deleting",
"realm_allow_message_editing",
diff --git a/zerver/tests/test_realm.py b/zerver/tests/test_realm.py
index 88ca1803c6..70156e6186 100644
--- a/zerver/tests/test_realm.py
+++ b/zerver/tests/test_realm.py
@@ -466,6 +466,7 @@ class RealmTest(ZulipTestCase):
wildcard_mention_policy=10,
invite_to_realm_policy=10,
move_messages_between_streams_policy=10,
+ add_custom_emoji_policy=10,
)
# We need an admin user.
@@ -780,6 +781,7 @@ class RealmAPITest(ZulipTestCase):
message_content_delete_limit_seconds=[1000, 1100, 1200],
invite_to_realm_policy=Realm.INVITE_TO_REALM_POLICY_TYPES,
move_messages_between_streams_policy=Realm.COMMON_POLICY_TYPES,
+ add_custom_emoji_policy=Realm.ADD_CUSTOM_EMOJI_POLICY_TYPES,
)
vals = test_values.get(name)
diff --git a/zerver/tests/test_realm_emoji.py b/zerver/tests/test_realm_emoji.py
index 5ad6f46b5e..e62bd8a033 100644
--- a/zerver/tests/test_realm_emoji.py
+++ b/zerver/tests/test_realm_emoji.py
@@ -47,7 +47,7 @@ class RealmEmojiTest(ZulipTestCase):
# having no author are also there in the list.
self.login("othello")
realm = get_realm("zulip")
- realm.add_emoji_by_admins_only = True
+ realm.add_custom_emoji_policy = Realm.ADD_CUSTOM_EMOJI_ADMINS_ONLY
realm.save()
realm_emoji = self.create_test_emoji_with_no_author("my_emoji", realm)
@@ -135,7 +135,7 @@ class RealmEmojiTest(ZulipTestCase):
def test_upload_admins_only(self) -> None:
self.login("othello")
realm = get_realm("zulip")
- realm.add_emoji_by_admins_only = True
+ realm.add_custom_emoji_policy = Realm.ADD_CUSTOM_EMOJI_ADMINS_ONLY
realm.save()
with get_test_image_file("img.png") as fp1:
emoji_data = {"f1": fp1}
@@ -145,7 +145,7 @@ class RealmEmojiTest(ZulipTestCase):
def test_upload_anyone(self) -> None:
self.login("othello")
realm = get_realm("zulip")
- realm.add_emoji_by_admins_only = False
+ realm.add_custom_emoji_policy = Realm.ADD_CUSTOM_EMOJI_MEMBERS_ONLY
realm.save()
with get_test_image_file("img.png") as fp1:
emoji_data = {"f1": fp1}
diff --git a/zerver/views/realm.py b/zerver/views/realm.py
index 6b8ea67b49..a05fae122a 100644
--- a/zerver/views/realm.py
+++ b/zerver/views/realm.py
@@ -60,7 +60,9 @@ def update_realm(
avatar_changes_disabled: Optional[bool] = REQ(json_validator=check_bool, default=None),
inline_image_preview: Optional[bool] = REQ(json_validator=check_bool, default=None),
inline_url_embed_preview: Optional[bool] = REQ(json_validator=check_bool, default=None),
- add_emoji_by_admins_only: Optional[bool] = REQ(json_validator=check_bool, default=None),
+ add_custom_emoji_policy: Optional[int] = REQ(
+ json_validator=check_int_in(Realm.ADD_CUSTOM_EMOJI_POLICY_TYPES), default=None
+ ),
allow_message_deleting: Optional[bool] = REQ(json_validator=check_bool, default=None),
message_content_delete_limit_seconds: Optional[int] = REQ(
converter=to_non_negative_int, default=None