Exemplo n.º 1
0
def mute_topic(user_profile: UserProfile, stream_name: str,
               topic_name: str) -> HttpResponse:
    (stream, recipient, sub) = access_stream_by_name(user_profile, stream_name)

    if topic_is_muted(user_profile, stream.id, topic_name):
        return json_error(_("Topic already muted"))

    do_mute_topic(user_profile, stream, recipient, topic_name)
    return json_success()
Exemplo n.º 2
0
def mute_topic(user_profile: UserProfile, stream_id: Optional[int],
               stream_name: Optional[str], topic_name: str) -> HttpResponse:
    if stream_name is not None:
        (stream, recipient,
         sub) = access_stream_by_name(user_profile, stream_name)
    else:
        assert stream_id is not None
        (stream, recipient, sub) = access_stream_by_id(user_profile, stream_id)

    if topic_is_muted(user_profile, stream.id, topic_name):
        return json_error(_("Topic already muted"))

    do_mute_topic(user_profile, stream, recipient, topic_name)
    return json_success()
Exemplo n.º 3
0
def mute_topic(user_profile: UserProfile,
               stream_id: Optional[int],
               stream_name: Optional[str],
               topic_name: str) -> HttpResponse:
    if stream_name is not None:
        (stream, recipient, sub) = access_stream_by_name(user_profile, stream_name)
    else:
        assert stream_id is not None
        (stream, recipient, sub) = access_stream_by_id(user_profile, stream_id)

    if topic_is_muted(user_profile, stream.id, topic_name):
        return json_error(_("Topic already muted"))

    do_mute_topic(user_profile, stream, recipient, topic_name)
    return json_success()
Exemplo n.º 4
0
def mute_topic(
    user_profile: UserProfile,
    stream_id: Optional[int],
    stream_name: Optional[str],
    topic_name: str,
    date_muted: datetime.datetime,
) -> HttpResponse:
    if stream_name is not None:
        (stream, sub) = access_stream_by_name(user_profile, stream_name)
    else:
        assert stream_id is not None
        (stream, sub) = access_stream_by_id(user_profile, stream_id)

    if topic_is_muted(user_profile, stream.id, topic_name):
        raise JsonableError(_("Topic already muted"))

    do_mute_topic(user_profile, stream, topic_name, date_muted)
    return json_success()
Exemplo n.º 5
0
def mute_topic(
    user_profile: UserProfile,
    stream_id: Optional[int],
    stream_name: Optional[str],
    topic_name: str,
    date_muted: datetime.datetime,
) -> None:
    if stream_name is not None:
        (stream, sub) = access_stream_by_name(user_profile, stream_name)
    else:
        assert stream_id is not None
        (stream, sub) = access_stream_by_id(user_profile, stream_id)

    if topic_is_muted(user_profile, stream.id, topic_name):
        raise JsonableError(_("Topic already muted"))

    try:
        do_mute_topic(user_profile, stream, topic_name, date_muted)
    except IntegrityError:
        raise JsonableError(_("Topic already muted"))
