settings: Add `can_add_custom_emoji_group` realm setting.

Added `can_add_custom_emoji_group` setting to replace `add_custom_emoji_policy`.
This commit is contained in:
Vector73 2024-10-13 12:39:11 +05:30 committed by Tim Abbott
parent b95225d071
commit f733ab112c
26 changed files with 296 additions and 58 deletions

View File

@ -20,6 +20,14 @@ format used by the Zulip server that they are interacting with.
## Changes in Zulip 10.0
**Feature level 307**
* `PATCH /realm`, [`GET /events`](/api/get-events),
[`POST /register`](/api/register-queue):
Added `can_add_custom_emoji_group` realm setting which is a
[group-setting value](/api/group-setting-values) describing the set of users
with permission to add custom emoji in the organization.
**Feature level 306**
* [`GET /events`](/api/get-events): Removed the `extra_data` optional

View File

@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
# new level means in api_docs/changelog.md, as well as "**Changes**"
# entries in the endpoint's documentation in `zulip.yaml`.
API_FEATURE_LEVEL = 306 # Last bumped for adding `max_file_upload_size_mib`.
API_FEATURE_LEVEL = 307 # Last bumped for can_add_custom_emoji_group.
# 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

View File

@ -21,6 +21,7 @@ import * as settings_sections from "./settings_sections";
import * as settings_toggle from "./settings_toggle";
import * as settings_users from "./settings_users";
import {current_user, realm} from "./state_data";
import * as user_groups from "./user_groups";
const admin_settings_label = {
// Organization profile
@ -125,7 +126,6 @@ export function build_page() {
realm_require_unique_names: realm.realm_require_unique_names,
realm_email_changes_disabled: realm.realm_email_changes_disabled,
realm_avatar_changes_disabled: realm.realm_avatar_changes_disabled,
realm_add_custom_emoji_policy: realm.realm_add_custom_emoji_policy,
can_add_emojis: settings_data.user_can_add_custom_emoji(),
can_create_new_bots: settings_bots.can_create_new_bots(),
realm_message_content_edit_limit_minutes:
@ -186,6 +186,10 @@ export function build_page() {
policy_values: settings_config.common_policy_values,
realm_can_delete_any_message_group: realm.realm_can_delete_any_message_group,
realm_can_delete_own_message_group: realm.realm_can_delete_own_message_group,
realm_can_add_custom_emoji_group: realm.realm_can_add_custom_emoji_group,
realm_can_add_custom_emoji_group_name: user_groups.get_user_group_from_id(
realm.realm_can_add_custom_emoji_group,
).name,
...settings_org.get_organization_settings_options(),
demote_inactive_streams_values: settings_config.demote_inactive_streams_values,
web_mark_read_on_scroll_policy_values:

View File

@ -205,7 +205,6 @@ export function dispatch_normal_event(event) {
case "realm": {
const realm_settings = {
add_custom_emoji_policy: settings_emoji.update_custom_emoji_ui,
allow_edit_history: noop,
allow_message_editing: noop,
edit_topic_policy: noop,
@ -300,6 +299,10 @@ export function dispatch_normal_event(event) {
gear_menu.rerender();
}
if (key === "can_add_custom_emoji_group") {
settings_emoji.update_custom_emoji_ui();
}
if (
key === "can_create_public_channel_group" ||
key === "can_create_private_channel_group" ||

View File

@ -218,7 +218,6 @@ export function get_subsection_property_elements($subsection: JQuery): HTMLEleme
type simple_dropdown_realm_settings = Pick<
typeof realm,
| "realm_invite_to_stream_policy"
| "realm_add_custom_emoji_policy"
| "realm_invite_to_realm_policy"
| "realm_wildcard_mention_policy"
| "realm_move_messages_between_streams_policy"
@ -482,6 +481,7 @@ const dropdown_widget_map = new Map<string, DropdownWidget | null>([
["can_remove_subscribers_group", null],
["realm_can_access_all_users_group", null],
["can_mention_group", null],
["realm_can_add_custom_emoji_group", null],
["realm_can_create_groups", null],
["realm_can_create_public_channel_group", null],
["realm_can_create_private_channel_group", null],
@ -807,6 +807,7 @@ export function check_realm_settings_property_changed(elem: HTMLElement): boolea
case "realm_default_code_block_language":
case "realm_create_multiuse_invite_group":
case "realm_can_access_all_users_group":
case "realm_can_add_custom_emoji_group":
case "realm_can_create_groups":
case "realm_can_create_public_channel_group":
case "realm_can_create_private_channel_group":
@ -1047,6 +1048,7 @@ export function populate_data_for_realm_settings_request(
}
const realm_group_settings_using_new_api_format = new Set([
"can_add_custom_emoji_group",
"can_create_groups",
"can_create_private_channel_group",
"can_create_public_channel_group",

View File

@ -240,7 +240,11 @@ export function user_can_create_user_groups(): boolean {
}
export function user_can_add_custom_emoji(): boolean {
return user_has_permission(realm.realm_add_custom_emoji_policy);
return user_has_permission_for_group_setting(
realm.realm_can_add_custom_emoji_group,
"can_add_custom_emoji_group",
"realm",
);
}
export function user_can_move_messages_to_another_topic(): boolean {

View File

@ -18,11 +18,11 @@ import * as ListWidget from "./list_widget";
import * as loading from "./loading";
import * as people from "./people";
import * as scroll_util from "./scroll_util";
import * as settings_config from "./settings_config";
import * as settings_data from "./settings_data";
import {current_user, realm} from "./state_data";
import * as ui_report from "./ui_report";
import * as upload_widget from "./upload_widget";
import * as user_groups from "./user_groups";
import * as util from "./util";
const meta = {
@ -45,8 +45,9 @@ function can_delete_emoji(emoji: ServerEmoji): boolean {
export function update_custom_emoji_ui(): void {
const rendered_tip = render_settings_emoji_settings_tip({
realm_add_custom_emoji_policy: realm.realm_add_custom_emoji_policy,
policy_values: settings_config.common_policy_values,
realm_can_add_custom_emoji_group_name: user_groups.get_user_group_from_id(
realm.realm_can_add_custom_emoji_group,
).name,
});
$("#emoji-settings").find(".emoji-settings-tip-container").html(rendered_tip);
if (!settings_data.user_can_add_custom_emoji()) {

View File

@ -125,7 +125,6 @@ export function get_org_type_dropdown_options() {
const simple_dropdown_properties = [
"realm_invite_to_stream_policy",
"realm_add_custom_emoji_policy",
"realm_invite_to_realm_policy",
"realm_wildcard_mention_policy",
"realm_move_messages_between_streams_policy",
@ -509,6 +508,7 @@ export function discard_realm_property_element_changes(elem) {
case "realm_create_multiuse_invite_group":
case "realm_direct_message_initiator_group":
case "realm_direct_message_permission_group":
case "realm_can_add_custom_emoji_group":
case "realm_can_access_all_users_group":
case "realm_can_create_groups":
case "realm_can_create_public_channel_group":

View File

@ -267,7 +267,6 @@ const realm_schema = z.object({
max_topic_length: z.number(),
password_min_guesses: z.number(),
password_min_length: z.number(),
realm_add_custom_emoji_policy: z.number(),
realm_allow_edit_history: z.boolean(),
realm_allow_message_editing: z.boolean(),
realm_authentication_methods: z.record(
@ -287,6 +286,7 @@ const realm_schema = z.object({
realm_bot_creation_policy: z.number(),
realm_bot_domain: z.string(),
realm_can_access_all_users_group: z.number(),
realm_can_add_custom_emoji_group: z.number(),
realm_can_create_groups: z.number(),
realm_can_create_public_channel_group: z.number(),
realm_can_create_private_channel_group: z.number(),

View File

@ -1,10 +1,10 @@
{{#if is_guest}}
<div class='tip'>{{t "Guests cannot edit custom emoji." }}</div>
{{else if (eq realm_add_custom_emoji_policy policy_values.by_admins_only.code) }}
{{else if (eq realm_can_add_custom_emoji_group_name "role:administrators") }}
<div class='tip'>{{t "This organization is configured so that only administrators can add custom emoji." }}</div>
{{else if (eq realm_add_custom_emoji_policy policy_values.by_moderators_only.code)}}
{{else if (eq realm_can_add_custom_emoji_group_name "role:moderators")}}
<div class='tip'>{{t 'This organization is configured so that administrators and moderators can add custom emoji.'}}</div>
{{else if (eq realm_add_custom_emoji_policy policy_values.by_full_members.code)}}
{{else if (eq realm_can_add_custom_emoji_group_name "role:fullmembers")}}
<div class='tip'>{{t 'This organization is configured so that full members can add custom emoji.'}}</div>
{{else}}
<div class='tip'>{{t "This organization is configured so that any member of this organization can add custom emoji." }}</div>

View File

@ -350,12 +350,10 @@
value_type="number"
is_setting_disabled=(not is_owner)}}
<div class="input-group">
<label for="realm_add_custom_emoji_policy" class="settings-field-label">{{t "Who can add custom emoji" }}</label>
<select name="realm_add_custom_emoji_policy" class="setting-widget prop-element settings_select bootstrap-focus-style" id="id_realm_add_custom_emoji_policy" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=common_policy_values}}
</select>
</div>
{{> ../dropdown_widget_with_label
widget_name="realm_can_add_custom_emoji_group"
label=(t 'Who can add custom emoji')
value_type="number"}}
</div>
</div>
</form>

View File

@ -462,6 +462,7 @@ run_test("realm settings", ({override}) => {
override(settings_org, "check_disable_direct_message_initiator_group_dropdown", noop);
override(settings_org, "sync_realm_settings", noop);
override(settings_bots, "update_bot_permissions_ui", noop);
override(settings_emoji, "update_custom_emoji_ui", noop);
override(settings_invites, "update_invite_user_panel", noop);
override(sidebar_ui, "update_invite_user_option", noop);
override(gear_menu, "rerender", noop);
@ -582,6 +583,7 @@ run_test("realm settings", ({override}) => {
override(realm, "realm_message_content_edit_limit_seconds", 0);
override(realm, "realm_edit_topic_policy", 3);
override(realm, "realm_authentication_methods", {Google: {enabled: false, available: true}});
override(realm, "realm_can_add_custom_emoji_group", 1);
override(realm, "realm_can_create_public_channel_group", 1);
override(realm, "realm_direct_message_permission_group", 1);
override(realm, "realm_plan_type", 2);
@ -596,6 +598,7 @@ run_test("realm settings", ({override}) => {
assert_same(realm.realm_authentication_methods, {
Google: {enabled: true, available: true},
});
assert_same(realm.realm_can_add_custom_emoji_group, 3);
assert_same(realm.realm_can_create_public_channel_group, 3);
assert_same(realm.realm_direct_message_permission_group, 3);
assert_same(realm.realm_plan_type, 3);

View File

@ -368,6 +368,7 @@ exports.fixtures = {
authentication_methods: {
Google: {enabled: true, available: true},
},
can_add_custom_emoji_group: 3,
can_create_public_channel_group: 3,
direct_message_permission_group: 3,
plan_type: 3,

View File

@ -167,11 +167,6 @@ test_policy(
"realm_move_messages_between_streams_policy",
settings_data.user_can_move_messages_between_streams,
);
test_policy(
"user_can_add_custom_emoji",
"realm_add_custom_emoji_policy",
settings_data.user_can_add_custom_emoji,
);
function test_message_policy(label, policy, validation_func) {
run_test(label, ({override}) => {
@ -244,6 +239,11 @@ run_test("user_can_move_messages_between_streams_nobody_case", ({override}) => {
assert.equal(settings_data.user_can_move_messages_between_streams(), false);
});
test_realm_group_settings(
"realm_can_add_custom_emoji_group",
settings_data.user_can_add_custom_emoji,
);
test_realm_group_settings(
"realm_can_delete_any_message_group",
settings_data.user_can_delete_any_message,

View File

@ -102,7 +102,6 @@ function createSaveButtons(subsection) {
function test_submit_settings_form(override, submit_form) {
Object.assign(realm, {
realm_bot_creation_policy: settings_bots.bot_creation_policy_values.restricted.code,
realm_add_custom_emoji_policy: settings_config.common_policy_values.by_admins_only.code,
realm_waiting_period_threshold: 1,
realm_default_language: '"es"',
realm_invite_to_stream_policy: settings_config.common_policy_values.by_admins_only.code,
@ -138,11 +137,6 @@ function test_submit_settings_form(override, submit_form) {
$invite_to_stream_policy_elem.attr("id", "id_realm_invite_to_stream_policy");
$invite_to_stream_policy_elem.data = () => "number";
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");
$bot_creation_policy_elem.attr("id", "id_realm_bot_creation_policy");
@ -156,7 +150,6 @@ function test_submit_settings_form(override, submit_form) {
let $subsection_elem = $(`#org-${CSS.escape(subsection)}`);
$subsection_elem.set_find_results(".prop-element", [
$bot_creation_policy_elem,
$add_custom_emoji_policy_elem,
$invite_to_realm_policy_elem,
$invite_to_stream_policy_elem,
]);
@ -169,7 +162,6 @@ function test_submit_settings_form(override, submit_form) {
bot_creation_policy: 1,
invite_to_realm_policy: 2,
invite_to_stream_policy: 1,
add_custom_emoji_policy: 1,
};
assert.deepEqual(data, expected_value);

View File

@ -35,6 +35,9 @@ mock_esm("../src/compose_state", {
mock_esm("../src/pm_list", {
update_private_messages() {},
});
mock_esm("../src/settings", {
update_lock_icon_in_sidebar() {},
});
mock_esm("../src/settings_linkifiers", {
maybe_disable_widgets() {},
});

View File

@ -1059,6 +1059,7 @@ group_setting_update_data_type = DictType(
optional_keys=[
("create_multiuse_invite_group", int),
("can_access_all_users_group", int),
("can_add_custom_emoji_group", group_setting_type),
("can_create_groups", group_setting_type),
("can_create_public_channel_group", group_setting_type),
("can_create_private_channel_group", group_setting_type),

View File

@ -0,0 +1,23 @@
# Generated by Django 5.0.9 on 2024-10-04 07:01
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0602_remap_can_manage_all_groups"),
]
operations = [
migrations.AddField(
model_name="realm",
name="can_add_custom_emoji_group",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.RESTRICT,
related_name="+",
to="zerver.usergroup",
),
),
]

View File

@ -0,0 +1,43 @@
# Generated by Django 4.2.1 on 2023-06-12 10:47
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from django.db.models import OuterRef
def set_default_value_for_can_add_custom_emoji_group(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
Realm = apps.get_model("zerver", "Realm")
NamedUserGroup = apps.get_model("zerver", "NamedUserGroup")
add_custom_emoji_policy_to_group_name = {
1: "role:members",
2: "role:administrators",
3: "role:fullmembers",
4: "role:moderators",
}
for id, group_name in add_custom_emoji_policy_to_group_name.items():
Realm.objects.filter(can_add_custom_emoji_group=None, add_custom_emoji_policy=id).update(
can_add_custom_emoji_group=NamedUserGroup.objects.filter(
name=group_name, realm=OuterRef("id"), is_system_group=True
).values("pk")
)
class Migration(migrations.Migration):
atomic = False
dependencies = [
("zerver", "0603_realm_can_add_custom_emoji_group"),
]
operations = [
migrations.RunPython(
set_default_value_for_can_add_custom_emoji_group,
elidable=True,
reverse_code=migrations.RunPython.noop,
)
]

View File

@ -0,0 +1,22 @@
# Generated by Django 5.0.9 on 2024-10-04 07:06
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0604_set_default_value_for_can_add_custom_emoji_group"),
]
operations = [
migrations.AlterField(
model_name="realm",
name="can_add_custom_emoji_group",
field=models.ForeignKey(
on_delete=django.db.models.deletion.RESTRICT,
related_name="+",
to="zerver.usergroup",
),
),
]

View File

@ -287,6 +287,11 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
default=CommonPolicyEnum.MEMBERS_ONLY
)
# Who in the organization is allowed to add custom emojis.
can_add_custom_emoji_group = models.ForeignKey(
"UserGroup", on_delete=models.RESTRICT, related_name="+"
)
# Who in the organization is allowed to create streams.
can_create_public_channel_group = models.ForeignKey(
"UserGroup", on_delete=models.RESTRICT, related_name="+"
@ -704,6 +709,15 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
id_field_name="can_access_all_users_group_id",
allowed_system_groups=[SystemGroups.EVERYONE, SystemGroups.MEMBERS],
),
can_add_custom_emoji_group=GroupPermissionSetting(
require_system_group=False,
allow_internet_group=False,
allow_owners_group=False,
allow_nobody_group=False,
allow_everyone_group=False,
default_group_name=SystemGroups.MEMBERS,
id_field_name="can_add_custom_emoji_group_id",
),
can_create_groups=GroupPermissionSetting(
require_system_group=False,
allow_internet_group=False,
@ -794,6 +808,7 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
)
REALM_PERMISSION_GROUP_SETTINGS_WITH_NEW_API_FORMAT = [
"can_add_custom_emoji_group",
"can_create_groups",
"can_create_private_channel_group",
"can_create_public_channel_group",
@ -1181,6 +1196,8 @@ def get_realm_with_settings(realm_id: int) -> Realm:
return Realm.objects.select_related(
"can_access_all_users_group",
"can_access_all_users_group__named_user_group",
"can_add_custom_emoji_group",
"can_add_custom_emoji_group__named_user_group",
"can_create_groups",
"can_create_groups__named_user_group",
"can_create_public_channel_group",

View File

@ -816,6 +816,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin, UserBaseSettings):
if policy_name not in [
"add_custom_emoji_policy",
"can_add_custom_emoji_group",
"can_create_groups",
"can_create_private_channel_group",
"can_create_public_channel_group",
@ -910,7 +911,7 @@ class UserProfile(AbstractBaseUser, PermissionsMixin, UserBaseSettings):
return self.has_permission("edit_topic_policy")
def can_add_custom_emoji(self) -> bool:
return self.has_permission("add_custom_emoji_policy")
return self.has_permission("can_add_custom_emoji_group")
def can_delete_any_message(self) -> bool:
return self.has_permission("can_delete_any_message_group")

View File

@ -4410,6 +4410,20 @@ paths:
**Changes**: New in Zulip 10.0 (feature level 280). Previously
`realm_create_web_public_stream_policy` field used to control
the permission to create web-public channels.
can_add_custom_emoji_group:
allOf:
- description: |
A [group-setting value](/api/group-setting-values) defining the set of
users who have permission to add custom emoji in the organization.
**Changes**: New in Zulip 10.0 (feature level 307). Previously, this
permission was controlled by the enum `add_custom_emoji_policy`. Values
were 1=Members, 2=Admins, 3=Full members, 4=Moderators.
Before Zulip 5.0 (feature level 85), the `realm_add_emoji_by_admins_only`
boolean setting controlled this permission; `true` corresponded to `Admins`,
and `false` to `Everyone`.
- $ref: "#/components/schemas/GroupSettingValue"
can_delete_any_message_group:
allOf:
- description: |
@ -16235,6 +16249,22 @@ paths:
Whether this organization is configured to allow users to access
[message edit history](/help/view-a-messages-edit-history).
realm_can_add_custom_emoji_group:
allOf:
- description: |
Present if `realm` is present in `fetch_event_types`.
A [group-setting value](/api/group-setting-values) defining the set of
users who have permission to add custom emoji in the organization.
**Changes**: New in Zulip 10.0 (feature level 307). Previously, this
permission was controlled by the enum `add_custom_emoji_policy`. Values
were 1=Members, 2=Admins, 3=Full members, 4=Moderators.
Before Zulip 5.0 (feature level 85), the `realm_add_emoji_by_admins_only`
boolean setting controlled this permission; `true` corresponded to `Admins`,
and `false` to `Everyone`.
- $ref: "#/components/schemas/GroupSettingValue"
realm_can_delete_any_message_group:
allOf:
- description: |

View File

@ -130,6 +130,7 @@ class HomeTest(ZulipTestCase):
"realm_bot_domain",
"realm_bots",
"realm_can_access_all_users_group",
"realm_can_add_custom_emoji_group",
"realm_can_create_groups",
"realm_can_create_private_channel_group",
"realm_can_create_public_channel_group",

View File

@ -3,15 +3,20 @@ from unittest import mock
from zerver.actions.create_realm import do_create_realm
from zerver.actions.create_user import do_create_user
from zerver.actions.realm_emoji import check_add_realm_emoji
from zerver.actions.realm_settings import do_set_realm_property
from zerver.actions.realm_settings import (
do_change_realm_permission_group_setting,
do_set_realm_property,
)
from zerver.actions.user_groups import check_add_user_group
from zerver.actions.users import do_change_user_role
from zerver.lib.emoji import get_emoji_file_name
from zerver.lib.exceptions import JsonableError
from zerver.lib.test_classes import ZulipTestCase
from zerver.lib.test_helpers import get_test_image_file
from zerver.lib.thumbnail import BadImageError
from zerver.models import Realm, RealmEmoji, UserProfile
from zerver.models.realms import CommonPolicyEnum, get_realm
from zerver.models import NamedUserGroup, Realm, RealmEmoji, UserProfile
from zerver.models.groups import SystemGroups
from zerver.models.realms import get_realm
class RealmEmojiTest(ZulipTestCase):
@ -57,8 +62,15 @@ class RealmEmojiTest(ZulipTestCase):
# having no author are also there in the list.
self.login("othello")
realm = get_realm("zulip")
realm.add_custom_emoji_policy = CommonPolicyEnum.ADMINS_ONLY
realm.save()
administrators_system_group = NamedUserGroup.objects.get(
name=SystemGroups.ADMINISTRATORS, realm=realm, is_system_group=True
)
do_change_realm_permission_group_setting(
realm,
"can_add_custom_emoji_group",
administrators_system_group,
acting_user=None,
)
realm_emoji = self.create_test_emoji_with_no_author("my_emoji", realm)
result = self.client_get("/json/realm/emoji")
@ -165,19 +177,23 @@ class RealmEmojiTest(ZulipTestCase):
result = self.client_post("/json/realm/emoji/%20", info=emoji_data)
self.assert_json_error(result, "Emoji name is missing")
def test_can_add_custom_emoji(self) -> None:
def validation_func(user_profile: UserProfile) -> bool:
return user_profile.can_add_custom_emoji()
self.check_has_permission_policies("add_custom_emoji_policy", validation_func)
def test_user_settings_for_adding_custom_emoji(self) -> None:
othello = self.example_user("othello")
cordelia = self.example_user("cordelia")
iago = self.example_user("iago")
realm = othello.realm
self.login_user(othello)
do_change_user_role(othello, UserProfile.ROLE_MODERATOR, acting_user=None)
do_set_realm_property(
othello.realm, "add_custom_emoji_policy", CommonPolicyEnum.ADMINS_ONLY, acting_user=None
administrators_system_group = NamedUserGroup.objects.get(
name=SystemGroups.ADMINISTRATORS, realm=realm, is_system_group=True
)
do_change_realm_permission_group_setting(
realm,
"can_add_custom_emoji_group",
administrators_system_group,
acting_user=None,
)
with get_test_image_file("img.png") as fp1:
emoji_data = {"f1": fp1}
@ -190,10 +206,13 @@ class RealmEmojiTest(ZulipTestCase):
result = self.client_post("/json/realm/emoji/my_emoji_1", info=emoji_data)
self.assert_json_success(result)
do_set_realm_property(
othello.realm,
"add_custom_emoji_policy",
CommonPolicyEnum.MODERATORS_ONLY,
moderators_system_group = NamedUserGroup.objects.get(
name=SystemGroups.MODERATORS, realm=realm, is_system_group=True
)
do_change_realm_permission_group_setting(
realm,
"can_add_custom_emoji_group",
moderators_system_group,
acting_user=None,
)
do_change_user_role(othello, UserProfile.ROLE_MEMBER, acting_user=None)
@ -208,10 +227,13 @@ class RealmEmojiTest(ZulipTestCase):
result = self.client_post("/json/realm/emoji/my_emoji_2", info=emoji_data)
self.assert_json_success(result)
do_set_realm_property(
othello.realm,
"add_custom_emoji_policy",
CommonPolicyEnum.FULL_MEMBERS_ONLY,
full_members_system_group = NamedUserGroup.objects.get(
name=SystemGroups.FULL_MEMBERS, realm=realm, is_system_group=True
)
do_change_realm_permission_group_setting(
realm,
"can_add_custom_emoji_group",
full_members_system_group,
acting_user=None,
)
do_set_realm_property(othello.realm, "waiting_period_threshold", 100000, acting_user=None)
@ -228,10 +250,13 @@ class RealmEmojiTest(ZulipTestCase):
result = self.client_post("/json/realm/emoji/my_emoji_3", info=emoji_data)
self.assert_json_success(result)
do_set_realm_property(
othello.realm,
"add_custom_emoji_policy",
CommonPolicyEnum.MEMBERS_ONLY,
members_system_group = NamedUserGroup.objects.get(
name=SystemGroups.MEMBERS, realm=realm, is_system_group=True
)
do_change_realm_permission_group_setting(
realm,
"can_add_custom_emoji_group",
members_system_group,
acting_user=None,
)
do_change_user_role(othello, UserProfile.ROLE_GUEST, acting_user=None)
@ -246,6 +271,61 @@ class RealmEmojiTest(ZulipTestCase):
result = self.client_post("/json/realm/emoji/my_emoji_4", info=emoji_data)
self.assert_json_success(result)
# Test for checking setting for non-system user group.
user_group = check_add_user_group(
realm, "newgroup", [othello, cordelia], acting_user=othello
)
do_change_realm_permission_group_setting(
realm, "can_add_custom_emoji_group", user_group, acting_user=None
)
# Othello is in the allowed user group, so can add custom emoji.
with get_test_image_file("img.png") as fp1:
emoji_data = {"f1": fp1}
result = self.client_post("/json/realm/emoji/my_emoji_5", info=emoji_data)
self.assert_json_success(result)
# Iago is not present in the allowed user group, so cannot add custom emoji.
self.login_user(iago)
with get_test_image_file("img.png") as fp1:
emoji_data = {"f1": fp1}
result = self.client_post("/json/realm/emoji/my_emoji_6", info=emoji_data)
self.assert_json_error(result, "Insufficient permission")
# Test for checking the setting for anonymous user group.
anonymous_user_group = self.create_or_update_anonymous_group_for_setting(
[othello],
[administrators_system_group],
)
do_change_realm_permission_group_setting(
realm,
"can_add_custom_emoji_group",
anonymous_user_group,
acting_user=None,
)
# Iago is present in the `administrators_system_group` subgroup, so can add
# custom emoji.
with get_test_image_file("img.png") as fp1:
emoji_data = {"f1": fp1}
result = self.client_post("/json/realm/emoji/my_emoji_6", info=emoji_data)
self.assert_json_success(result)
# Othello is the direct member of the allowed anonymous user group, so can add
# custom emoji.
self.login_user(othello)
with get_test_image_file("img.png") as fp1:
emoji_data = {"f1": fp1}
result = self.client_post("/json/realm/emoji/my_emoji_7", info=emoji_data)
self.assert_json_success(result)
# Cordelia is not present in the anonymous user group, so cannot add custom emoji.
self.login_user(cordelia)
with get_test_image_file("img.png") as fp1:
emoji_data = {"f1": fp1}
result = self.client_post("/json/realm/emoji/my_emoji_6", info=emoji_data)
self.assert_json_error(result, "Insufficient permission")
def test_delete(self) -> None:
emoji_author = self.example_user("iago")
self.login_user(emoji_author)

View File

@ -112,6 +112,7 @@ def update_realm(
inline_image_preview: Json[bool] | None = None,
inline_url_embed_preview: Json[bool] | None = None,
add_custom_emoji_policy: Json[CommonPolicyEnum] | None = None,
can_add_custom_emoji_group: Json[GroupSettingChangeRequest] | None = None,
can_delete_any_message_group: Json[GroupSettingChangeRequest] | None = None,
can_delete_own_message_group: Json[GroupSettingChangeRequest] | None = None,
message_content_delete_limit_seconds_raw: Annotated[