mirror of https://github.com/zulip/zulip.git
realm: Extend add_custom_emoji_policy to use COMMON_POLICY_TYPES.
This commit adds full members and moderators option for add_custom_emoji_policy by using COMMON_POLICY_TYPES.
This commit is contained in:
parent
5efc854f66
commit
1ce09d9db6
|
@ -5,7 +5,7 @@ from typing import Tuple
|
||||||
import orjson
|
import orjson
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from zerver.lib.exceptions import JsonableError, OrganizationAdministratorRequired
|
from zerver.lib.exceptions import JsonableError
|
||||||
from zerver.lib.storage import static_path
|
from zerver.lib.storage import static_path
|
||||||
from zerver.lib.upload import upload_backend
|
from zerver.lib.upload import upload_backend
|
||||||
from zerver.models import Reaction, Realm, RealmEmoji, UserProfile
|
from zerver.models import Reaction, Realm, RealmEmoji, UserProfile
|
||||||
|
@ -84,16 +84,6 @@ def check_emoji_request(realm: Realm, emoji_name: str, emoji_code: str, emoji_ty
|
||||||
raise JsonableError(_("Invalid emoji type."))
|
raise JsonableError(_("Invalid emoji type."))
|
||||||
|
|
||||||
|
|
||||||
def check_add_emoji_admin(user_profile: UserProfile) -> None:
|
|
||||||
"""Raises an exception if the user cannot add the emoji in their organization."""
|
|
||||||
|
|
||||||
# Realm administrators can always add emoji
|
|
||||||
if user_profile.is_realm_admin:
|
|
||||||
return
|
|
||||||
if user_profile.realm.add_custom_emoji_policy == Realm.ADD_CUSTOM_EMOJI_ADMINS_ONLY:
|
|
||||||
raise OrganizationAdministratorRequired()
|
|
||||||
|
|
||||||
|
|
||||||
def check_remove_custom_emoji(user_profile: UserProfile, emoji_name: str) -> None:
|
def check_remove_custom_emoji(user_profile: UserProfile, emoji_name: str) -> None:
|
||||||
# normal users can remove emoji they themselves added
|
# normal users can remove emoji they themselves added
|
||||||
if user_profile.is_realm_admin:
|
if user_profile.is_realm_admin:
|
||||||
|
|
|
@ -245,17 +245,8 @@ class Realm(models.Model):
|
||||||
send_welcome_emails: bool = models.BooleanField(default=True)
|
send_welcome_emails: bool = models.BooleanField(default=True)
|
||||||
message_content_allowed_in_email_notifications: 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)
|
mandatory_topics: 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)
|
name_changes_disabled: bool = models.BooleanField(default=False)
|
||||||
email_changes_disabled: bool = models.BooleanField(default=False)
|
email_changes_disabled: bool = models.BooleanField(default=False)
|
||||||
avatar_changes_disabled: bool = models.BooleanField(default=False)
|
avatar_changes_disabled: bool = models.BooleanField(default=False)
|
||||||
|
@ -292,6 +283,9 @@ class Realm(models.Model):
|
||||||
|
|
||||||
DEFAULT_COMMUNITY_TOPIC_EDITING_LIMIT_SECONDS = 259200
|
DEFAULT_COMMUNITY_TOPIC_EDITING_LIMIT_SECONDS = 259200
|
||||||
|
|
||||||
|
# Who in the organization is allowed to add custom emojis.
|
||||||
|
add_custom_emoji_policy: int = models.PositiveSmallIntegerField(default=POLICY_MEMBERS_ONLY)
|
||||||
|
|
||||||
# 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)
|
||||||
|
|
||||||
|
|
|
@ -8739,6 +8739,8 @@ paths:
|
||||||
|
|
||||||
* 1 = Members only
|
* 1 = Members only
|
||||||
* 2 = Administrators only
|
* 2 = Administrators only
|
||||||
|
* 3 = Full members only
|
||||||
|
* 4 = Moderators only
|
||||||
|
|
||||||
**Changes**: New in Zulip 5.0 (feature level 85) replacing the
|
**Changes**: New in Zulip 5.0 (feature level 85) replacing the
|
||||||
previous `realm_add_emoji_by_admins_only` boolean.
|
previous `realm_add_emoji_by_admins_only` boolean.
|
||||||
|
|
|
@ -2047,7 +2047,7 @@ class RealmPropertyActionTest(BaseAction):
|
||||||
message_content_delete_limit_seconds=[1000, 1100, 1200],
|
message_content_delete_limit_seconds=[1000, 1100, 1200],
|
||||||
invite_to_realm_policy=[6, 4, 3, 2, 1],
|
invite_to_realm_policy=[6, 4, 3, 2, 1],
|
||||||
move_messages_between_streams_policy=[4, 3, 2, 1],
|
move_messages_between_streams_policy=[4, 3, 2, 1],
|
||||||
add_custom_emoji_policy=[2, 1],
|
add_custom_emoji_policy=[4, 3, 2, 1],
|
||||||
)
|
)
|
||||||
|
|
||||||
vals = test_values.get(name)
|
vals = test_values.get(name)
|
||||||
|
|
|
@ -781,7 +781,7 @@ class RealmAPITest(ZulipTestCase):
|
||||||
message_content_delete_limit_seconds=[1000, 1100, 1200],
|
message_content_delete_limit_seconds=[1000, 1100, 1200],
|
||||||
invite_to_realm_policy=Realm.INVITE_TO_REALM_POLICY_TYPES,
|
invite_to_realm_policy=Realm.INVITE_TO_REALM_POLICY_TYPES,
|
||||||
move_messages_between_streams_policy=Realm.COMMON_POLICY_TYPES,
|
move_messages_between_streams_policy=Realm.COMMON_POLICY_TYPES,
|
||||||
add_custom_emoji_policy=Realm.ADD_CUSTOM_EMOJI_POLICY_TYPES,
|
add_custom_emoji_policy=Realm.COMMON_POLICY_TYPES,
|
||||||
)
|
)
|
||||||
|
|
||||||
vals = test_values.get(name)
|
vals = test_values.get(name)
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from zerver.lib.actions import check_add_realm_emoji, do_create_realm, do_create_user
|
from zerver.lib.actions import (
|
||||||
|
check_add_realm_emoji,
|
||||||
|
do_change_user_role,
|
||||||
|
do_create_realm,
|
||||||
|
do_create_user,
|
||||||
|
do_set_realm_property,
|
||||||
|
)
|
||||||
from zerver.lib.test_classes import ZulipTestCase
|
from zerver.lib.test_classes import ZulipTestCase
|
||||||
from zerver.lib.test_helpers import get_test_image_file
|
from zerver.lib.test_helpers import get_test_image_file
|
||||||
from zerver.models import Realm, RealmEmoji, UserProfile, get_realm
|
from zerver.models import Realm, RealmEmoji, UserProfile, get_realm
|
||||||
|
@ -47,7 +53,7 @@ class RealmEmojiTest(ZulipTestCase):
|
||||||
# having no author are also there in the list.
|
# having no author are also there in the list.
|
||||||
self.login("othello")
|
self.login("othello")
|
||||||
realm = get_realm("zulip")
|
realm = get_realm("zulip")
|
||||||
realm.add_custom_emoji_policy = Realm.ADD_CUSTOM_EMOJI_ADMINS_ONLY
|
realm.add_custom_emoji_policy = Realm.POLICY_ADMINS_ONLY
|
||||||
realm.save()
|
realm.save()
|
||||||
realm_emoji = self.create_test_emoji_with_no_author("my_emoji", realm)
|
realm_emoji = self.create_test_emoji_with_no_author("my_emoji", realm)
|
||||||
|
|
||||||
|
@ -139,33 +145,75 @@ class RealmEmojiTest(ZulipTestCase):
|
||||||
|
|
||||||
self.check_has_permission_policies("add_custom_emoji_policy", validation_func)
|
self.check_has_permission_policies("add_custom_emoji_policy", validation_func)
|
||||||
|
|
||||||
def test_upload_admins_only(self) -> None:
|
def test_user_settings_for_adding_custom_emoji(self) -> None:
|
||||||
self.login("othello")
|
othello = self.example_user("othello")
|
||||||
realm = get_realm("zulip")
|
self.login_user(othello)
|
||||||
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}
|
|
||||||
result = self.client_post("/json/realm/emoji/my_emoji", info=emoji_data)
|
|
||||||
self.assert_json_error(result, "Must be an organization administrator")
|
|
||||||
|
|
||||||
def test_upload_anyone(self) -> None:
|
do_change_user_role(othello, UserProfile.ROLE_MODERATOR, acting_user=None)
|
||||||
self.login("othello")
|
do_set_realm_property(
|
||||||
realm = get_realm("zulip")
|
othello.realm, "add_custom_emoji_policy", Realm.POLICY_ADMINS_ONLY, acting_user=None
|
||||||
realm.add_custom_emoji_policy = Realm.ADD_CUSTOM_EMOJI_MEMBERS_ONLY
|
)
|
||||||
realm.save()
|
|
||||||
with get_test_image_file("img.png") as fp1:
|
with get_test_image_file("img.png") as fp1:
|
||||||
emoji_data = {"f1": fp1}
|
emoji_data = {"f1": fp1}
|
||||||
result = self.client_post("/json/realm/emoji/my_emoji", info=emoji_data)
|
result = self.client_post("/json/realm/emoji/my_emoji_1", info=emoji_data)
|
||||||
|
self.assert_json_error(result, "Insufficient permission")
|
||||||
|
|
||||||
|
do_change_user_role(othello, UserProfile.ROLE_REALM_ADMINISTRATOR, acting_user=None)
|
||||||
|
with get_test_image_file("img.png") as fp1:
|
||||||
|
emoji_data = {"f1": fp1}
|
||||||
|
result = self.client_post("/json/realm/emoji/my_emoji_1", info=emoji_data)
|
||||||
self.assert_json_success(result)
|
self.assert_json_success(result)
|
||||||
|
|
||||||
def test_emoji_upload_by_guest_user(self) -> None:
|
do_set_realm_property(
|
||||||
self.login("polonius")
|
othello.realm, "add_custom_emoji_policy", Realm.POLICY_MODERATORS_ONLY, acting_user=None
|
||||||
|
)
|
||||||
|
do_change_user_role(othello, UserProfile.ROLE_MEMBER, acting_user=None)
|
||||||
with get_test_image_file("img.png") as fp1:
|
with get_test_image_file("img.png") as fp1:
|
||||||
emoji_data = {"f1": fp1}
|
emoji_data = {"f1": fp1}
|
||||||
result = self.client_post("/json/realm/emoji/my_emoji", info=emoji_data)
|
result = self.client_post("/json/realm/emoji/my_emoji_2", info=emoji_data)
|
||||||
|
self.assert_json_error(result, "Insufficient permission")
|
||||||
|
|
||||||
|
do_change_user_role(othello, UserProfile.ROLE_MODERATOR, acting_user=None)
|
||||||
|
with get_test_image_file("img.png") as fp1:
|
||||||
|
emoji_data = {"f1": fp1}
|
||||||
|
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",
|
||||||
|
Realm.POLICY_FULL_MEMBERS_ONLY,
|
||||||
|
acting_user=None,
|
||||||
|
)
|
||||||
|
do_set_realm_property(othello.realm, "waiting_period_threshold", 100000, acting_user=None)
|
||||||
|
do_change_user_role(othello, UserProfile.ROLE_MEMBER, acting_user=None)
|
||||||
|
|
||||||
|
with get_test_image_file("img.png") as fp1:
|
||||||
|
emoji_data = {"f1": fp1}
|
||||||
|
result = self.client_post("/json/realm/emoji/my_emoji_3", info=emoji_data)
|
||||||
|
self.assert_json_error(result, "Insufficient permission")
|
||||||
|
|
||||||
|
do_set_realm_property(othello.realm, "waiting_period_threshold", 0, acting_user=None)
|
||||||
|
with get_test_image_file("img.png") as fp1:
|
||||||
|
emoji_data = {"f1": fp1}
|
||||||
|
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", Realm.POLICY_MEMBERS_ONLY, acting_user=None
|
||||||
|
)
|
||||||
|
do_change_user_role(othello, UserProfile.ROLE_GUEST, acting_user=None)
|
||||||
|
with get_test_image_file("img.png") as fp1:
|
||||||
|
emoji_data = {"f1": fp1}
|
||||||
|
result = self.client_post("/json/realm/emoji/my_emoji_4", info=emoji_data)
|
||||||
self.assert_json_error(result, "Not allowed for guest users")
|
self.assert_json_error(result, "Not allowed for guest users")
|
||||||
|
|
||||||
|
do_change_user_role(othello, UserProfile.ROLE_MEMBER, acting_user=None)
|
||||||
|
with get_test_image_file("img.png") as fp1:
|
||||||
|
emoji_data = {"f1": fp1}
|
||||||
|
result = self.client_post("/json/realm/emoji/my_emoji_4", info=emoji_data)
|
||||||
|
self.assert_json_success(result)
|
||||||
|
|
||||||
def test_delete(self) -> None:
|
def test_delete(self) -> None:
|
||||||
emoji_author = self.example_user("iago")
|
emoji_author = self.example_user("iago")
|
||||||
self.login_user(emoji_author)
|
self.login_user(emoji_author)
|
||||||
|
|
|
@ -61,7 +61,7 @@ def update_realm(
|
||||||
inline_image_preview: 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),
|
inline_url_embed_preview: Optional[bool] = REQ(json_validator=check_bool, default=None),
|
||||||
add_custom_emoji_policy: Optional[int] = REQ(
|
add_custom_emoji_policy: Optional[int] = REQ(
|
||||||
json_validator=check_int_in(Realm.ADD_CUSTOM_EMOJI_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: Optional[int] = REQ(
|
||||||
|
|
|
@ -4,12 +4,7 @@ from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from zerver.decorator import require_member_or_admin
|
from zerver.decorator import require_member_or_admin
|
||||||
from zerver.lib.actions import check_add_realm_emoji, do_remove_realm_emoji
|
from zerver.lib.actions import check_add_realm_emoji, do_remove_realm_emoji
|
||||||
from zerver.lib.emoji import (
|
from zerver.lib.emoji import check_remove_custom_emoji, check_valid_emoji_name, name_to_codepoint
|
||||||
check_add_emoji_admin,
|
|
||||||
check_remove_custom_emoji,
|
|
||||||
check_valid_emoji_name,
|
|
||||||
name_to_codepoint,
|
|
||||||
)
|
|
||||||
from zerver.lib.exceptions import JsonableError
|
from zerver.lib.exceptions import JsonableError
|
||||||
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
|
||||||
|
@ -31,7 +26,10 @@ def upload_emoji(
|
||||||
emoji_name = emoji_name.strip().replace(" ", "_")
|
emoji_name = emoji_name.strip().replace(" ", "_")
|
||||||
valid_built_in_emoji = name_to_codepoint.keys()
|
valid_built_in_emoji = name_to_codepoint.keys()
|
||||||
check_valid_emoji_name(emoji_name)
|
check_valid_emoji_name(emoji_name)
|
||||||
check_add_emoji_admin(user_profile)
|
|
||||||
|
if not user_profile.can_add_custom_emoji():
|
||||||
|
raise JsonableError(_("Insufficient permission"))
|
||||||
|
|
||||||
if RealmEmoji.objects.filter(
|
if RealmEmoji.objects.filter(
|
||||||
realm=user_profile.realm, name=emoji_name, deactivated=False
|
realm=user_profile.realm, name=emoji_name, deactivated=False
|
||||||
).exists():
|
).exists():
|
||||||
|
|
Loading…
Reference in New Issue