Exemple #1
0
    def test_unread_count_user_soft_deactivation(self) -> None:
        # In this test we make sure if a soft deactivated user had unread
        # messages before deactivation they remain same way after activation.
        long_term_idle_user = self.example_user('hamlet')
        self.login_user(long_term_idle_user)
        message = 'Test Message 1'
        self.send_test_message(message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 1)
        query_count = len(queries)
        user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(user_msg_list[-1].content, message)
        self.logout()

        with self.assertLogs(logger_string, level='INFO') as info_log:
            do_soft_deactivate_users([long_term_idle_user])
        self.assertEqual(info_log.output, [
            f'INFO:{logger_string}:Soft deactivated user {long_term_idle_user.id}',
            f'INFO:{logger_string}:Soft-deactivated batch of 1 users; 0 remain to process'
        ])

        self.login_user(long_term_idle_user)
        message = 'Test Message 2'
        self.send_test_message(message)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertNotEqual(idle_user_msg_list[-1].content, message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 2)
        # Test here for query count to be at least 5 greater than previous count
        # This will assure indirectly that add_missing_messages() was called.
        self.assertGreaterEqual(len(queries) - query_count, 5)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)
Exemple #2
0
    def test_multiple_user_soft_deactivations(self) -> None:
        long_term_idle_user = self.example_user('hamlet')
        # We are sending this message to ensure that long_term_idle_user has
        # at least one UserMessage row.
        self.send_test_message('Testing', sender_name='hamlet')
        with self.assertLogs(logger_string, level='INFO') as info_log:
            do_soft_deactivate_users([long_term_idle_user])
        self.assertEqual(info_log.output, [
            f'INFO:{logger_string}:Soft deactivated user {long_term_idle_user.id}',
            f'INFO:{logger_string}:Soft-deactivated batch of 1 users; 0 remain to process'
        ])

        message = 'Test Message 1'
        self.send_test_message(message)
        self.login_user(long_term_idle_user)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 2)
        query_count = len(queries)
        long_term_idle_user.refresh_from_db()
        self.assertFalse(long_term_idle_user.long_term_idle)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)

        message = 'Test Message 2'
        self.send_test_message(message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 3)
        # Test here for query count to be at least 5 less than previous count.
        # This will assure add_missing_messages() isn't repeatedly called.
        self.assertGreaterEqual(query_count - len(queries), 5)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)
        self.logout()

        with self.assertLogs(logger_string, level='INFO') as info_log:
            do_soft_deactivate_users([long_term_idle_user])
        self.assertEqual(info_log.output, [
            f'INFO:{logger_string}:Soft deactivated user {long_term_idle_user.id}',
            f'INFO:{logger_string}:Soft-deactivated batch of 1 users; 0 remain to process'
        ])

        message = 'Test Message 3'
        self.send_test_message(message)
        self.login_user(long_term_idle_user)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 4)
        query_count = len(queries)
        long_term_idle_user.refresh_from_db()
        self.assertFalse(long_term_idle_user.long_term_idle)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)

        message = 'Test Message 4'
        self.send_test_message(message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 5)
        self.assertGreaterEqual(query_count - len(queries), 5)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)
        self.logout()
    def test_do_catch_up_users(self) -> None:
        stream = 'Verona'
        hamlet = self.example_user('hamlet')
        users = [
            self.example_user('iago'),
            self.example_user('cordelia'),
        ]
        all_users = [*users, hamlet]
        for user in all_users:
            self.subscribe(user, stream)

        with mock.patch('logging.info'):
            do_soft_deactivate_users(users)
        for user in users:
            self.assertTrue(user.long_term_idle)

        message_id = self.send_stream_message(hamlet, stream, 'Hello world!')
        already_received = UserMessage.objects.filter(message_id=message_id).count()
        with mock.patch('logging.info'):
            do_catch_up_soft_deactivated_users(users)
        catch_up_received = UserMessage.objects.filter(message_id=message_id).count()
        self.assertEqual(already_received + len(users), catch_up_received)

        for user in users:
            user.refresh_from_db()
            self.assertTrue(user.long_term_idle)
            self.assertEqual(user.last_active_message_id, message_id)
    def test_do_soft_deactivate_users(self) -> None:
        users = [
            self.example_user("hamlet"),
            self.example_user("iago"),
            self.example_user("cordelia"),
        ]
        for user in users:
            self.assertFalse(user.long_term_idle)

        # We are sending this message to ensure that users have at least
        # one UserMessage row.
        self.send_huddle_message(users[0], users)

        with self.assertLogs(logger_string, level="INFO") as m:
            do_soft_deactivate_users(users)

        log_output = []
        for user in users:
            log_output.append(
                f"INFO:{logger_string}:Soft deactivated user {user.id}")
        log_output.append(
            f"INFO:{logger_string}:Soft-deactivated batch of {len(users[:100])} users; {len(users[100:])} remain to process"
        )

        self.assertEqual(m.output, log_output)

        for user in users:
            user.refresh_from_db()
            self.assertTrue(user.long_term_idle)
Exemple #5
0
    def test_unread_count_user_soft_deactivation(self) -> None:
        # In this test we make sure if a soft deactivated user had unread
        # messages before deactivation they remain same way after activation.
        long_term_idle_user = self.example_user('hamlet')
        self.login(long_term_idle_user.email)
        message = 'Test Message 1'
        self.send_test_message(message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 1)
        query_count = len(queries)
        user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(user_msg_list[-1].content, message)
        self.logout()

        do_soft_deactivate_users([long_term_idle_user])

        self.login(long_term_idle_user.email)
        message = 'Test Message 2'
        self.send_test_message(message)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertNotEqual(idle_user_msg_list[-1].content, message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 2)
        # Test here for query count to be at least 5 greater than previous count
        # This will assure indirectly that add_missing_messages() was called.
        self.assertGreaterEqual(len(queries) - query_count, 5)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)
