Example #1
0
    def handle(self, *args: Any, **options: Any) -> None:
        email = options["email"]
        realm = self.get_realm(options)

        user = self.get_user(email, realm)

        user_role_map = {
            "owner": UserProfile.ROLE_REALM_OWNER,
            "admin": UserProfile.ROLE_REALM_ADMINISTRATOR,
            "moderator": UserProfile.ROLE_MODERATOR,
            "member": UserProfile.ROLE_MEMBER,
            "guest": UserProfile.ROLE_GUEST,
        }

        if options["new_role"] not in ["can_forge_sender", "can_create_users"]:
            new_role = user_role_map[options["new_role"]]
            if not options["grant"]:
                raise CommandError(
                    "Revoke not supported with this permission; please specify new role."
                )
            if new_role == user.role:
                raise CommandError("User already has this role.")
            old_role_name = UserProfile.ROLE_ID_TO_NAME_MAP[user.role]
            do_change_user_role(user, new_role, acting_user=None)
            new_role_name = UserProfile.ROLE_ID_TO_NAME_MAP[user.role]
            print(
                f"Role for {user.delivery_email} changed from {old_role_name} to {new_role_name}."
            )
            return

        if options["new_role"] == "can_forge_sender":
            if user.can_forge_sender and options["grant"]:
                raise CommandError(
                    "User can already forge messages for this realm.")
            elif not user.can_forge_sender and not options["grant"]:
                raise CommandError("User can't forge messages for this realm.")
            do_change_can_forge_sender(user, options["grant"])

            granted_text = "have" if options["grant"] else "not have"
            print(
                f"{user.delivery_email} changed to {granted_text} {options['new_role']} permission."
            )
        else:
            if user.can_create_users and options["grant"]:
                raise CommandError(
                    "User can already create users for this realm.")
            elif not user.can_create_users and not options["grant"]:
                raise CommandError("User can't create users for this realm.")
            do_change_can_create_users(user, options["grant"])
    def test_can_create_users(self) -> None:
        # Typically, when testing an API endpoint, we prefer a single
        # test covering both the happy path and common error paths.
        #
        # See https://zulip.readthedocs.io/en/latest/testing/philosophy.html#share-test-setup-code.
        iago = self.example_user("iago")
        self.login_user(iago)

        do_change_can_create_users(iago, False)
        valid_params = dict(
            email="*****@*****.**",
            password="******",
            full_name="Romeo Montague",
        )

        # We often use assert_json_error for negative tests.
        result = self.client_post("/json/users", valid_params)
        self.assert_json_error(result, "User not authorized for this query", 400)

        do_change_can_create_users(iago, True)
        incomplete_params = dict(
            full_name="Romeo Montague",
        )
        result = self.client_post("/json/users", incomplete_params)
        self.assert_json_error(result, "Missing 'email' argument", 400)

        # Verify that the original parameters were valid. Especially
        # for errors with generic error messages, this is important to
        # confirm that the original request with these parameters
        # failed because of incorrect permissions, and not because
        # valid_params weren't actually valid.
        result = self.client_post("/json/users", valid_params)
        self.assert_json_success(result)

        # Verify error handling when the user already exists.
        result = self.client_post("/json/users", valid_params)
        self.assert_json_error(result, "Email '*****@*****.**' already in use", 400)
    def test_client_post(self) -> None:
        # Here we're gonna test a POST call to /json/users, and it's
        # important that we not only check the payload, but we make
        # sure that the intended side effects actually happen.
        iago = self.example_user("iago")
        self.login_user(iago)

        realm = get_realm("zulip")
        self.assertEqual(realm.id, iago.realm_id)

        # Get our failing test first.
        self.assertRaises(
            UserProfile.DoesNotExist, lambda: get_user_by_delivery_email("*****@*****.**", realm)
        )

        # Before we can successfully post, we need to ensure
        # that Iago can create users.
        do_change_can_create_users(iago, True)

        params = dict(
            email="*****@*****.**",
            password="******",
            full_name="Romeo Montague",
        )

        # Use the Zulip wrapper.
        result = self.client_post("/json/users", params)

        # Once again we check that the HTTP request was successful.
        self.assert_json_success(result)
        content = orjson.loads(result.content)

        # Finally we test the side effect of the post.
        user_id = content["user_id"]
        romeo = get_user_by_delivery_email("*****@*****.**", realm)
        self.assertEqual(romeo.id, user_id)