Exemplo n.º 6
0
    def test_end_to_end_missedmessage_hook(self) -> None:
        """Tests what arguments missedmessage_hook passes into maybe_enqueue_notifications.
        Combined with the previous test, this ensures that the missedmessage_hook is correct"""
        user_profile = self.example_user('hamlet')
        email = user_profile.email
        self.login(email)

        def change_subscription_properties(
                user_profile: UserProfile, stream: Stream, sub: Subscription,
                properties: Dict[str, bool]) -> None:
            for property_name, value in properties.items():
                do_change_subscription_property(user_profile, sub, stream,
                                                property_name, value)

        result = self.tornado_call(
            get_events, user_profile, {
                "apply_markdown": ujson.dumps(True),
                "client_gravatar": ujson.dumps(True),
                "event_types": ujson.dumps(["message"]),
                "user_client": "website",
                "dont_block": ujson.dumps(True),
            })
        self.assert_json_success(result)
        queue_id = ujson.loads(result.content)["queue_id"]
        client_descriptor = get_client_descriptor(queue_id)

        with mock.patch(
                "zerver.tornado.event_queue.maybe_enqueue_notifications"
        ) as mock_enqueue:
            # To test the missed_message hook, we first need to send a message
            msg_id = self.send_stream_message(self.example_email("iago"),
                                              "Denmark")

            # Verify that nothing happens if you call it as not the
            # "last client descriptor", in which case the function
            # short-circuits, since the `missedmessage_hook` handler
            # for garbage-collection is only for the user's last queue.
            missedmessage_hook(user_profile.id, client_descriptor, False)
            mock_enqueue.assert_not_called()

            # Now verify that we called the appropriate enqueue function
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list,
                             (user_profile.id, msg_id, False, False, False,
                              False, "Denmark", False, True, {
                                  'email_notified': False,
                                  'push_notified': False
                              }))

        # Clear the event queue, before repeating with a private message
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_personal_message(self.example_email("iago"), email)
        with mock.patch(
                "zerver.tornado.event_queue.maybe_enqueue_notifications"
        ) as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list, (user_profile.id, msg_id, True, False,
                                         False, False, None, False, True, {
                                             'email_notified': True,
                                             'push_notified': True
                                         }))

        # Clear the event queue, now repeat with a mention
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            self.example_email("iago"),
            "Denmark",
            content="@**King Hamlet** what's up?")
        with mock.patch(
                "zerver.tornado.event_queue.maybe_enqueue_notifications"
        ) as mock_enqueue:
            # Clear the event queue, before repeating with a private message
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list,
                             (user_profile.id, msg_id, False, True, False,
                              False, "Denmark", False, True, {
                                  'email_notified': True,
                                  'push_notified': True
                              }))

        stream = get_stream("Denmark", user_profile.realm)
        sub = Subscription.objects.get(user_profile=user_profile,
                                       recipient__type=Recipient.STREAM,
                                       recipient__type_id=stream.id)

        # Clear the event queue, now repeat with stream message with stream_push_notify
        change_subscription_properties(user_profile, stream, sub,
                                       {'push_notifications': True})
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(self.example_email("iago"),
                                          "Denmark",
                                          content="what's up everyone?")
        with mock.patch(
                "zerver.tornado.event_queue.maybe_enqueue_notifications"
        ) as mock_enqueue:
            # Clear the event queue, before repeating with a private message
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list, (user_profile.id, msg_id, False, False,
                                         True, False, "Denmark", False, True, {
                                             'email_notified': False,
                                             'push_notified': False
                                         }))

        # Clear the event queue, now repeat with stream message with stream_email_notify
        change_subscription_properties(user_profile, stream, sub, {
            'push_notifications': False,
            'email_notifications': True
        })
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(self.example_email("iago"),
                                          "Denmark",
                                          content="what's up everyone?")
        with mock.patch(
                "zerver.tornado.event_queue.maybe_enqueue_notifications"
        ) as mock_enqueue:
            # Clear the event queue, before repeating with a private message
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list, (user_profile.id, msg_id, False, False,
                                         False, True, "Denmark", False, True, {
                                             'email_notified': False,
                                             'push_notified': False
                                         }))

        # Clear the event queue, now repeat with stream message with stream_push_notify
        # on a muted topic, which we should not push notify for
        change_subscription_properties(user_profile, stream, sub, {
            'push_notifications': True,
            'email_notifications': False
        })
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        do_mute_topic(user_profile, stream, sub.recipient, "mutingtest")
        msg_id = self.send_stream_message(self.example_email("iago"),
                                          "Denmark",
                                          content="what's up everyone?",
                                          topic_name="mutingtest")
        with mock.patch(
                "zerver.tornado.event_queue.maybe_enqueue_notifications"
        ) as mock_enqueue:
            # Clear the event queue, before repeating with a private message
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list,
                             (user_profile.id, msg_id, False, False, False,
                              False, "Denmark", False, True, {
                                  'email_notified': False,
                                  'push_notified': False
                              }))

        # Clear the event queue, now repeat with stream message with stream_email_notify
        # on a muted stream, which we should not email notify for
        change_subscription_properties(user_profile, stream, sub, {
            'push_notifications': False,
            'email_notifications': True
        })
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        change_subscription_properties(user_profile, stream, sub,
                                       {'in_home_view': False})
        msg_id = self.send_stream_message(self.example_email("iago"),
                                          "Denmark",
                                          content="what's up everyone?")
        with mock.patch(
                "zerver.tornado.event_queue.maybe_enqueue_notifications"
        ) as mock_enqueue:
            # Clear the event queue, before repeating with a private message
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list,
                             (user_profile.id, msg_id, False, False, False,
                              False, "Denmark", False, True, {
                                  'email_notified': False,
                                  'push_notified': False
                              }))

        # Clean up the state we just changed (not necessary unless we add more test code below)
        change_subscription_properties(user_profile, stream, sub, {
            'push_notifications': True,
            'in_home_view': True
        })
