mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	email digests: Write RealmAuditLog rows.
This commit is contained in:
		@@ -10,6 +10,7 @@ from confirmation.models import one_click_unsubscribe_link
 | 
			
		||||
from zerver.context_processors import common_context
 | 
			
		||||
from zerver.lib.email_notifications import build_message_list
 | 
			
		||||
from zerver.lib.logging_util import log_to_file
 | 
			
		||||
from zerver.lib.message import get_last_message_id
 | 
			
		||||
from zerver.lib.queue import queue_json_publish
 | 
			
		||||
from zerver.lib.send_email import FromAddress, send_future_email
 | 
			
		||||
from zerver.lib.url_encoding import encode_stream
 | 
			
		||||
@@ -256,11 +257,14 @@ def bulk_handle_digest_email(user_ids: List[int], cutoff: float) -> None:
 | 
			
		||||
    users = [get_user_profile_by_id(user_id) for user_id in user_ids]
 | 
			
		||||
    context_map = bulk_get_digest_context(users, cutoff)
 | 
			
		||||
 | 
			
		||||
    digest_users = []
 | 
			
		||||
 | 
			
		||||
    for user in users:
 | 
			
		||||
        context = context_map[user.id]
 | 
			
		||||
 | 
			
		||||
        # We don't want to send emails containing almost no information.
 | 
			
		||||
        if enough_traffic(context["hot_conversations"], context["new_streams_count"]):
 | 
			
		||||
            digest_users.append(user)
 | 
			
		||||
            logger.info("Sending digest email for user %s", user.id)
 | 
			
		||||
            # Send now, as a ScheduledEmail
 | 
			
		||||
            send_future_email(
 | 
			
		||||
@@ -272,6 +276,31 @@ def bulk_handle_digest_email(user_ids: List[int], cutoff: float) -> None:
 | 
			
		||||
                context=context,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
    bulk_write_realm_audit_logs(digest_users)
 | 
			
		||||
 | 
			
		||||
def bulk_write_realm_audit_logs(users: List[UserProfile]) -> None:
 | 
			
		||||
    if not users:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    # We write RealmAuditLog rows for auditing, and we will also
 | 
			
		||||
    # use these rows during the next run to possibly exclude the
 | 
			
		||||
    # users (if insufficient time has passed).
 | 
			
		||||
    last_message_id = get_last_message_id()
 | 
			
		||||
    now = timezone_now()
 | 
			
		||||
 | 
			
		||||
    log_rows = [
 | 
			
		||||
        RealmAuditLog(
 | 
			
		||||
            realm_id=user.realm_id,
 | 
			
		||||
            modified_user_id=user.id,
 | 
			
		||||
            event_last_message_id=last_message_id,
 | 
			
		||||
            event_time=now,
 | 
			
		||||
            event_type=RealmAuditLog.USER_DIGEST_EMAIL_CREATED,
 | 
			
		||||
        )
 | 
			
		||||
        for user in users
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    RealmAuditLog.objects.bulk_create(log_rows)
 | 
			
		||||
 | 
			
		||||
def handle_digest_email(user_id: int, cutoff: float) -> None:
 | 
			
		||||
    bulk_handle_digest_email([user_id], cutoff)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2812,6 +2812,7 @@ class AbstractRealmAuditLog(models.Model):
 | 
			
		||||
    USER_DEFAULT_REGISTER_STREAM_CHANGED = 130
 | 
			
		||||
    USER_DEFAULT_ALL_PUBLIC_STREAMS_CHANGED = 131
 | 
			
		||||
    USER_NOTIFICATION_SETTINGS_CHANGED = 132
 | 
			
		||||
    USER_DIGEST_EMAIL_CREATED = 133
 | 
			
		||||
 | 
			
		||||
    REALM_DEACTIVATED = 201
 | 
			
		||||
    REALM_REACTIVATED = 202
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ from zerver.lib.digest import (
 | 
			
		||||
    handle_digest_email,
 | 
			
		||||
    streams_recently_modified_for_user,
 | 
			
		||||
)
 | 
			
		||||
from zerver.lib.message import get_last_message_id
 | 
			
		||||
from zerver.lib.streams import create_stream_if_needed
 | 
			
		||||
from zerver.lib.test_classes import ZulipTestCase
 | 
			
		||||
from zerver.lib.test_helpers import cache_tries_captured, queries_captured
 | 
			
		||||
@@ -61,7 +62,7 @@ class TestDigestEmailMessages(ZulipTestCase):
 | 
			
		||||
        with queries_captured() as queries:
 | 
			
		||||
            handle_digest_email(othello.id, cutoff)
 | 
			
		||||
 | 
			
		||||
        self.assert_length(queries, 7)
 | 
			
		||||
        self.assert_length(queries, 9)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(mock_send_future_email.call_count, 1)
 | 
			
		||||
        kwargs = mock_send_future_email.call_args[1]
 | 
			
		||||
@@ -114,7 +115,7 @@ class TestDigestEmailMessages(ZulipTestCase):
 | 
			
		||||
        with queries_captured() as queries:
 | 
			
		||||
            handle_digest_email(polonius.id, cutoff)
 | 
			
		||||
 | 
			
		||||
        self.assert_length(queries, 7)
 | 
			
		||||
        self.assert_length(queries, 9)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(mock_send_future_email.call_count, 1)
 | 
			
		||||
        kwargs = mock_send_future_email.call_args[1]
 | 
			
		||||
@@ -175,7 +176,7 @@ class TestDigestEmailMessages(ZulipTestCase):
 | 
			
		||||
                with cache_tries_captured() as cache_tries:
 | 
			
		||||
                    bulk_handle_digest_email(digest_user_ids, cutoff)
 | 
			
		||||
 | 
			
		||||
            self.assert_length(queries, 37)
 | 
			
		||||
            self.assert_length(queries, 39)
 | 
			
		||||
            self.assert_length(cache_tries, 4)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(mock_send_future_email.call_count, len(digest_users))
 | 
			
		||||
@@ -199,6 +200,15 @@ class TestDigestEmailMessages(ZulipTestCase):
 | 
			
		||||
            self.assertIn('some content', teaser_messages[0]['content'][0]['plain'])
 | 
			
		||||
            self.assertIn(teaser_messages[0]['sender'], expected_participants)
 | 
			
		||||
 | 
			
		||||
        last_message_id = get_last_message_id()
 | 
			
		||||
        for digest_user in digest_users:
 | 
			
		||||
            log_rows = RealmAuditLog.objects.filter(
 | 
			
		||||
                modified_user_id=digest_user.id,
 | 
			
		||||
                event_type=RealmAuditLog.USER_DIGEST_EMAIL_CREATED,
 | 
			
		||||
            )
 | 
			
		||||
            (log,) = log_rows
 | 
			
		||||
            self.assertEqual(log.event_last_message_id, last_message_id)
 | 
			
		||||
 | 
			
		||||
    def test_streams_recently_modified_for_user(self) -> None:
 | 
			
		||||
        othello = self.example_user('othello')
 | 
			
		||||
        cordelia = self.example_user('cordelia')
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user