models: Use COMMON_POLICY_TYPES for user_group_edit_policy.

This commit adds moderators and full members options for
user_group_edit_policy by using COMMON_POLICY_TYPES.

Moderators do not require to be a member of user group in
order to edit or remove the user group if they are allowed
to do so according to user_group_edit_policy.
But full members need to be a member of user group to edit
or remove the user group.
This commit is contained in:
sahil839
2021-05-21 10:32:43 +05:30
committed by Tim Abbott
parent 93a1479286
commit 50240ca71b
8 changed files with 310 additions and 223 deletions

View File

@@ -575,12 +575,8 @@ def require_user_group_edit_permission(view_func: ViewFuncT) -> ViewFuncT:
def _wrapped_view_func( def _wrapped_view_func(
request: HttpRequest, user_profile: UserProfile, *args: object, **kwargs: object request: HttpRequest, user_profile: UserProfile, *args: object, **kwargs: object
) -> HttpResponse: ) -> HttpResponse:
realm = user_profile.realm if not user_profile.can_edit_user_groups():
if ( raise JsonableError(_("Insufficient permission"))
realm.user_group_edit_policy != Realm.USER_GROUP_EDIT_POLICY_MEMBERS
and not user_profile.is_realm_admin
):
raise OrganizationAdministratorRequired()
return view_func(request, user_profile, *args, **kwargs) return view_func(request, user_profile, *args, **kwargs)
return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927 return cast(ViewFuncT, _wrapped_view_func) # https://github.com/python/mypy/issues/1927

View File

@@ -11,7 +11,11 @@ def access_user_group_by_id(user_group_id: int, user_profile: UserProfile) -> Us
try: try:
user_group = UserGroup.objects.get(id=user_group_id, realm=user_profile.realm) user_group = UserGroup.objects.get(id=user_group_id, realm=user_profile.realm)
group_member_ids = get_user_group_members(user_group) group_member_ids = get_user_group_members(user_group)
if not user_profile.is_realm_admin and user_profile.id not in group_member_ids: if (
not user_profile.is_realm_admin
and not user_profile.is_moderator
and user_profile.id not in group_member_ids
):
raise JsonableError(_("Insufficient permission")) raise JsonableError(_("Insufficient permission"))
except UserGroup.DoesNotExist: except UserGroup.DoesNotExist:
raise JsonableError(_("Invalid user group")) raise JsonableError(_("Invalid user group"))

View File

@@ -291,15 +291,7 @@ class Realm(models.Model):
default=POLICY_ADMINS_ONLY default=POLICY_ADMINS_ONLY
) )
USER_GROUP_EDIT_POLICY_MEMBERS = 1 user_group_edit_policy: int = models.PositiveSmallIntegerField(default=POLICY_MEMBERS_ONLY)
USER_GROUP_EDIT_POLICY_ADMINS = 2
user_group_edit_policy: int = models.PositiveSmallIntegerField(
default=USER_GROUP_EDIT_POLICY_MEMBERS
)
USER_GROUP_EDIT_POLICY_TYPES = [
USER_GROUP_EDIT_POLICY_MEMBERS,
USER_GROUP_EDIT_POLICY_ADMINS,
]
PRIVATE_MESSAGE_POLICY_UNLIMITED = 1 PRIVATE_MESSAGE_POLICY_UNLIMITED = 1
PRIVATE_MESSAGE_POLICY_DISABLED = 2 PRIVATE_MESSAGE_POLICY_DISABLED = 2

View File

@@ -3464,6 +3464,8 @@ paths:
* 1 = All members can create and edit user groups * 1 = All members can create and edit user groups
* 2 = Only organization administrators can create and edit user groups * 2 = Only organization administrators can create and edit user groups
* 3 = Only full members can create and edit user groups
* 4 = Only organization administrators and moderators can create and edit user groups
default_code_block_language: default_code_block_language:
type: string type: string
nullable: true nullable: true
@@ -9009,6 +9011,8 @@ paths:
* 1 = All members can create and edit user groups * 1 = All members can create and edit user groups
* 2 = Only organization administrators can create and edit user groups * 2 = Only organization administrators can create and edit user groups
* 3 = Only full members can create and edit user groups.
* 4 = Only organization administrators and moderators can create and edit user groups.
realm_default_code_block_language: realm_default_code_block_language:
type: string type: string
nullable: true nullable: true