Exemplo n.º 7
0
    def test_end_to_end_missedmessage_hook(self) -> None:
        """Tests what arguments missedmessage_hook passes into maybe_enqueue_notifications.
        Combined with the previous test, this ensures that the missedmessage_hook is correct"""
        user_profile = self.example_user("hamlet")
        cordelia = self.example_user("cordelia")

        user_profile.enable_online_push_notifications = False
        user_profile.save()

        iago = self.example_user("iago")

        # Fetch the Denmark stream for testing
        stream = get_stream("Denmark", user_profile.realm)
        sub = Subscription.objects.get(
            user_profile=user_profile,
            recipient__type=Recipient.STREAM,
            recipient__type_id=stream.id,
        )

        self.login_user(user_profile)

        def change_subscription_properties(
            user_profile: UserProfile,
            stream: Stream,
            sub: Subscription,
            properties: Dict[str, bool],
        ) -> None:
            for property_name, value in properties.items():
                do_change_subscription_property(
                    user_profile, sub, stream, property_name, value, acting_user=None
                )

        def allocate_event_queue() -> ClientDescriptor:
            result = self.tornado_call(
                get_events,
                user_profile,
                {
                    "apply_markdown": orjson.dumps(True).decode(),
                    "client_gravatar": orjson.dumps(True).decode(),
                    "event_types": orjson.dumps(["message"]).decode(),
                    "user_client": "website",
                    "dont_block": orjson.dumps(True).decode(),
                },
            )
            self.assert_json_success(result)
            queue_id = orjson.loads(result.content)["queue_id"]
            return get_client_descriptor(queue_id)

        def destroy_event_queue(queue_id: str) -> None:
            result = self.tornado_call(cleanup_event_queue, user_profile, {"queue_id": queue_id})
            self.assert_json_success(result)

        def assert_maybe_enqueue_notifications_call_args(
            args_dict: Collection[Any],
            message_id: int,
            **kwargs: Any,
        ) -> None:
            expected_args_dict = self.get_maybe_enqueue_notifications_parameters(
                user_id=user_profile.id,
                acting_user_id=iago.id,
                message_id=message_id,
                **kwargs,
            )
            self.assertEqual(args_dict, expected_args_dict)

        client_descriptor = allocate_event_queue()
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            # To test the missed_message hook, we first need to send a message
            msg_id = self.send_stream_message(iago, "Denmark")

            # Verify that nothing happens if you call it as not the
            # "last client descriptor", in which case the function
            # short-circuits, since the `missedmessage_hook` handler
            # for garbage-collection is only for the user's last queue.
            missedmessage_hook(user_profile.id, client_descriptor, False)
            mock_enqueue.assert_not_called()

            # Now verify that we called the appropriate enqueue function
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                already_notified={"email_notified": False, "push_notified": False},
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with a private message; this should trigger notifications
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_personal_message(iago, user_profile)
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                pm_email_notify=True,
                pm_push_notify=True,
                already_notified={"email_notified": True, "push_notified": True},
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # If `enable_offline_email_notifications` is disabled, email otifications shouldn't
        # be sent even for PMs
        user_profile.enable_offline_email_notifications = False
        user_profile.save()
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_personal_message(iago, user_profile)
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                pm_email_notify=False,
                pm_push_notify=True,
                already_notified={"email_notified": False, "push_notified": True},
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        user_profile.enable_offline_email_notifications = True
        user_profile.save()

        # Test the hook with a mention; this should trigger notifications
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            self.example_user("iago"), "Denmark", content="@**King Hamlet** what's up?"
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                mention_push_notify=True,
                mention_email_notify=True,
                already_notified={"email_notified": True, "push_notified": True},
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # If `enable_offline_push_notifications` is disabled, push otifications shouldn't
        # be sent even for mentions
        user_profile.enable_offline_push_notifications = False
        user_profile.save()
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_personal_message(iago, user_profile)
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                pm_email_notify=True,
                pm_push_notify=False,
                already_notified={"email_notified": True, "push_notified": False},
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        user_profile.enable_offline_push_notifications = True
        user_profile.save()

        # Test the hook with a wildcard mention; this should trigger notifications
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(iago, "Denmark", content="@**all** what's up?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                wildcard_mention_email_notify=True,
                wildcard_mention_push_notify=True,
                already_notified={"email_notified": True, "push_notified": True},
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Wildcard mentions in muted streams don't notify.
        change_subscription_properties(user_profile, stream, sub, {"is_muted": True})
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(iago, "Denmark", content="@**all** what's up?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                wildcard_mention_email_notify=False,
                wildcard_mention_push_notify=False,
                message_id=msg_id,
                already_notified={"email_notified": False, "push_notified": False},
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        change_subscription_properties(user_profile, stream, sub, {"is_muted": False})

        # With wildcard_mentions_notify=False, we treat the user as not mentioned.
        user_profile.wildcard_mentions_notify = False
        user_profile.save()
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(iago, "Denmark", content="@**all** what's up?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                wildcard_mention_email_notify=False,
                wildcard_mention_push_notify=False,
                already_notified={"email_notified": False, "push_notified": False},
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        user_profile.wildcard_mentions_notify = True
        user_profile.save()

        # If wildcard_mentions_notify=True for a stream and False for a user, we treat the user
        # as mentioned for that stream.
        user_profile.wildcard_mentions_notify = False
        sub.wildcard_mentions_notify = True
        user_profile.save()
        sub.save()
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(iago, "Denmark", content="@**all** what's up?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                wildcard_mention_email_notify=True,
                wildcard_mention_push_notify=True,
                already_notified={"email_notified": True, "push_notified": True},
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        user_profile.wildcard_mentions_notify = True
        sub.wildcard_mentions_notify = None
        user_profile.save()
        sub.save()

        # If notifications for personal mentions themselves have been turned off,
        # even turning on `wildcard_mentions_notify` should not send notifications
        user_profile.enable_offline_email_notifications = False
        user_profile.wildcard_mentions_notify = True
        user_profile.save()
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(iago, "Denmark", content="@**all** what's up?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            # We've turned off email notifications for personal mentions, but push notifications
            # for personal mentions are still on.
            # Because `wildcard_mentions_notify` is True, a message with `@all` should follow the
            # personal mention settings
            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                wildcard_mention_email_notify=False,
                wildcard_mention_push_notify=True,
                already_notified={"email_notified": False, "push_notified": True},
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        user_profile.enable_offline_email_notifications = True
        user_profile.wildcard_mentions_notify = True
        user_profile.save()

        # Test with a user group mention
        hamlet_and_cordelia = create_user_group(
            "hamlet_and_cordelia", [user_profile, cordelia], cordelia.realm
        )
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            iago, "Denmark", content="@*hamlet_and_cordelia* what's up?"
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                mention_push_notify=True,
                mention_email_notify=True,
                mentioned_user_group_id=hamlet_and_cordelia.id,
                already_notified={"email_notified": True, "push_notified": True},
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        remove_user_from_user_group(user_profile, hamlet_and_cordelia)
        remove_user_from_user_group(cordelia, hamlet_and_cordelia)

        # Test the hook with a stream message with stream_push_notify
        change_subscription_properties(user_profile, stream, sub, {"push_notifications": True})
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(iago, "Denmark", content="what's up everyone?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                stream_push_notify=True,
                stream_email_notify=False,
                already_notified={"email_notified": False, "push_notified": True},
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with a stream message with stream_email_notify
        client_descriptor = allocate_event_queue()
        change_subscription_properties(
            user_profile, stream, sub, {"push_notifications": False, "email_notifications": True}
        )
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(iago, "Denmark", content="what's up everyone?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                stream_push_notify=False,
                stream_email_notify=True,
                already_notified={"email_notified": True, "push_notified": False},
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with stream message with stream_push_notify on
        # a muted topic, which we should not push notify for
        client_descriptor = allocate_event_queue()
        change_subscription_properties(
            user_profile, stream, sub, {"push_notifications": True, "email_notifications": False}
        )

        self.assertTrue(client_descriptor.event_queue.empty())
        do_mute_topic(user_profile, stream, "mutingtest")
        msg_id = self.send_stream_message(
            iago,
            "Denmark",
            content="what's up everyone?",
            topic_name="mutingtest",
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                already_notified={"email_notified": False, "push_notified": False},
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with stream message with stream_email_notify on
        # a muted stream, which we should not push notify for
        client_descriptor = allocate_event_queue()
        change_subscription_properties(
            user_profile, stream, sub, {"push_notifications": False, "email_notifications": True}
        )

        self.assertTrue(client_descriptor.event_queue.empty())
        change_subscription_properties(user_profile, stream, sub, {"is_muted": True})
        msg_id = self.send_stream_message(iago, "Denmark", content="what's up everyone?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                already_notified={"email_notified": False, "push_notified": False},
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Clean up the state we just changed (not necessary unless we add more test code below)
        change_subscription_properties(
            user_profile, stream, sub, {"push_notifications": True, "is_muted": False}
        )

        # Test the hook when the sender has been muted
        result = self.api_post(user_profile, f"/api/v1/users/me/muted_users/{iago.id}")
        self.assert_json_success(result)
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_personal_message(iago, user_profile)
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_dict = mock_enqueue.call_args_list[0][1]

            assert_maybe_enqueue_notifications_call_args(
                args_dict=args_dict,
                message_id=msg_id,
                sender_is_muted=True,
                pm_email_notify=True,
                pm_push_notify=True,
                already_notified={"email_notified": False, "push_notified": False},
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        result = self.api_delete(user_profile, f"/api/v1/users/me/muted_users/{iago.id}")
        self.assert_json_success(result)
Exemplo n.º 8
0
    def test_end_to_end_missedmessage_hook(self):
        # type: () -> None
        """Tests what arguments missedmessage_hook passes into maybe_enqueue_notifications.
        Combined with the previous test, this ensures that the missedmessage_hook is correct"""
        user_profile = self.example_user('hamlet')
        email = user_profile.email
        self.login(email)

        result = self.tornado_call(get_events_backend, user_profile,
                                   {"apply_markdown": ujson.dumps(True),
                                    "event_types": ujson.dumps(["message"]),
                                    "user_client": "website",
                                    "dont_block": ujson.dumps(True),
                                    })
        self.assert_json_success(result)
        queue_id = ujson.loads(result.content)["queue_id"]
        client_descriptor = get_client_descriptor(queue_id)

        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            # To test the missed_message hook, we first need to send a message
            msg_id = self.send_stream_message(self.example_email("iago"), "Denmark")

            # Verify that nothing happens if you call it as not the
            # "last client descriptor", in which case the function
            # short-circuits, since the `missedmessage_hook` handler
            # for garbage-collection is only for the user's last queue.
            missedmessage_hook(user_profile.id, client_descriptor, False)
            mock_enqueue.assert_not_called()

            # Now verify that we called the appropriate enqueue function
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list, (user_profile.id, msg_id, False, False, False,
                                         "Denmark", False, True,
                                         {'email_notified': False, 'push_notified': False}))

        # Clear the event queue, before repeating with a private message
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_personal_message(self.example_email("iago"), email)
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list, (user_profile.id, msg_id, True, False,
                                         False, None, False, True,
                                         {'email_notified': True, 'push_notified': True}))

        # Clear the event queue, now repeat with a mention
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(self.example_email("iago"), "Denmark",
                                          content="@**King Hamlet** what's up?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            # Clear the event queue, before repeating with a private message
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list, (user_profile.id, msg_id, False, True,
                                         False, "Denmark", False, True,
                                         {'email_notified': True, 'push_notified': True}))

        # Clear the event queue, now repeat with stream message with stream_push_notify
        stream = get_stream("Denmark", user_profile.realm)
        sub = Subscription.objects.get(user_profile=user_profile, recipient__type=Recipient.STREAM,
                                       recipient__type_id=stream.id)
        sub.push_notifications = True
        sub.save()
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(self.example_email("iago"), "Denmark",
                                          content="what's up everyone?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            # Clear the event queue, before repeating with a private message
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list, (user_profile.id, msg_id, False, False,
                                         True, "Denmark", False, True,
                                         {'email_notified': False, 'push_notified': False}))

        # Clear the event queue, now repeat with stream message with stream_push_notify
        # on a muted topic, which we should not push notify for
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        do_mute_topic(user_profile, stream, sub.recipient, "mutingtest")
        msg_id = self.send_stream_message(self.example_email("iago"), "Denmark",
                                          content="what's up everyone?", topic_name="mutingtest")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            # Clear the event queue, before repeating with a private message
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list, (user_profile.id, msg_id, False, False,
                                         False, "Denmark", False, True,
                                         {'email_notified': False, 'push_notified': False}))

        # Clear the event queue, now repeat with stream message with stream_push_notify
        # on a muted stream, which we should not push notify for
        client_descriptor.event_queue.pop()
        self.assertTrue(client_descriptor.event_queue.empty())
        sub.in_home_view = False
        sub.save()
        msg_id = self.send_stream_message(self.example_email("iago"), "Denmark",
                                          content="what's up everyone?")
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            # Clear the event queue, before repeating with a private message
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(args_list, (user_profile.id, msg_id, False, False,
                                         False, "Denmark", False, True,
                                         {'email_notified': False, 'push_notified': False}))

        # Clean up the state we just changed (not necessary unless we add more test code below)
        sub.push_notifications = True
        sub.in_home_view = True
        sub.save()
Exemplo n.º 9
0
    def test_end_to_end_missedmessage_hook(self) -> None:
        """Tests what arguments missedmessage_hook passes into maybe_enqueue_notifications.
        Combined with the previous test, this ensures that the missedmessage_hook is correct"""
        user_profile = self.example_user("hamlet")

        user_profile.enable_online_push_notifications = False
        user_profile.save()

        # Fetch the Denmark stream for testing
        stream = get_stream("Denmark", user_profile.realm)
        sub = Subscription.objects.get(
            user_profile=user_profile,
            recipient__type=Recipient.STREAM,
            recipient__type_id=stream.id,
        )

        self.login_user(user_profile)

        def change_subscription_properties(
            user_profile: UserProfile,
            stream: Stream,
            sub: Subscription,
            properties: Dict[str, bool],
        ) -> None:
            for property_name, value in properties.items():
                do_change_subscription_property(
                    user_profile, sub, stream, property_name, value, acting_user=None
                )

        def allocate_event_queue() -> ClientDescriptor:
            result = self.tornado_call(
                get_events,
                user_profile,
                {
                    "apply_markdown": orjson.dumps(True).decode(),
                    "client_gravatar": orjson.dumps(True).decode(),
                    "event_types": orjson.dumps(["message"]).decode(),
                    "user_client": "website",
                    "dont_block": orjson.dumps(True).decode(),
                },
            )
            self.assert_json_success(result)
            queue_id = orjson.loads(result.content)["queue_id"]
            return get_client_descriptor(queue_id)

        def destroy_event_queue(queue_id: str) -> None:
            result = self.tornado_call(cleanup_event_queue, user_profile, {"queue_id": queue_id})
            self.assert_json_success(result)

        client_descriptor = allocate_event_queue()
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            # To test the missed_message hook, we first need to send a message
            msg_id = self.send_stream_message(self.example_user("iago"), "Denmark")

            # Verify that nothing happens if you call it as not the
            # "last client descriptor", in which case the function
            # short-circuits, since the `missedmessage_hook` handler
            # for garbage-collection is only for the user's last queue.
            missedmessage_hook(user_profile.id, client_descriptor, False)
            mock_enqueue.assert_not_called()

            # Now verify that we called the appropriate enqueue function
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    False,
                    False,
                    False,
                    False,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": False, "push_notified": False},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with a private message; this should trigger notifications
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_personal_message(self.example_user("iago"), user_profile)
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    True,
                    False,
                    False,
                    False,
                    False,
                    None,
                    False,
                    True,
                    {"email_notified": True, "push_notified": True},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with a mention; this should trigger notifications
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            self.example_user("iago"), "Denmark", content="@**King Hamlet** what's up?"
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    True,
                    False,
                    False,
                    False,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": True, "push_notified": True},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with a wildcard mention; this should trigger notifications
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            self.example_user("iago"), "Denmark", content="@**all** what's up?"
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    False,
                    True,
                    False,
                    False,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": True, "push_notified": True},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with a wildcard mention sent by the user
        # themself using a human client; should not notify.
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            self.example_user("hamlet"),
            "Denmark",
            content="@**all** what's up?",
            sending_client_name="website",
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    False,
                    False,
                    False,
                    False,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": False, "push_notified": False},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Wildcard mentions in muted streams don't notify.
        change_subscription_properties(user_profile, stream, sub, {"is_muted": True})
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            self.example_user("iago"), "Denmark", content="@**all** what's up?"
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    False,
                    False,
                    False,
                    False,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": False, "push_notified": False},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        change_subscription_properties(user_profile, stream, sub, {"is_muted": False})

        # With wildcard_mentions_notify=False, we treat the user as not mentioned.
        user_profile.wildcard_mentions_notify = False
        user_profile.save()
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            self.example_user("iago"), "Denmark", content="@**all** what's up?"
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    False,
                    False,
                    False,
                    False,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": False, "push_notified": False},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        user_profile.wildcard_mentions_notify = True
        user_profile.save()

        # If wildcard_mentions_notify=True for a stream and False for a user, we treat the user
        # as mentioned for that stream.
        user_profile.wildcard_mentions_notify = False
        sub.wildcard_mentions_notify = True
        user_profile.save()
        sub.save()
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            self.example_user("iago"), "Denmark", content="@**all** what's up?"
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    False,
                    True,
                    False,
                    False,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": True, "push_notified": True},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)
        user_profile.wildcard_mentions_notify = True
        sub.wildcard_mentions_notify = None
        user_profile.save()
        sub.save()

        # Test the hook with a stream message with stream_push_notify
        change_subscription_properties(user_profile, stream, sub, {"push_notifications": True})
        client_descriptor = allocate_event_queue()
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            self.example_user("iago"), "Denmark", content="what's up everyone?"
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    False,
                    False,
                    True,
                    False,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": False, "push_notified": False},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with a stream message with stream_email_notify
        client_descriptor = allocate_event_queue()
        change_subscription_properties(
            user_profile, stream, sub, {"push_notifications": False, "email_notifications": True}
        )
        self.assertTrue(client_descriptor.event_queue.empty())
        msg_id = self.send_stream_message(
            self.example_user("iago"), "Denmark", content="what's up everyone?"
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    False,
                    False,
                    False,
                    True,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": False, "push_notified": False},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with stream message with stream_push_notify on
        # a muted topic, which we should not push notify for
        client_descriptor = allocate_event_queue()
        change_subscription_properties(
            user_profile, stream, sub, {"push_notifications": True, "email_notifications": False}
        )

        self.assertTrue(client_descriptor.event_queue.empty())
        do_mute_topic(user_profile, stream, "mutingtest")
        msg_id = self.send_stream_message(
            self.example_user("iago"),
            "Denmark",
            content="what's up everyone?",
            topic_name="mutingtest",
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    False,
                    False,
                    False,
                    False,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": False, "push_notified": False},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Test the hook with stream message with stream_email_notify on
        # a muted stream, which we should not push notify for
        client_descriptor = allocate_event_queue()
        change_subscription_properties(
            user_profile, stream, sub, {"push_notifications": False, "email_notifications": True}
        )

        self.assertTrue(client_descriptor.event_queue.empty())
        change_subscription_properties(user_profile, stream, sub, {"is_muted": True})
        msg_id = self.send_stream_message(
            self.example_user("iago"), "Denmark", content="what's up everyone?"
        )
        with mock.patch("zerver.tornado.event_queue.maybe_enqueue_notifications") as mock_enqueue:
            missedmessage_hook(user_profile.id, client_descriptor, True)
            mock_enqueue.assert_called_once()
            args_list = mock_enqueue.call_args_list[0][0]

            self.assertEqual(
                args_list,
                (
                    user_profile.id,
                    msg_id,
                    False,
                    False,
                    False,
                    False,
                    False,
                    "Denmark",
                    False,
                    True,
                    {"email_notified": False, "push_notified": False},
                ),
            )
        destroy_event_queue(client_descriptor.event_queue.id)

        # Clean up the state we just changed (not necessary unless we add more test code below)
        change_subscription_properties(
            user_profile, stream, sub, {"push_notifications": True, "is_muted": False}
        )