Exemple #6
0
    def test_unread_count_user_soft_deactivation(self) -> None:
        # In this test we make sure if a soft deactivated user had unread
        # messages before deactivation they remain same way after activation.
        long_term_idle_user = self.example_user('hamlet')
        self.login(long_term_idle_user.email)
        message = 'Test Message 1'
        self.send_test_message(message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 1)
        query_count = len(queries)
        user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(user_msg_list[-1].content, message)
        self.logout()

        do_soft_deactivate_users([long_term_idle_user])

        self.login(long_term_idle_user.email)
        message = 'Test Message 2'
        self.send_test_message(message)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertNotEqual(idle_user_msg_list[-1].content, message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 2)
        # Test here for query count to be at least 5 greater than previous count
        # This will assure indirectly that add_missing_messages() was called.
        self.assertGreaterEqual(len(queries) - query_count, 5)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)
    def test_add_missing_messages_pagination(self) -> None:
        recipient_list  = [self.example_user("hamlet"), self.example_user("iago")]
        stream_name = 'Denmark'
        for user_profile in recipient_list:
            self.subscribe(user_profile, stream_name)

        sender = self.example_user('iago')
        long_term_idle_user = self.example_user('hamlet')
        self.send_stream_message(long_term_idle_user, stream_name)
        with self.assertLogs(level='INFO') as info_logs:
            do_soft_deactivate_users([long_term_idle_user])
        self.assertEqual(info_logs.output, [
            'INFO:root:Soft-deactivated batch of 1 users; 0 remain to process'
        ])

        num_new_messages = 5
        message_ids = []
        for _ in range(num_new_messages):
            message_id = self.send_stream_message(sender, stream_name)
            message_ids.append(message_id)

        idle_user_msg_list = get_user_messages(long_term_idle_user)
        idle_user_msg_count = len(idle_user_msg_list)
        with queries_captured() as queries:
            add_missing_messages(long_term_idle_user)
        self.assert_length(queries, 10)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(len(idle_user_msg_list), idle_user_msg_count + num_new_messages)
        long_term_idle_user.refresh_from_db()
        self.assertEqual(long_term_idle_user.last_active_message_id, message_ids[-1])
Exemple #8
0
    def test_multiple_user_soft_deactivations(self):
        # type: () -> None
        long_term_idle_user = self.example_user('hamlet')
        # We are sending this message to ensure that long_term_idle_user has
        # at least one UserMessage row.
        self.send_test_message('Testing', sender_name='hamlet')
        do_soft_deactivate_users([long_term_idle_user])

        message = 'Test Message 1'
        self.send_test_message(message)
        self.login(long_term_idle_user.email)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 2)
        query_count = len(queries)
        long_term_idle_user.refresh_from_db()
        self.assertFalse(long_term_idle_user.long_term_idle)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)

        message = 'Test Message 2'
        self.send_test_message(message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 3)
        # Test here for query count to be at least 5 less than previous count.
        # This will assure add_missing_messages() isn't repeatedly called.
        self.assertGreaterEqual(query_count - len(queries), 5)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)
        self.logout()

        do_soft_deactivate_users([long_term_idle_user])

        message = 'Test Message 3'
        self.send_test_message(message)
        self.login(long_term_idle_user.email)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 4)
        query_count = len(queries)
        long_term_idle_user.refresh_from_db()
        self.assertFalse(long_term_idle_user.long_term_idle)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)

        message = 'Test Message 4'
        self.send_test_message(message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 5)
        self.assertGreaterEqual(query_count - len(queries), 5)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)
        self.logout()
