diff --git a/templates/zerver/api/changelog.md b/templates/zerver/api/changelog.md index c86b38446b..42e7183ef9 100644 --- a/templates/zerver/api/changelog.md +++ b/templates/zerver/api/changelog.md @@ -10,6 +10,11 @@ below features are supported. ## Changes in Zulip 4.0 +**Feature level 61** + +* Added support for inviting users as moderators to the invitation + endpoints. + **Feature level 60** * [`POST /register`](/api/register-queue): Added a new boolean field diff --git a/templates/zerver/app/invite_user.html b/templates/zerver/app/invite_user.html index 73c8d70dc9..71f9156882 100644 --- a/templates/zerver/app/invite_user.html +++ b/templates/zerver/app/invite_user.html @@ -40,6 +40,7 @@ {% if is_admin %} + {% endif %} {% if is_owner %} diff --git a/templates/zerver/help/invite-new-users.md b/templates/zerver/help/invite-new-users.md index 4c5cc48f7c..5680dc3458 100644 --- a/templates/zerver/help/invite-new-users.md +++ b/templates/zerver/help/invite-new-users.md @@ -12,7 +12,7 @@ the article below describes each in more detail. * Share a **reusable invitation link**. The last two, invite-based, techniques also allow you to control the -[role (owner, admin, member, or guest)](/help/roles-and-permissions) that the +[role (owner, admin, moderator, member, or guest)](/help/roles-and-permissions) that the invited people will have. You can also manage access by @@ -78,7 +78,7 @@ and reusable invitation links expire 10 days after they are sent. 1. Enter a list of email addresses. -1. Decide whether the users should join as [admins, members, or +1. Decide whether the users should join as [admins, moderators, members, or guests](/help/roles-and-permissions). 1. Select which streams they should join. If you send invitations often, you @@ -100,7 +100,7 @@ and reusable invitation links expire 10 days after they are sent. 1. Click **Generate invite link**. -1. Decide whether users using the link should join as [admins, +1. Decide whether users using the link should join as [admins, moderators members, or guests](/help/roles-and-permissions). 1. Select which streams they should join. If you send invitations often, you diff --git a/version.py b/version.py index ee9f9816f9..4c37560b7d 100644 --- a/version.py +++ b/version.py @@ -30,7 +30,7 @@ DESKTOP_WARNING_VERSION = "5.2.0" # # Changes should be accompanied by documentation explaining what the # new level means in templates/zerver/api/changelog.md. -API_FEATURE_LEVEL = 60 +API_FEATURE_LEVEL = 61 # 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/models.py b/zerver/models.py index bf260164ae..359fc0f7f2 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -1713,6 +1713,7 @@ class PreregistrationUser(models.Model): INVITE_AS = dict( REALM_OWNER=100, REALM_ADMIN=200, + MODERATOR=300, MEMBER=400, GUEST_USER=600, ) diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index f1c0e153de..115b4b46c1 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -1171,6 +1171,37 @@ class InviteUserTest(InviteUserBase): ) self.assert_json_error(response, "Must be an organization administrator") + def test_successful_invite_user_as_moderator_from_admin_account(self) -> None: + self.login("iago") + invitee = self.nonreg_email("alice") + result = self.invite( + invitee, ["Denmark"], invite_as=PreregistrationUser.INVITE_AS["MODERATOR"] + ) + self.assert_json_success(result) + self.assertTrue(find_key_by_email(invitee)) + + self.submit_reg_form_for_user(invitee, "password") + invitee_profile = self.nonreg_user("alice") + self.assertFalse(invitee_profile.is_realm_admin) + self.assertTrue(invitee_profile.is_moderator) + self.assertFalse(invitee_profile.is_guest) + + def test_invite_user_as_moderator_from_normal_account(self) -> None: + self.login("hamlet") + invitee = self.nonreg_email("alice") + response = self.invite( + invitee, ["Denmark"], invite_as=PreregistrationUser.INVITE_AS["MODERATOR"] + ) + self.assert_json_error(response, "Must be an organization administrator") + + def test_invite_user_as_moderator_from_moderator_account(self) -> None: + self.login("shiva") + invitee = self.nonreg_email("alice") + response = self.invite( + invitee, ["Denmark"], invite_as=PreregistrationUser.INVITE_AS["MODERATOR"] + ) + self.assert_json_error(response, "Must be an organization administrator") + def test_invite_user_as_invalid_type(self) -> None: """ Test inviting a user as invalid type of user i.e. type of invite_as diff --git a/zerver/views/invite.py b/zerver/views/invite.py index f5b987c04b..e70a737e7c 100644 --- a/zerver/views/invite.py +++ b/zerver/views/invite.py @@ -47,7 +47,11 @@ def invite_users_backend( return json_error(_("Must be invited as an valid type of user")) check_if_owner_required(invite_as, user_profile) if ( - invite_as == PreregistrationUser.INVITE_AS["REALM_ADMIN"] + invite_as + in [ + PreregistrationUser.INVITE_AS["REALM_ADMIN"], + PreregistrationUser.INVITE_AS["MODERATOR"], + ] and not user_profile.is_realm_admin ): return json_error(_("Must be an organization administrator"))