View File

@@ -2029,7 +2029,7 @@ class RealmPropertyActionTest(BaseAction):
create_stream_policy=[4, 3, 2, 1], create_stream_policy=[4, 3, 2, 1],
invite_to_stream_policy=[4, 3, 2, 1], invite_to_stream_policy=[4, 3, 2, 1],
private_message_policy=[2, 1], private_message_policy=[2, 1],
user_group_edit_policy=[1, 2], user_group_edit_policy=[1, 2, 3, 4],
wildcard_mention_policy=[7, 6, 5, 4, 3, 2, 1], wildcard_mention_policy=[7, 6, 5, 4, 3, 2, 1],
email_address_visibility=[Realm.EMAIL_ADDRESS_VISIBILITY_ADMINS], email_address_visibility=[Realm.EMAIL_ADDRESS_VISIBILITY_ADMINS],
bot_creation_policy=[Realm.BOT_CREATION_EVERYONE], bot_creation_policy=[Realm.BOT_CREATION_EVERYONE],

View File

@@ -757,7 +757,7 @@ class RealmAPITest(ZulipTestCase):
name=["Zulip", "New Name"], name=["Zulip", "New Name"],
waiting_period_threshold=[10, 20], waiting_period_threshold=[10, 20],
create_stream_policy=Realm.COMMON_POLICY_TYPES, create_stream_policy=Realm.COMMON_POLICY_TYPES,
user_group_edit_policy=Realm.USER_GROUP_EDIT_POLICY_TYPES, user_group_edit_policy=Realm.COMMON_POLICY_TYPES,
private_message_policy=Realm.PRIVATE_MESSAGE_POLICY_TYPES, private_message_policy=Realm.PRIVATE_MESSAGE_POLICY_TYPES,
invite_to_stream_policy=Realm.COMMON_POLICY_TYPES, invite_to_stream_policy=Realm.COMMON_POLICY_TYPES,
wildcard_mention_policy=Realm.WILDCARD_MENTION_POLICY_TYPES, wildcard_mention_policy=Realm.WILDCARD_MENTION_POLICY_TYPES,

View File