Exemple #9
0
    def test_multiple_user_soft_deactivations(self):
        # type: () -> None
        long_term_idle_user = self.example_user('hamlet')
        # We are sending this message to ensure that long_term_idle_user has
        # at least one UserMessage row.
        self.send_stream_message('Testing', sender_name='hamlet')
        do_soft_deactivate_users([long_term_idle_user])

        message = 'Test Message 1'
        self.send_stream_message(message)
        self.login(long_term_idle_user.email)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 2)
        query_count = len(queries)
        long_term_idle_user.refresh_from_db()
        self.assertFalse(long_term_idle_user.long_term_idle)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)

        message = 'Test Message 2'
        self.send_stream_message(message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 3)
        # Test here for query count to be at least 5 less than previous count.
        # This will assure add_missing_messages() isn't repeatedly called.
        self.assertGreaterEqual(query_count - len(queries), 5)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)
        self.logout()

        do_soft_deactivate_users([long_term_idle_user])

        message = 'Test Message 3'
        self.send_stream_message(message)
        self.login(long_term_idle_user.email)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 4)
        query_count = len(queries)
        long_term_idle_user.refresh_from_db()
        self.assertFalse(long_term_idle_user.long_term_idle)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)

        message = 'Test Message 4'
        self.send_stream_message(message)
        with queries_captured() as queries:
            self.assertEqual(self.soft_activate_and_get_unread_count(), 5)
        self.assertGreaterEqual(query_count - len(queries), 5)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(idle_user_msg_list[-1].content, message)
        self.logout()
    def test_reactivate_user_if_soft_deactivated(self) -> None:
        recipient_list = [
            self.example_user("hamlet"),
            self.example_user("iago")
        ]
        for user_profile in recipient_list:
            self.subscribe(user_profile, "Denmark")

        sender = self.example_user("iago")
        stream_name = "Denmark"
        topic_name = "foo"

        def last_realm_audit_log_entry(event_type: int) -> RealmAuditLog:
            return RealmAuditLog.objects.filter(
                event_type=event_type).order_by("-event_time")[0]

        long_term_idle_user = self.example_user("hamlet")
        # We are sending this message to ensure that long_term_idle_user has
        # at least one UserMessage row.
        self.send_stream_message(long_term_idle_user, stream_name)
        with self.assertLogs(logger_string, level="INFO") as info_logs:
            do_soft_deactivate_users([long_term_idle_user])
        self.assertEqual(
            info_logs.output,
            [
                f"INFO:{logger_string}:Soft deactivated user {long_term_idle_user.id}",
                f"INFO:{logger_string}:Soft-deactivated batch of 1 users; 0 remain to process",
            ],
        )

        message = "Test message 1"
        message_id = self.send_stream_message(sender, stream_name, message,
                                              topic_name)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        idle_user_msg_count = len(idle_user_msg_list)
        self.assertNotEqual(idle_user_msg_list[-1].content, message)
        with queries_captured() as queries:
            reactivate_user_if_soft_deactivated(long_term_idle_user)
        self.assert_length(queries, 8)
        self.assertFalse(long_term_idle_user.long_term_idle)
        self.assertEqual(
            last_realm_audit_log_entry(
                RealmAuditLog.USER_SOFT_ACTIVATED).modified_user,
            long_term_idle_user,
        )
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assert_length(idle_user_msg_list, idle_user_msg_count + 1)
        self.assertEqual(idle_user_msg_list[-1].content, message)
        long_term_idle_user.refresh_from_db()
        self.assertEqual(long_term_idle_user.last_active_message_id,
                         message_id)
    def handle(self, *args: Any, **options: str) -> None:
        if settings.STAGING:
            print('This is a Staging server. Suppressing management command.')
            sys.exit(0)

        realm = self.get_realm(options)
        user_emails = options['users']
        activate = options['activate']
        deactivate = options['deactivate']

        filter_kwargs = {}  # type: Dict[str, Realm]
        if realm is not None:
            filter_kwargs = dict(realm=realm)

        if activate:
            if not user_emails:
                print('You need to specify at least one user to use the activate option.')
                self.print_help("./manage.py", "soft_deactivate_users")
                sys.exit(1)

            users_to_activate = UserProfile.objects.filter(
                email__in=user_emails,
                **filter_kwargs
            )
            users_to_activate = list(users_to_activate)

            if len(users_to_activate) != len(user_emails):
                user_emails_found = [user.email for user in users_to_activate]
                for user in user_emails:
                    if user not in user_emails_found:
                        raise Exception('User with email %s was not found. Check if the email is correct.' % (user))

            users_activated = do_soft_activate_users(users_to_activate)
            logger.info('Soft Reactivated %d user(s)' % (len(users_activated)))
        elif deactivate:
            if user_emails:
                users_to_deactivate = UserProfile.objects.filter(
                    email__in=user_emails,
                    **filter_kwargs
                )
                users_to_deactivate = list(users_to_deactivate)

                if len(users_to_deactivate) != len(user_emails):
                    user_emails_found = [user.email for user in users_to_deactivate]
                    for user in user_emails:
                        if user not in user_emails_found:
                            raise Exception('User with email %s was not found. '
                                            'Check if the email is correct.' % (user,))
                print('Soft deactivating forcefully...')
            else:
                if realm is not None:
                    filter_kwargs = dict(user_profile__realm=realm)
                users_to_deactivate = get_users_for_soft_deactivation(int(options['inactive_for']), filter_kwargs)

            if users_to_deactivate:
                users_deactivated = do_soft_deactivate_users(users_to_deactivate)
                logger.info('Soft Deactivated %d user(s)' % (len(users_deactivated)))
        else:
            self.print_help("./manage.py", "soft_deactivate_users")
            sys.exit(1)
    def test_do_soft_activate_users(self) -> None:
        users = [
            self.example_user('hamlet'),
            self.example_user('iago'),
            self.example_user('cordelia'),
        ]
        self.send_huddle_message(users[0].email,
                                 [user.email for user in users])
        do_soft_deactivate_users(users)
        for user in users:
            self.assertTrue(user.long_term_idle)

        do_soft_activate_users(users)

        for user in users:
            user.refresh_from_db()
            self.assertFalse(user.long_term_idle)
    def test_do_catch_up_users(self) -> None:
        stream = "Verona"
        hamlet = self.example_user("hamlet")
        users = [
            self.example_user("iago"),
            self.example_user("cordelia"),
        ]
        all_users = [*users, hamlet]
        for user in all_users:
            self.subscribe(user, stream)

        with self.assertLogs(logger_string, level="INFO") as m:
            do_soft_deactivate_users(users)

        log_output = []
        for user in users:
            log_output.append(
                f"INFO:{logger_string}:Soft deactivated user {user.id}")
        log_output.append(
            f"INFO:{logger_string}:Soft-deactivated batch of {len(users[:100])} users; {len(users[100:])} remain to process"
        )

        self.assertEqual(m.output, log_output)

        for user in users:
            self.assertTrue(user.long_term_idle)

        message_id = self.send_stream_message(hamlet, stream, "Hello world!")
        already_received = UserMessage.objects.filter(
            message_id=message_id).count()

        with self.assertLogs(logger_string, level="INFO") as m:
            do_catch_up_soft_deactivated_users(users)
        self.assertEqual(m.output, [
            f"INFO:{logger_string}:Caught up {len(users)} soft-deactivated users"
        ])

        catch_up_received = UserMessage.objects.filter(
            message_id=message_id).count()
        self.assertEqual(already_received + len(users), catch_up_received)

        for user in users:
            user.refresh_from_db()
            self.assertTrue(user.long_term_idle)
            self.assertEqual(user.last_active_message_id, message_id)
    def test_do_soft_deactivate_users(self) -> None:
        users = [
            self.example_user('hamlet'),
            self.example_user('iago'),
            self.example_user('cordelia'),
        ]
        for user in users:
            self.assertFalse(user.long_term_idle)

        # We are sending this message to ensure that users have at least
        # one UserMessage row.
        self.send_huddle_message(users[0].email,
                                 [user.email for user in users])
        do_soft_deactivate_users(users)

        for user in users:
            user.refresh_from_db()
            self.assertTrue(user.long_term_idle)
    def test_do_soft_activate_users(self) -> None:
        users = [
            self.example_user('hamlet'),
            self.example_user('iago'),
            self.example_user('cordelia'),
        ]
        self.send_huddle_message(users[0], users)

        with mock.patch('logging.info'):
            do_soft_deactivate_users(users)
        for user in users:
            self.assertTrue(user.long_term_idle)

        with mock.patch('logging.info'):
            do_soft_activate_users(users)

        for user in users:
            user.refresh_from_db()
            self.assertFalse(user.long_term_idle)
    def test_reactivate_user_if_soft_deactivated(self) -> None:
        recipient_list = [
            self.example_user("hamlet"),
            self.example_user("iago")
        ]
        for user_profile in recipient_list:
            self.subscribe(user_profile, "Denmark")

        sender = self.example_user('iago')
        stream_name = 'Denmark'
        topic_name = 'foo'

        def last_realm_audit_log_entry(event_type: int) -> RealmAuditLog:
            return RealmAuditLog.objects.filter(
                event_type=event_type, ).order_by('-event_time')[0]

        long_term_idle_user = self.example_user('hamlet')
        # We are sending this message to ensure that long_term_idle_user has
        # at least one UserMessage row.
        self.send_stream_message(long_term_idle_user, stream_name)
        do_soft_deactivate_users([long_term_idle_user])

        message = 'Test Message 1'
        message_id = self.send_stream_message(sender, stream_name, message,
                                              topic_name)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        idle_user_msg_count = len(idle_user_msg_list)
        self.assertNotEqual(idle_user_msg_list[-1].content, message)
        with queries_captured() as queries:
            reactivate_user_if_soft_deactivated(long_term_idle_user)
        self.assert_length(queries, 8)
        self.assertFalse(long_term_idle_user.long_term_idle)
        self.assertEqual(
            last_realm_audit_log_entry(
                RealmAuditLog.USER_SOFT_ACTIVATED).modified_user,
            long_term_idle_user)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(len(idle_user_msg_list), idle_user_msg_count + 1)
        self.assertEqual(idle_user_msg_list[-1].content, message)
        long_term_idle_user.refresh_from_db()
        self.assertEqual(long_term_idle_user.last_active_message_id,
                         message_id)
    def test_do_soft_activate_users(self) -> None:
        users = [
            self.example_user('hamlet'),
            self.example_user('iago'),
            self.example_user('cordelia'),
        ]
        self.send_huddle_message(users[0], users)

        with self.assertLogs(logger_string, level="INFO") as m:
            do_soft_deactivate_users(users)

        log_output = []
        for user in users:
            log_output.append(
                f"INFO:{logger_string}:Soft Deactivated user {user.id}")
        log_output.append(
            f"INFO:{logger_string}:Soft-deactivated batch of {len(users[:100])} users; {len(users[100:])} remain to process"
        )

        self.assertEqual(m.output, log_output)

        for user in users:
            self.assertTrue(user.long_term_idle)

        with self.assertLogs(logger_string, level="INFO") as m:
            do_soft_activate_users(users)

        log_output = []
        for user in users:
            log_output.append(
                f"INFO:{logger_string}:Soft Reactivated user {user.id}")

        self.assertEqual(m.output, log_output)

        for user in users:
            user.refresh_from_db()
            self.assertFalse(user.long_term_idle)
