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 @@
- - + {{> dropdown_options_widget option_values=add_custom_emoji_policy_values}}
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