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:
sahil839 2021-05-17 19:10:28 +05:30 committed by Tim Abbott
parent 5efc854f66
commit 1ce09d9db6
8 changed files with 83 additions and 51 deletions

View File

@ -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:

View File

@ -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)

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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(

View File

@ -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():