@@ -1,6 +1,9 @@
from datetime import timedelta
from typing import Optional
from unittest import mock from unittest import mock
import orjson import orjson
from django.utils.timezone import now as timezone_now
from zerver.lib.actions import do_set_realm_property, ensure_stream from zerver.lib.actions import do_set_realm_property, ensure_stream
from zerver.lib.test_classes import ZulipTestCase from zerver.lib.test_classes import ZulipTestCase
@@ -77,7 +80,7 @@ class UserGroupTestCase(ZulipTestCase):
self.assertFalse(check_remove_user_from_user_group(othello, user_group)) self.assertFalse(check_remove_user_from_user_group(othello, user_group))
class UserGroupAPITestCase(ZulipTestCase): class UserGroupAPITestCase(UserGroupTestCase):
def test_user_group_create(self) -> None: def test_user_group_create(self) -> None:
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
@@ -129,19 +132,6 @@ class UserGroupAPITestCase(ZulipTestCase):
self.check_has_permission_policies("user_group_edit_policy", validation_func) self.check_has_permission_policies("user_group_edit_policy", validation_func)
def test_user_group_create_by_guest_user(self) -> None:
guest_user = self.example_user("polonius")
# Guest users can't create user group
self.login_user(guest_user)
params = {
"name": "support",
"members": orjson.dumps([guest_user.id]).decode(),
"description": "Support team",
}
result = self.client_post("/json/user_groups/create", info=params)
self.assert_json_error(result, "Not allowed for guest users")
def test_user_group_update(self) -> None: def test_user_group_update(self) -> None:
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
self.login("hamlet") self.login("hamlet")
@@ -169,50 +159,6 @@ class UserGroupAPITestCase(ZulipTestCase):
result = self.client_patch("/json/user_groups/1111", info=params) result = self.client_patch("/json/user_groups/1111", info=params)
self.assert_json_error(result, "Invalid user group") self.assert_json_error(result, "Invalid user group")
self.logout()
# Test when user not a member of user group tries to modify it
cordelia = self.example_user("cordelia")
self.login_user(cordelia)
params = {
"name": "help",
"description": "Troubleshooting",
}
result = self.client_patch(f"/json/user_groups/{user_group.id}", info=params)
self.assert_json_error(result, "Insufficient permission")
self.logout()
# Test when organization admin tries to modify group
iago = self.example_user("iago")
self.login_user(iago)
params = {
"name": "help",
"description": "Troubleshooting",
}
result = self.client_patch(f"/json/user_groups/{user_group.id}", info=params)
self.assert_json_success(result)
def test_user_group_update_by_guest_user(self) -> None:
hamlet = self.example_user("hamlet")
guest_user = self.example_user("polonius")
self.login_user(hamlet)
params = {
"name": "support",
"members": orjson.dumps([hamlet.id, guest_user.id]).decode(),
"description": "Support team",
}
result = self.client_post("/json/user_groups/create", info=params)
self.assert_json_success(result)
user_group = UserGroup.objects.get(name="support")
# Guest user can't edit any detail of an user group
self.login_user(guest_user)
params = {
"name": "help",
"description": "Troubleshooting team",
}
result = self.client_patch(f"/json/user_groups/{user_group.id}", info=params)
self.assert_json_error(result, "Not allowed for guest users")
def test_user_group_update_to_already_existing_name(self) -> None: def test_user_group_update_to_already_existing_name(self) -> None:
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
self.login_user(hamlet) self.login_user(hamlet)
@@ -248,51 +194,6 @@ class UserGroupAPITestCase(ZulipTestCase):
result = self.client_delete("/json/user_groups/1111") result = self.client_delete("/json/user_groups/1111")
self.assert_json_error(result, "Invalid user group") self.assert_json_error(result, "Invalid user group")
# Test when user not a member of user group tries to delete it
params = {
"name": "Development",
"members": orjson.dumps([hamlet.id]).decode(),
"description": "Development team",
}
self.client_post("/json/user_groups/create", info=params)
user_group = UserGroup.objects.get(name="Development")
self.assertEqual(UserGroup.objects.count(), 2)
self.logout()
cordelia = self.example_user("cordelia")
self.login_user(cordelia)
result = self.client_delete(f"/json/user_groups/{user_group.id}")
self.assert_json_error(result, "Insufficient permission")
self.assertEqual(UserGroup.objects.count(), 2)
self.logout()
# Test when organization admin tries to delete group
iago = self.example_user("iago")
self.login_user(iago)
result = self.client_delete(f"/json/user_groups/{user_group.id}")
self.assert_json_success(result)
self.assertEqual(UserGroup.objects.count(), 1)
self.assertEqual(UserGroupMembership.objects.count(), 2)
def test_user_group_delete_by_guest_user(self) -> None:
hamlet = self.example_user("hamlet")
guest_user = self.example_user("polonius")
self.login_user(hamlet)
params = {
"name": "support",
"members": orjson.dumps([hamlet.id, guest_user.id]).decode(),
"description": "Support team",
}
result = self.client_post("/json/user_groups/create", info=params)
self.assert_json_success(result)
user_group = UserGroup.objects.get(name="support")
# Guest users can't delete any user group(not even those of which they are a member)
self.login_user(guest_user)
result = self.client_delete(f"/json/user_groups/{user_group.id}")
self.assert_json_error(result, "Not allowed for guest users")
def test_update_members_of_user_group(self) -> None: def test_update_members_of_user_group(self) -> None:
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
self.login("hamlet") self.login("hamlet")
@@ -322,28 +223,7 @@ class UserGroupAPITestCase(ZulipTestCase):
members = get_memberships_of_users(user_group, [hamlet, othello]) members = get_memberships_of_users(user_group, [hamlet, othello])
self.assert_length(members, 2) self.assert_length(members, 2)
self.logout()
# Test when user not a member of user group tries to add members to it
cordelia = self.example_user("cordelia")
self.login_user(cordelia)
add = [cordelia.id]
params = {"add": orjson.dumps(add).decode()}
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
self.assert_json_error(result, "Insufficient permission")
self.assertEqual(UserGroupMembership.objects.count(), 4)
self.logout()
# Test when organization admin tries to add members to group
iago = self.example_user("iago")
self.login_user(iago)
aaron = self.example_user("aaron") aaron = self.example_user("aaron")
add = [aaron.id]
params = {"add": orjson.dumps(add).decode()}
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
self.assert_json_success(result)
self.assertEqual(UserGroupMembership.objects.count(), 5)
members = get_memberships_of_users(user_group, [hamlet, othello, aaron])
self.assert_length(members, 3)
# For normal testing we again log in with hamlet # For normal testing we again log in with hamlet
self.logout() self.logout()
@@ -352,41 +232,23 @@ class UserGroupAPITestCase(ZulipTestCase):
params = {"delete": orjson.dumps([othello.id]).decode()} params = {"delete": orjson.dumps([othello.id]).decode()}
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params) result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
self.assert_json_success(result) self.assert_json_success(result)
self.assertEqual(UserGroupMembership.objects.count(), 4) self.assertEqual(UserGroupMembership.objects.count(), 3)
members = get_memberships_of_users(user_group, [hamlet, othello, aaron]) members = get_memberships_of_users(user_group, [hamlet, othello, aaron])
self.assert_length(members, 2) self.assert_length(members, 1)
# Test remove a member that's already removed # Test remove a member that's already removed
params = {"delete": orjson.dumps([othello.id]).decode()} params = {"delete": orjson.dumps([othello.id]).decode()}
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params) result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
self.assert_json_error(result, f"There is no member '{othello.id}' in this user group") self.assert_json_error(result, f"There is no member '{othello.id}' in this user group")
self.assertEqual(UserGroupMembership.objects.count(), 4) self.assertEqual(UserGroupMembership.objects.count(), 3)
members = get_memberships_of_users(user_group, [hamlet, othello, aaron]) members = get_memberships_of_users(user_group, [hamlet, othello, aaron])
self.assert_length(members, 2) self.assert_length(members, 1)
# Test when nothing is provided # Test when nothing is provided
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info={}) result = self.client_post(f"/json/user_groups/{user_group.id}/members", info={})
msg = 'Nothing to do. Specify at least one of "add" or "delete".' msg = 'Nothing to do. Specify at least one of "add" or "delete".'
self.assert_json_error(result, msg) self.assert_json_error(result, msg)
# Test when user not a member of user group tries to remove members
self.logout()
self.login_user(cordelia)
params = {"delete": orjson.dumps([hamlet.id]).decode()}
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
self.assert_json_error(result, "Insufficient permission")
self.assertEqual(UserGroupMembership.objects.count(), 4)
self.logout()
# Test when organization admin tries to remove members from group
iago = self.example_user("iago")
self.login_user(iago)
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
self.assert_json_success(result)
self.assertEqual(UserGroupMembership.objects.count(), 3)
members = get_memberships_of_users(user_group, [hamlet, othello, aaron])
self.assert_length(members, 1)
def test_mentions(self) -> None: def test_mentions(self) -> None:
cordelia = self.example_user("cordelia") cordelia = self.example_user("cordelia")
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
@@ -436,82 +298,311 @@ class UserGroupAPITestCase(ZulipTestCase):
um = most_recent_usermessage(user) um = most_recent_usermessage(user)
self.assertFalse(um.flags.mentioned) self.assertFalse(um.flags.mentioned)
def test_only_admin_manage_groups(self) -> None: def test_user_group_edit_policy_for_creating_and_deleting_user_group(self) -> None:
iago = self.example_user("iago")
hamlet = self.example_user("hamlet") hamlet = self.example_user("hamlet")
cordelia = self.example_user("cordelia")
self.login_user(iago)
do_set_realm_property(
iago.realm,
"user_group_edit_policy",
Realm.USER_GROUP_EDIT_POLICY_ADMINS,
acting_user=None,
)
def check_create_user_group(acting_user: str, error_msg: Optional[str] = None) -> None:
self.login(acting_user)
params = { params = {
"name": "support", "name": "support",
"members": orjson.dumps([iago.id, hamlet.id]).decode(), "members": orjson.dumps([hamlet.id]).decode(),
"description": "Support Team",
}
result = self.client_post("/json/user_groups/create", info=params)
if error_msg is None:
self.assert_json_success(result)
# One group already exists in the test database.
self.assert_length(UserGroup.objects.all(), 2)
else:
self.assert_json_error(result, error_msg)
def check_delete_user_group(acting_user: str, error_msg: Optional[str] = None) -> None:
self.login(acting_user)
user_group = UserGroup.objects.get(name="support")
result = self.client_delete(f"/json/user_groups/{user_group.id}")
if error_msg is None:
self.assert_json_success(result)
self.assert_length(UserGroup.objects.all(), 1)
else:
self.assert_json_error(result, error_msg)
realm = hamlet.realm
# Check only admins are allowed to create/delete user group. Admins are allowed even if
# they are not a member of the group.
do_set_realm_property(
realm,
"user_group_edit_policy",
Realm.POLICY_ADMINS_ONLY,
acting_user=None,
)
check_create_user_group("shiva", "Insufficient permission")
check_create_user_group("iago")
check_delete_user_group("shiva", "Insufficient permission")
check_delete_user_group("iago")
# Check moderators are allowed to create/delete user group but not members. Moderators are
# allowed even if they are not a member of the group.
do_set_realm_property(
realm,
"user_group_edit_policy",
Realm.POLICY_MODERATORS_ONLY,
acting_user=None,
)
check_create_user_group("cordelia", "Insufficient permission")
check_create_user_group("shiva")
check_delete_user_group("hamlet", "Insufficient permission")
check_delete_user_group("shiva")
# Check only members are allowed to create the user group and they are allowed to delete
# a user group only if they are a member of that group.
do_set_realm_property(
realm,
"user_group_edit_policy",
Realm.POLICY_MEMBERS_ONLY,
acting_user=None,
)
check_create_user_group("polonius", "Not allowed for guest users")
check_create_user_group("cordelia")
check_delete_user_group("polonius", "Not allowed for guest users")
check_delete_user_group("cordelia", "Insufficient permission")
check_delete_user_group("hamlet")
# Check only full members are allowed to create the user group and they are allowed to delete
# a user group only if they are a member of that group.
do_set_realm_property(
realm,
"user_group_edit_policy",
Realm.POLICY_FULL_MEMBERS_ONLY,
acting_user=None,
)
cordelia = self.example_user("cordelia")
do_set_realm_property(realm, "waiting_period_threshold", 10, acting_user=None)
cordelia.date_joined = timezone_now() - timedelta(days=9)
cordelia.save()
check_create_user_group("cordelia", "Insufficient permission")
cordelia.date_joined = timezone_now() - timedelta(days=11)
cordelia.save()
check_create_user_group("cordelia")
hamlet.date_joined = timezone_now() - timedelta(days=9)
hamlet.save()
check_delete_user_group("cordelia", "Insufficient permission")
check_delete_user_group("hamlet", "Insufficient permission")
hamlet.date_joined = timezone_now() - timedelta(days=11)
hamlet.save()
check_delete_user_group("hamlet")
def test_user_group_edit_policy_for_updating_user_groups(self) -> None:
othello = self.example_user("othello")
self.login("othello")
params = {
"name": "support",
"members": orjson.dumps([othello.id]).decode(),
"description": "Support team", "description": "Support team",
} }
self.client_post("/json/user_groups/create", info=params)
result = self.client_post("/json/user_groups/create", info=params)
self.assert_json_success(result)
user_group = UserGroup.objects.get(name="support") user_group = UserGroup.objects.get(name="support")
# Test add member def check_update_user_group(
params = {"add": orjson.dumps([cordelia.id]).decode()} new_name: str,
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params) new_description: str,
self.assert_json_success(result) acting_user: str,
error_msg: Optional[str] = None,
# Test remove member ) -> None:
params = {"delete": orjson.dumps([cordelia.id]).decode()} self.login(acting_user)
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
self.assert_json_success(result)
# Test changing groups name
params = { params = {
"name": "help", "name": new_name,
"description": "Troubleshooting", "description": new_description,
} }
result = self.client_patch(f"/json/user_groups/{user_group.id}", info=params) result = self.client_patch(f"/json/user_groups/{user_group.id}", info=params)
if error_msg is None:
self.assert_json_success(result) self.assert_json_success(result)
else:
self.assert_json_error(result, error_msg)
# Test delete a group realm = othello.realm
result = self.client_delete(f"/json/user_groups/{user_group.id}")
self.assert_json_success(result)
user_group = create_user_group( # Check only admins are allowed to update user group. Admins are allowed even if
name="support", # they are not a member of the group.
members=[hamlet, iago], do_set_realm_property(
realm=iago.realm, realm,
"user_group_edit_policy",
Realm.POLICY_ADMINS_ONLY,
acting_user=None,
) )
check_update_user_group("help", "Troubleshooting team", "shiva", "Insufficient permission")
check_update_user_group("help", "Troubleshooting team", "iago")
self.logout() # Check moderators are allowed to update user group but not members. Moderators are
# allowed even if they are not a member of the group.
do_set_realm_property(
realm,
"user_group_edit_policy",
Realm.POLICY_MODERATORS_ONLY,
acting_user=None,
)
check_update_user_group("support", "Support team", "othello", "Insufficient permission")
check_update_user_group("support", "Support team", "iago")
self.login("hamlet") # Check only members are allowed to update the user group and only if belong to the
# user group.
do_set_realm_property(
realm,
"user_group_edit_policy",
Realm.POLICY_MEMBERS_ONLY,
acting_user=None,
)
check_update_user_group(
"help", "Troubleshooting team", "polonius", "Not allowed for guest users"
)
check_update_user_group(
"help",
"Troubleshooting team",
"cordelia",
"Insufficient permission",
)
check_update_user_group("help", "Troubleshooting team", "othello")
# Test creating a group # Check only full members are allowed to update the user group and only if belong to the
params = { # user group.
"name": "support2", do_set_realm_property(
"members": orjson.dumps([hamlet.id]).decode(), realm, "user_group_edit_policy", Realm.POLICY_FULL_MEMBERS_ONLY, acting_user=None
"description": "Support team", )
} do_set_realm_property(realm, "waiting_period_threshold", 10, acting_user=None)
result = self.client_post("/json/user_groups/create", info=params) othello = self.example_user("othello")
self.assert_json_error(result, "Must be an organization administrator") othello.date_joined = timezone_now() - timedelta(days=9)
othello.save()
# Test add member cordelia = self.example_user("cordelia")
params = {"add": orjson.dumps([cordelia.id]).decode()} cordelia.date_joined = timezone_now() - timedelta(days=11)
cordelia.save()
check_update_user_group(
"support",
"Support team",
"cordelia",
"Insufficient permission",
)
check_update_user_group("support", "Support team", "othello", "Insufficient permission")
othello.date_joined = timezone_now() - timedelta(days=11)
othello.save()
check_update_user_group("support", "Support team", "othello")
def test_user_group_edit_policy_for_updating_members(self) -> None:
user_group = self.create_user_group_for_test("support")
aaron = self.example_user("aaron")
othello = self.example_user("othello")
cordelia = self.example_user("cordelia")
def check_adding_members_to_group(
acting_user: str, error_msg: Optional[str] = None
) -> None:
self.login(acting_user)
params = {"add": orjson.dumps([aaron.id]).decode()}
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params) result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
self.assert_json_error(result, "Must be an organization administrator") if error_msg is None:
self.assert_json_success(result)
self.assertEqual(UserGroupMembership.objects.count(), 4)
members = get_memberships_of_users(user_group, [aaron, othello])
self.assert_length(members, 2)
else:
self.assert_json_error(result, error_msg)
# Test delete a group def check_removing_members_from_group(
result = self.client_delete(f"/json/user_groups/{user_group.id}") acting_user: str, error_msg: Optional[str] = None
self.assert_json_error(result, "Must be an organization administrator") ) -> None:
self.login(acting_user)
params = {"delete": orjson.dumps([aaron.id]).decode()}
result = self.client_post(f"/json/user_groups/{user_group.id}/members", info=params)
if error_msg is None:
self.assert_json_success(result)
self.assertEqual(UserGroupMembership.objects.count(), 3)
members = get_memberships_of_users(user_group, [aaron, othello])
self.assert_length(members, 1)
else:
self.assert_json_error(result, error_msg)
# Test changing groups name realm = get_realm("zulip")
params = { # Check only admins are allowed to add/remove users from the group. Admins are allowed even if
"name": "help", # they are not a member of the group.
"description": "Troubleshooting", do_set_realm_property(
} realm,
result = self.client_patch(f"/json/user_groups/{user_group.id}", info=params) "user_group_edit_policy",
self.assert_json_error(result, "Must be an organization administrator") Realm.POLICY_ADMINS_ONLY,
acting_user=None,
)
check_adding_members_to_group("shiva", "Insufficient permission")
check_adding_members_to_group("iago")
check_removing_members_from_group("shiva", "Insufficient permission")
check_removing_members_from_group("iago")
# Check moderators are allowed to add/remove users from the group but not members. Moderators are
# allowed even if they are not a member of the group.
do_set_realm_property(
realm,
"user_group_edit_policy",
Realm.POLICY_MODERATORS_ONLY,
acting_user=None,
)
check_adding_members_to_group("cordelia", "Insufficient permission")
check_adding_members_to_group("shiva")
check_removing_members_from_group("hamlet", "Insufficient permission")
check_removing_members_from_group("shiva")
# Check only members are allowed to add/remove users in the group and only if belong to the
# user group.
do_set_realm_property(
realm,
"user_group_edit_policy",
Realm.POLICY_MEMBERS_ONLY,
acting_user=None,
)
check_adding_members_to_group("polonius", "Not allowed for guest users")
check_adding_members_to_group("cordelia", "Insufficient permission")
check_adding_members_to_group("othello")
check_removing_members_from_group("polonius", "Not allowed for guest users")
check_removing_members_from_group("cordelia", "Insufficient permission")
check_removing_members_from_group("othello")
# Check only full members are allowed to add/remove users in the group and only if belong to the
# user group.
do_set_realm_property(
realm,
"user_group_edit_policy",
Realm.POLICY_FULL_MEMBERS_ONLY,
acting_user=None,
)
do_set_realm_property(realm, "waiting_period_threshold", 10, acting_user=None)
othello.date_joined = timezone_now() - timedelta(days=9)
othello.save()
check_adding_members_to_group("cordelia", "Insufficient permission")
cordelia.date_joined = timezone_now() - timedelta(days=11)
cordelia.save()
check_adding_members_to_group("cordelia", "Insufficient permission")
othello.date_joined = timezone_now() - timedelta(days=11)
othello.save()
check_adding_members_to_group("othello")
othello.date_joined = timezone_now() - timedelta(days=9)
othello.save()
check_removing_members_from_group("cordelia", "Insufficient permission")
check_removing_members_from_group("othello", "Insufficient permission")
othello.date_joined = timezone_now() - timedelta(days=11)
othello.save()
check_removing_members_from_group("othello")

View File

@@ -102,7 +102,7 @@ def update_realm(
json_validator=check_int_in(Realm.COMMON_POLICY_TYPES), default=None json_validator=check_int_in(Realm.COMMON_POLICY_TYPES), default=None
), ),
user_group_edit_policy: Optional[int] = REQ( user_group_edit_policy: Optional[int] = REQ(
json_validator=check_int_in(Realm.USER_GROUP_EDIT_POLICY_TYPES), default=None json_validator=check_int_in(Realm.COMMON_POLICY_TYPES), default=None
), ),
private_message_policy: Optional[int] = REQ( private_message_policy: Optional[int] = REQ(
json_validator=check_int_in(Realm.PRIVATE_MESSAGE_POLICY_TYPES), default=None json_validator=check_int_in(Realm.PRIVATE_MESSAGE_POLICY_TYPES), default=None