Exemple #18
0
    def handle(self, *args: Any, **options: str) -> None:
        if settings.STAGING:
            print('This is a Staging server. Suppressing management command.')
            sys.exit(0)

        realm = self.get_realm(options)
        user_emails = options[
            'users']  # type: ignore  # mypy thinks this is a str, not List[str] #
        activate = options['activate']
        deactivate = options['deactivate']

        filter_kwargs = {}  # type: Dict[str, Realm]
        if realm is not None:
            filter_kwargs = dict(realm=realm)

        if activate:
            if not user_emails:
                print(
                    'You need to specify at least one user to use the activate option.'
                )
                self.print_help("./manage.py", "soft_deactivate_users")
                raise CommandError

            users_to_activate = get_users_from_emails(user_emails,
                                                      filter_kwargs)
            users_activated = do_soft_activate_users(users_to_activate)
            logger.info('Soft Reactivated %d user(s)' %
                        (len(users_activated), ))

        elif deactivate:
            if user_emails:
                users_to_deactivate = get_users_from_emails(
                    user_emails, filter_kwargs)
                print('Soft deactivating forcefully...')
                users_deactivated = do_soft_deactivate_users(
                    users_to_deactivate)
            else:
                users_deactivated = do_auto_soft_deactivate_users(
                    int(options['inactive_for']), realm)
            logger.info('Soft Deactivated %d user(s)' %
                        (len(users_deactivated), ))

        else:
            self.print_help("./manage.py", "soft_deactivate_users")
            raise CommandError
Exemple #19
0
    def handle(self, *args: Any, **options: Any) -> None:
        if settings.STAGING:
            print("This is a Staging server. Suppressing management command.")
            sys.exit(0)

        realm = self.get_realm(options)
        user_emails = options["users"]
        activate = options["activate"]
        deactivate = options["deactivate"]

        filter_kwargs: Dict[str, Realm] = {}
        if realm is not None:
            filter_kwargs = dict(realm=realm)

        if activate:
            if not user_emails:
                print(
                    "You need to specify at least one user to use the activate option."
                )
                self.print_help("./manage.py", "soft_deactivate_users")
                raise CommandError

            users_to_activate = get_users_from_emails(user_emails,
                                                      filter_kwargs)
            users_activated = do_soft_activate_users(users_to_activate)
            logger.info("Soft Reactivated %d user(s)", len(users_activated))

        elif deactivate:
            if user_emails:
                users_to_deactivate = get_users_from_emails(
                    user_emails, filter_kwargs)
                print("Soft deactivating forcefully...")
                users_deactivated = do_soft_deactivate_users(
                    users_to_deactivate)
            else:
                users_deactivated = do_auto_soft_deactivate_users(
                    int(options["inactive_for"]), realm)
            logger.info("Soft deactivated %d user(s)", len(users_deactivated))

        else:
            self.print_help("./manage.py", "soft_deactivate_users")
            raise CommandError
    def handle(self, *args, **options):
        # type: (*Any, **str) -> None
        realm = self.get_realm(options)
        user_emails = options['users']
        activate = options['activate']
        deactivate = options['deactivate']
        if activate:
            if not user_emails:
                print('You need to specify at least one user to use the activate option.')
                self.print_help("./manage.py", "soft_activate_deactivate_users")
                sys.exit(1)
            users_to_activate = list(UserProfile.objects.filter(
                realm=realm,
                email__in=user_emails))
            if len(users_to_activate) != len(user_emails):
                user_emails_found = [user.email for user in users_to_activate]
                for user in user_emails:
                    if user not in user_emails_found:
                        raise Exception('User with email %s was not found. Check if the email is correct.' % (user))
            users_activated = do_soft_activate_users(users_to_activate)
            logger.info('Soft Reactivated %d user(s)' % (len(users_activated)))
        elif deactivate:
            if user_emails:
                users_to_deactivate = list(UserProfile.objects.filter(
                    realm=realm,
                    email__in=user_emails))
                if len(users_to_deactivate) != len(user_emails):
                    user_emails_found = [user.email for user in users_to_deactivate]
                    for user in user_emails:
                        if user not in user_emails_found:
                            raise Exception('User with email %s was not found. Check if the email is correct.' % (user))
                print('Soft deactivating forcefully...')
            else:
                users_to_deactivate = get_users_for_soft_deactivation(realm, int(options['inactive_for']))

            if users_to_deactivate:
                users_deactivated = do_soft_deactivate_users(users_to_deactivate)
                logger.info('Soft Deactivated %d user(s)' % (len(users_deactivated)))
        else:
            self.print_help("./manage.py", "soft_activate_deactivate_users")
            sys.exit(1)
    def handle(self, *args: Any, **options: str) -> None:
        if settings.STAGING:
            print('This is a Staging server. Suppressing management command.')
            sys.exit(0)

        realm = self.get_realm(options)
        user_emails = options['users']
        activate = options['activate']
        deactivate = options['deactivate']

        filter_kwargs = {}  # type: Dict[str, Realm]
        if realm is not None:
            filter_kwargs = dict(realm=realm)

        if activate:
            if not user_emails:
                print('You need to specify at least one user to use the activate option.')
                self.print_help("./manage.py", "soft_deactivate_users")
                sys.exit(1)

            users_to_activate = UserProfile.objects.filter(
                email__in=user_emails,
                **filter_kwargs
            )
            users_to_activate = list(users_to_activate)

            if len(users_to_activate) != len(user_emails):
                user_emails_found = [user.email for user in users_to_activate]
                for user in user_emails:
                    if user not in user_emails_found:
                        raise Exception('User with email %s was not found. '
                                        'Check if the email is correct.' % (user))

            users_activated = do_soft_activate_users(users_to_activate)
            logger.info('Soft Reactivated %d user(s)' % (len(users_activated)))
        elif deactivate:
            if user_emails:
                users_to_deactivate = UserProfile.objects.filter(
                    email__in=user_emails,
                    **filter_kwargs
                )
                users_to_deactivate = list(users_to_deactivate)

                if len(users_to_deactivate) != len(user_emails):
                    user_emails_found = [user.email for user in users_to_deactivate]
                    for user in user_emails:
                        if user not in user_emails_found:
                            raise Exception('User with email %s was not found. '
                                            'Check if the email is correct.' % (user,))
                print('Soft deactivating forcefully...')
            else:
                if realm is not None:
                    filter_kwargs = dict(user_profile__realm=realm)
                users_to_deactivate = get_users_for_soft_deactivation(int(options['inactive_for']),
                                                                      filter_kwargs)

            if users_to_deactivate:
                users_deactivated = do_soft_deactivate_users(users_to_deactivate)
                logger.info('Soft Deactivated %d user(s)' % (len(users_deactivated)))
        else:
            self.print_help("./manage.py", "soft_deactivate_users")
            sys.exit(1)
    def test_user_message_filter(self) -> None:
        # In this test we are basically testing out the logic used out in
        # do_send_messages() in action.py for filtering the messages for which
        # UserMessage rows should be created for a soft-deactivated user.
        recipient_list = [
            self.example_user("hamlet"),
            self.example_user("iago"),
            self.example_user('cordelia'),
        ]
        for user_profile in recipient_list:
            self.subscribe(user_profile, "Denmark")

        cordelia = self.example_user('cordelia')
        sender = self.example_user('iago')
        stream_name = 'Denmark'
        topic_name = 'foo'

        def send_stream_message(content: str) -> None:
            self.send_stream_message(sender, stream_name, content, topic_name)

        def send_personal_message(content: str) -> None:
            self.send_personal_message(sender, self.example_user("hamlet"),
                                       content)

        long_term_idle_user = self.example_user('hamlet')
        self.send_stream_message(long_term_idle_user, stream_name)
        with self.assertLogs(level='INFO') as info_logs:
            do_soft_deactivate_users([long_term_idle_user])
        self.assertEqual(info_logs.output, [
            'INFO:root:Soft-deactivated batch of 1 users; 0 remain to process'
        ])

        def assert_um_count(user: UserProfile, count: int) -> None:
            user_messages = get_user_messages(user)
            self.assertEqual(len(user_messages), count)

        def assert_last_um_content(user: UserProfile,
                                   content: str,
                                   negate: bool = False) -> None:
            user_messages = get_user_messages(user)
            if negate:
                self.assertNotEqual(user_messages[-1].content, content)
            else:
                self.assertEqual(user_messages[-1].content, content)

        # Test that sending a message to a stream with soft deactivated user
        # doesn't end up creating UserMessage row for deactivated user.
        general_user_msg_count = len(get_user_messages(cordelia))
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = 'Test Message 1'
        send_stream_message(message)
        assert_last_um_content(long_term_idle_user, message, negate=True)
        assert_um_count(long_term_idle_user, soft_deactivated_user_msg_count)
        assert_um_count(cordelia, general_user_msg_count + 1)
        assert_last_um_content(cordelia, message)

        # Test that sending a message to a stream with soft deactivated user
        # and push/email notifications on creates a UserMessage row for the
        # deactivated user.
        sub = get_subscription(stream_name, long_term_idle_user)
        sub.push_notifications = True
        sub.save()
        general_user_msg_count = len(get_user_messages(cordelia))
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = 'Test private stream message'
        send_stream_message(message)
        assert_um_count(long_term_idle_user,
                        soft_deactivated_user_msg_count + 1)
        assert_last_um_content(long_term_idle_user, message)
        sub.push_notifications = False
        sub.save()

        # Test sending a private message to soft deactivated user creates
        # UserMessage row.
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = 'Test PM'
        send_personal_message(message)
        assert_um_count(long_term_idle_user,
                        soft_deactivated_user_msg_count + 1)
        assert_last_um_content(long_term_idle_user, message)

        # Test UserMessage row is created while user is deactivated if
        # user itself is mentioned.
        general_user_msg_count = len(get_user_messages(cordelia))
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = 'Test @**King Hamlet** mention'
        send_stream_message(message)
        assert_last_um_content(long_term_idle_user, message)
        assert_um_count(long_term_idle_user,
                        soft_deactivated_user_msg_count + 1)
        assert_um_count(cordelia, general_user_msg_count + 1)
        assert_last_um_content(cordelia, message)

        # Test UserMessage row is not created while user is deactivated if
        # anyone is mentioned but the user.
        general_user_msg_count = len(get_user_messages(cordelia))
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = 'Test @**Cordelia Lear**  mention'
        send_stream_message(message)
        assert_last_um_content(long_term_idle_user, message, negate=True)
        assert_um_count(long_term_idle_user, soft_deactivated_user_msg_count)
        assert_um_count(cordelia, general_user_msg_count + 1)
        assert_last_um_content(cordelia, message)

        # Test UserMessage row is created while user is deactivated if
        # there is a wildcard mention such as @all or @everyone
        general_user_msg_count = len(get_user_messages(cordelia))
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = 'Test @**all** mention'
        send_stream_message(message)
        assert_last_um_content(long_term_idle_user, message)
        assert_um_count(long_term_idle_user,
                        soft_deactivated_user_msg_count + 1)
        assert_um_count(cordelia, general_user_msg_count + 1)
        assert_last_um_content(cordelia, message)

        general_user_msg_count = len(get_user_messages(cordelia))
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = 'Test @**everyone** mention'
        send_stream_message(message)
        assert_last_um_content(long_term_idle_user, message)
        assert_um_count(long_term_idle_user,
                        soft_deactivated_user_msg_count + 1)
        assert_um_count(cordelia, general_user_msg_count + 1)
        assert_last_um_content(cordelia, message)

        general_user_msg_count = len(get_user_messages(cordelia))
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = 'Test @**stream** mention'
        send_stream_message(message)
        assert_last_um_content(long_term_idle_user, message)
        assert_um_count(long_term_idle_user,
                        soft_deactivated_user_msg_count + 1)
        assert_um_count(cordelia, general_user_msg_count + 1)
        assert_last_um_content(cordelia, message)

        # Test UserMessage row is not created while user is deactivated if there
        # is a alert word in message.
        do_add_alert_words(long_term_idle_user, ['test_alert_word'])
        general_user_msg_count = len(get_user_messages(cordelia))
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = 'Testing test_alert_word'
        send_stream_message(message)
        assert_last_um_content(long_term_idle_user, message)
        assert_um_count(long_term_idle_user,
                        soft_deactivated_user_msg_count + 1)
        assert_um_count(cordelia, general_user_msg_count + 1)
        assert_last_um_content(cordelia, message)

        # Test UserMessage row is created while user is deactivated if
        # message is a me message.
        general_user_msg_count = len(get_user_messages(cordelia))
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = '/me says test'
        send_stream_message(message)
        assert_last_um_content(long_term_idle_user, message, negate=True)
        assert_um_count(long_term_idle_user, soft_deactivated_user_msg_count)
        assert_um_count(cordelia, general_user_msg_count + 1)
        assert_last_um_content(cordelia, message)
    def test_add_missing_messages(self) -> None:
        recipient_list = [
            self.example_user("hamlet"),
            self.example_user("iago")
        ]
        for user_profile in recipient_list:
            self.subscribe(user_profile, "Denmark")

        sender = self.example_user('iago')
        realm = sender.realm
        sending_client = make_client(name="test suite")
        stream_name = 'Denmark'
        stream = get_stream(stream_name, realm)
        topic_name = 'foo'

        def send_fake_message(message_content: str, stream: Stream) -> Message:
            recipient = stream.recipient
            message = Message(sender=sender,
                              recipient=recipient,
                              content=message_content,
                              date_sent=timezone_now(),
                              sending_client=sending_client)
            message.set_topic_name(topic_name)
            message.save()
            return message

        long_term_idle_user = self.example_user('hamlet')
        self.send_stream_message(long_term_idle_user, stream_name)
        with self.assertLogs(level='INFO') as info_logs:
            do_soft_deactivate_users([long_term_idle_user])
        self.assertEqual(info_logs.output, [
            'INFO:root:Soft-deactivated batch of 1 users; 0 remain to process'
        ])

        # Test that add_missing_messages() in simplest case of adding a
        # message for which UserMessage row doesn't exist for this user.
        sent_message = send_fake_message('Test Message 1', stream)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        idle_user_msg_count = len(idle_user_msg_list)
        self.assertNotEqual(idle_user_msg_list[-1], sent_message)
        with queries_captured() as queries:
            add_missing_messages(long_term_idle_user)
        self.assert_length(queries, 6)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(len(idle_user_msg_list), idle_user_msg_count + 1)
        self.assertEqual(idle_user_msg_list[-1], sent_message)
        long_term_idle_user.refresh_from_db()
        self.assertEqual(long_term_idle_user.last_active_message_id,
                         sent_message.id)

        # Test that add_missing_messages() only adds messages that aren't
        # already present in the UserMessage table. This test works on the
        # fact that previous test just above this added a message but didn't
        # updated the last_active_message_id field for the user.
        sent_message = send_fake_message('Test Message 2', stream)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        idle_user_msg_count = len(idle_user_msg_list)
        self.assertNotEqual(idle_user_msg_list[-1], sent_message)
        with queries_captured() as queries:
            add_missing_messages(long_term_idle_user)
        self.assert_length(queries, 7)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(len(idle_user_msg_list), idle_user_msg_count + 1)
        self.assertEqual(idle_user_msg_list[-1], sent_message)
        long_term_idle_user.refresh_from_db()
        self.assertEqual(long_term_idle_user.last_active_message_id,
                         sent_message.id)

        # Test UserMessage rows are created correctly in case of stream
        # Subscription was altered by admin while user was away.

        # Test for a public stream.
        sent_message_list = []
        sent_message_list.append(send_fake_message('Test Message 3', stream))
        # Alter subscription to stream.
        self.unsubscribe(long_term_idle_user, stream_name)
        send_fake_message('Test Message 4', stream)
        self.subscribe(long_term_idle_user, stream_name)
        sent_message_list.append(send_fake_message('Test Message 5', stream))
        sent_message_list.reverse()
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        idle_user_msg_count = len(idle_user_msg_list)
        for sent_message in sent_message_list:
            self.assertNotEqual(idle_user_msg_list.pop(), sent_message)
        with queries_captured() as queries:
            add_missing_messages(long_term_idle_user)
        self.assert_length(queries, 6)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(len(idle_user_msg_list), idle_user_msg_count + 2)
        for sent_message in sent_message_list:
            self.assertEqual(idle_user_msg_list.pop(), sent_message)
        long_term_idle_user.refresh_from_db()
        self.assertEqual(long_term_idle_user.last_active_message_id,
                         sent_message_list[0].id)

        # Test consecutive subscribe/unsubscribe in a public stream
        sent_message_list = []

        sent_message_list.append(send_fake_message('Test Message 6', stream))
        # Unsubscribe from stream and then immediately subscribe back again.
        self.unsubscribe(long_term_idle_user, stream_name)
        self.subscribe(long_term_idle_user, stream_name)
        sent_message_list.append(send_fake_message('Test Message 7', stream))
        # Again unsubscribe from stream and send a message.
        # This will make sure that if initially in a unsubscribed state
        # a consecutive subscribe/unsubscribe doesn't misbehave.
        self.unsubscribe(long_term_idle_user, stream_name)
        send_fake_message('Test Message 8', stream)
        # Do a subscribe and unsubscribe immediately.
        self.subscribe(long_term_idle_user, stream_name)
        self.unsubscribe(long_term_idle_user, stream_name)

        sent_message_list.reverse()
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        idle_user_msg_count = len(idle_user_msg_list)
        for sent_message in sent_message_list:
            self.assertNotEqual(idle_user_msg_list.pop(), sent_message)
        with queries_captured() as queries:
            add_missing_messages(long_term_idle_user)
        self.assert_length(queries, 6)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(len(idle_user_msg_list), idle_user_msg_count + 2)
        for sent_message in sent_message_list:
            self.assertEqual(idle_user_msg_list.pop(), sent_message)
        long_term_idle_user.refresh_from_db()
        self.assertEqual(long_term_idle_user.last_active_message_id,
                         sent_message_list[0].id)

        # Test for when user unsubscribes before soft deactivation
        # (must reactivate them in order to do this).

        do_soft_activate_users([long_term_idle_user])
        self.subscribe(long_term_idle_user, stream_name)
        # Send a real message to update last_active_message_id
        sent_message_id = self.send_stream_message(sender, stream_name,
                                                   'Test Message 9')
        self.unsubscribe(long_term_idle_user, stream_name)
        # Soft deactivate and send another message to the unsubscribed stream.
        with self.assertLogs(level='INFO') as info_logs:
            do_soft_deactivate_users([long_term_idle_user])
        self.assertEqual(info_logs.output, [
            'INFO:root:Soft-deactivated batch of 1 users; 0 remain to process'
        ])
        send_fake_message('Test Message 10', stream)

        idle_user_msg_list = get_user_messages(long_term_idle_user)
        idle_user_msg_count = len(idle_user_msg_list)
        self.assertEqual(idle_user_msg_list[-1].id, sent_message_id)
        with queries_captured() as queries:
            add_missing_messages(long_term_idle_user)
        # There are no streams to fetch missing messages from, so
        # the Message.objects query will be avoided.
        self.assert_length(queries, 4)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        # No new UserMessage rows should have been created.
        self.assertEqual(len(idle_user_msg_list), idle_user_msg_count)

        # Note: At this point in this test we have long_term_idle_user
        # unsubscribed from the 'Denmark' stream.

        # Test for a Private Stream.
        stream_name = "Core"
        private_stream = self.make_stream('Core', invite_only=True)
        self.subscribe(self.example_user("iago"), stream_name)
        sent_message_list = []
        send_fake_message('Test Message 11', private_stream)
        self.subscribe(self.example_user("hamlet"), stream_name)
        sent_message_list.append(
            send_fake_message('Test Message 12', private_stream))
        self.unsubscribe(long_term_idle_user, stream_name)
        send_fake_message('Test Message 13', private_stream)
        self.subscribe(long_term_idle_user, stream_name)
        sent_message_list.append(
            send_fake_message('Test Message 14', private_stream))
        sent_message_list.reverse()
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        idle_user_msg_count = len(idle_user_msg_list)
        for sent_message in sent_message_list:
            self.assertNotEqual(idle_user_msg_list.pop(), sent_message)
        with queries_captured() as queries:
            add_missing_messages(long_term_idle_user)
        self.assert_length(queries, 6)
        idle_user_msg_list = get_user_messages(long_term_idle_user)
        self.assertEqual(len(idle_user_msg_list), idle_user_msg_count + 2)
        for sent_message in sent_message_list:
            self.assertEqual(idle_user_msg_list.pop(), sent_message)
        long_term_idle_user.refresh_from_db()
        self.assertEqual(long_term_idle_user.last_active_message_id,
                         sent_message_list[0].id)
    def test_user_message_filter(self) -> None:
        # In this test we are basically testing out the logic used out in
        # do_send_messages() in action.py for filtering the messages for which
        # UserMessage rows should be created for a soft-deactivated user.
        AlertWord.objects.all().delete()

        long_term_idle_user = self.example_user("hamlet")
        cordelia = self.example_user("cordelia")
        sender = self.example_user("iago")
        stream_name = "Brand New Stream"
        topic_name = "foo"
        realm_id = cordelia.realm_id

        self.subscribe(long_term_idle_user, stream_name)
        self.subscribe(cordelia, stream_name)
        self.subscribe(sender, stream_name)

        stream_id = get_stream(stream_name, cordelia.realm).id

        def send_stream_message(content: str) -> None:
            self.send_stream_message(sender, stream_name, content, topic_name)

        def send_personal_message(content: str) -> None:
            self.send_personal_message(sender, self.example_user("hamlet"),
                                       content)

        self.send_stream_message(long_term_idle_user, stream_name)

        with self.assertLogs(logger_string, level="INFO") as info_logs:
            do_soft_deactivate_users([long_term_idle_user])

        self.assertEqual(
            info_logs.output,
            [
                f"INFO:{logger_string}:Soft deactivated user {long_term_idle_user.id}",
                f"INFO:{logger_string}:Soft-deactivated batch of 1 users; 0 remain to process",
            ],
        )

        def assert_um_count(user: UserProfile, count: int) -> None:
            user_messages = get_user_messages(user)
            self.assert_length(user_messages, count)

        def assert_last_um_content(user: UserProfile,
                                   content: str,
                                   negate: bool = False) -> None:
            user_messages = get_user_messages(user)
            if negate:
                self.assertNotEqual(user_messages[-1].content, content)
            else:
                self.assertEqual(user_messages[-1].content, content)

        def assert_num_possible_users(
                expected_count: int,
                *,
                possible_wildcard_mention: bool = False,
                possibly_mentioned_user_ids: AbstractSet[int] = set(),
        ) -> None:
            self.assertEqual(
                len(
                    get_subscriptions_for_send_message(
                        realm_id=realm_id,
                        stream_id=stream_id,
                        possible_wildcard_mention=possible_wildcard_mention,
                        possibly_mentioned_user_ids=possibly_mentioned_user_ids,
                    )),
                expected_count,
            )

        def assert_stream_message_sent_to_idle_user(
                content: str,
                *,
                possible_wildcard_mention: bool = False,
                possibly_mentioned_user_ids: AbstractSet[int] = set(),
        ) -> None:
            assert_num_possible_users(
                expected_count=3,
                possible_wildcard_mention=possible_wildcard_mention,
                possibly_mentioned_user_ids=possibly_mentioned_user_ids,
            )
            general_user_msg_count = len(get_user_messages(cordelia))
            soft_deactivated_user_msg_count = len(
                get_user_messages(long_term_idle_user))
            send_stream_message(content)
            assert_um_count(long_term_idle_user,
                            soft_deactivated_user_msg_count + 1)
            assert_um_count(cordelia, general_user_msg_count + 1)
            assert_last_um_content(long_term_idle_user, content)
            assert_last_um_content(cordelia, content)

        def assert_stream_message_not_sent_to_idle_user(
            content: str,
            *,
            possibly_mentioned_user_ids: AbstractSet[int] = set(),
            false_alarm_row: bool = False,
        ) -> None:
            if false_alarm_row:
                # We will query for our idle user if he has **ANY** alert
                # words, but we won't actually write a UserMessage row until
                # we truly parse the message. We also get false alarms for
                # messages with quoted mentions.
                assert_num_possible_users(
                    3, possibly_mentioned_user_ids=possibly_mentioned_user_ids)
            else:
                assert_num_possible_users(2)
            general_user_msg_count = len(get_user_messages(cordelia))
            soft_deactivated_user_msg_count = len(
                get_user_messages(long_term_idle_user))
            send_stream_message(content)
            assert_um_count(long_term_idle_user,
                            soft_deactivated_user_msg_count)
            assert_um_count(cordelia, general_user_msg_count + 1)
            assert_last_um_content(long_term_idle_user, content, negate=True)
            assert_last_um_content(cordelia, content)

        # Test that sending a message to a stream with soft deactivated user
        # doesn't end up creating UserMessage row for deactivated user.
        assert_stream_message_not_sent_to_idle_user("Test message 1")

        sub = get_subscription(stream_name, long_term_idle_user)

        # Sub settings override user settings.
        sub.push_notifications = True
        sub.save()
        assert_stream_message_sent_to_idle_user("Sub push")

        sub.push_notifications = False
        sub.save()
        assert_stream_message_not_sent_to_idle_user("Sub no push")

        # Let user defaults take over
        sub.push_notifications = None
        sub.save()

        long_term_idle_user.enable_stream_push_notifications = True
        long_term_idle_user.save()
        assert_stream_message_sent_to_idle_user("User push")

        long_term_idle_user.enable_stream_push_notifications = False
        long_term_idle_user.save()
        assert_stream_message_not_sent_to_idle_user("User no push")

        # Sub settings override user settings.
        sub.email_notifications = True
        sub.save()
        assert_stream_message_sent_to_idle_user("Sub email")

        sub.email_notifications = False
        sub.save()
        assert_stream_message_not_sent_to_idle_user("Sub no email")

        # Let user defaults take over
        sub.email_notifications = None
        sub.save()

        long_term_idle_user.enable_stream_email_notifications = True
        long_term_idle_user.save()
        assert_stream_message_sent_to_idle_user("User email")

        long_term_idle_user.enable_stream_email_notifications = False
        long_term_idle_user.save()
        assert_stream_message_not_sent_to_idle_user("User no email")

        # Test sending a private message to soft deactivated user creates
        # UserMessage row.
        soft_deactivated_user_msg_count = len(
            get_user_messages(long_term_idle_user))
        message = "Test PM"
        send_personal_message(message)
        assert_um_count(long_term_idle_user,
                        soft_deactivated_user_msg_count + 1)
        assert_last_um_content(long_term_idle_user, message)

        # Test UserMessage row is created while user is deactivated if
        # user itself is mentioned.
        assert_stream_message_sent_to_idle_user(
            "Test @**King Hamlet** mention",
            possibly_mentioned_user_ids={long_term_idle_user.id},
        )

        assert_stream_message_not_sent_to_idle_user(
            "Test `@**King Hamlet**` mention",
            possibly_mentioned_user_ids={long_term_idle_user.id},
            false_alarm_row=True,
        )

        # Test UserMessage row is not created while user is deactivated if
        # anyone is mentioned but the user.
        assert_stream_message_not_sent_to_idle_user(
            "Test @**Cordelia, Lear's daughter**  mention")

        # Test UserMessage row is created while user is deactivated if
        # there is a wildcard mention such as @all or @everyone
        assert_stream_message_sent_to_idle_user("Test @**all** mention",
                                                possible_wildcard_mention=True)
        assert_stream_message_sent_to_idle_user("Test @**everyone** mention",
                                                possible_wildcard_mention=True)
        assert_stream_message_sent_to_idle_user("Test @**stream** mention",
                                                possible_wildcard_mention=True)
        assert_stream_message_not_sent_to_idle_user("Test @**bogus** mention")

        # Test UserMessage row is created while user is deactivated if there
        # is a alert word in message.
        do_add_alert_words(long_term_idle_user, ["test_alert_word"])
        assert_stream_message_sent_to_idle_user("Testing test_alert_word")

        do_add_alert_words(cordelia, ["cordelia"])
        assert_stream_message_not_sent_to_idle_user("cordelia",
                                                    false_alarm_row=True)

        # Test UserMessage row is not created while user is deactivated if
        # message is a me message.
        assert_stream_message_not_sent_to_idle_user("/me says test",
                                                    false_alarm_row=True)

        # Sanity check after removing the alert word for Hamlet.
        AlertWord.objects.filter(user_profile=long_term_idle_user).delete()
        assert_stream_message_not_sent_to_idle_user("no alert words")