mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	models: Add ScheduledEmail.realm.
The two extra queries in the test are due to the assert in send_future_email.
This commit is contained in:
		@@ -255,6 +255,6 @@ def handle_digest_email(user_profile_id: int, cutoff: float) -> None:
 | 
			
		||||
                      new_streams_count, new_users_count):
 | 
			
		||||
        logger.info("Sending digest email for %s" % (user_profile.email,))
 | 
			
		||||
        # Send now, as a ScheduledEmail
 | 
			
		||||
        send_future_email('zerver/emails/digest', to_user_id=user_profile.id,
 | 
			
		||||
        send_future_email('zerver/emails/digest', user_profile.realm, to_user_id=user_profile.id,
 | 
			
		||||
                          from_name="Zulip Digest", from_address=FromAddress.NOREPLY,
 | 
			
		||||
                          context=context)
 | 
			
		||||
 
 | 
			
		||||
@@ -453,10 +453,10 @@ def enqueue_welcome_emails(user: UserProfile) -> None:
 | 
			
		||||
        'is_realm_admin': user.is_realm_admin,
 | 
			
		||||
    })
 | 
			
		||||
    send_future_email(
 | 
			
		||||
        "zerver/emails/followup_day1", to_user_id=user.id, from_name=from_name,
 | 
			
		||||
        "zerver/emails/followup_day1", user.realm, to_user_id=user.id, from_name=from_name,
 | 
			
		||||
        from_address=from_address, context=context)
 | 
			
		||||
    send_future_email(
 | 
			
		||||
        "zerver/emails/followup_day2", to_user_id=user.id, from_name=from_name,
 | 
			
		||||
        "zerver/emails/followup_day2", user.realm, to_user_id=user.id, from_name=from_name,
 | 
			
		||||
        from_address=from_address, context=context, delay=datetime.timedelta(days=1))
 | 
			
		||||
 | 
			
		||||
def convert_html_to_markdown(html: Text) -> Text:
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ from django.template import loader
 | 
			
		||||
from django.utils.timezone import now as timezone_now
 | 
			
		||||
from django.template.exceptions import TemplateDoesNotExist
 | 
			
		||||
from zerver.models import UserProfile, ScheduledEmail, get_user_profile_by_id, \
 | 
			
		||||
    EMAIL_TYPES
 | 
			
		||||
    EMAIL_TYPES, Realm
 | 
			
		||||
 | 
			
		||||
import datetime
 | 
			
		||||
from email.utils import parseaddr, formataddr
 | 
			
		||||
@@ -98,9 +98,9 @@ def send_email(template_prefix, to_user_id=None, to_email=None, from_name=None,
 | 
			
		||||
def send_email_from_dict(email_dict: Mapping[str, Any]) -> None:
 | 
			
		||||
    send_email(**dict(email_dict))
 | 
			
		||||
 | 
			
		||||
def send_future_email(template_prefix, to_user_id=None, to_email=None, from_name=None,
 | 
			
		||||
def send_future_email(template_prefix, realm, to_user_id=None, to_email=None, from_name=None,
 | 
			
		||||
                      from_address=None, context={}, delay=datetime.timedelta(0)):
 | 
			
		||||
    # type: (str, Optional[int], Optional[Text], Optional[Text], Optional[Text], Dict[str, Any], datetime.timedelta) -> None
 | 
			
		||||
    # type: (str, Realm, Optional[int], Optional[Text], Optional[Text], Optional[Text], Dict[str, Any], datetime.timedelta) -> None
 | 
			
		||||
    template_name = template_prefix.split('/')[-1]
 | 
			
		||||
    email_fields = {'template_prefix': template_prefix, 'to_user_id': to_user_id, 'to_email': to_email,
 | 
			
		||||
                    'from_name': from_name, 'from_address': from_address, 'context': context}
 | 
			
		||||
@@ -112,6 +112,9 @@ def send_future_email(template_prefix, to_user_id=None, to_email=None, from_name
 | 
			
		||||
 | 
			
		||||
    assert (to_user_id is None) ^ (to_email is None)
 | 
			
		||||
    if to_user_id is not None:
 | 
			
		||||
        # The realm is redundant if we have a to_user_id; this assert just
 | 
			
		||||
        # expresses that fact
 | 
			
		||||
        assert(UserProfile.objects.filter(id=to_user_id, realm=realm).exists())
 | 
			
		||||
        to_field = {'user_id': to_user_id}  # type: Dict[str, Any]
 | 
			
		||||
    else:
 | 
			
		||||
        to_field = {'address': parseaddr(to_email)[1]}
 | 
			
		||||
@@ -119,5 +122,6 @@ def send_future_email(template_prefix, to_user_id=None, to_email=None, from_name
 | 
			
		||||
    ScheduledEmail.objects.create(
 | 
			
		||||
        type=EMAIL_TYPES[template_name],
 | 
			
		||||
        scheduled_timestamp=timezone_now() + delay,
 | 
			
		||||
        realm=realm,
 | 
			
		||||
        data=ujson.dumps(email_fields),
 | 
			
		||||
        **to_field)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								zerver/migrations/0128_scheduledemail_realm.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								zerver/migrations/0128_scheduledemail_realm.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# Generated by Django 1.11.6 on 2017-12-05 01:08
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
from django.db.backends.postgresql_psycopg2.schema import DatabaseSchemaEditor
 | 
			
		||||
from django.db.migrations.state import StateApps
 | 
			
		||||
 | 
			
		||||
def set_realm_for_existing_scheduledemails(
 | 
			
		||||
        apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None:
 | 
			
		||||
    scheduledemail_model = apps.get_model("zerver", "ScheduledEmail")
 | 
			
		||||
    preregistrationuser_model = apps.get_model("zerver", "PreregistrationUser")
 | 
			
		||||
    for scheduledemail in scheduledemail_model.objects.all():
 | 
			
		||||
        if scheduledemail.type == 3:  # ScheduledEmail.INVITATION_REMINDER
 | 
			
		||||
            # Don't think this can be None, but just be safe
 | 
			
		||||
            prereg = preregistrationuser_model.objects.filter(email=scheduledemail.address).first()
 | 
			
		||||
            if prereg is not None:
 | 
			
		||||
                scheduledemail.realm = prereg.realm
 | 
			
		||||
        else:
 | 
			
		||||
            scheduledemail.realm = scheduledemail.user.realm
 | 
			
		||||
        scheduledemail.save(update_fields=['realm'])
 | 
			
		||||
 | 
			
		||||
    # Shouldn't be needed, but just in case
 | 
			
		||||
    scheduledemail_model.objects.filter(realm=None).delete()
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('zerver', '0127_disallow_chars_in_stream_and_user_name'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        # Start with ScheduledEmail.realm being non-null
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='scheduledemail',
 | 
			
		||||
            name='realm',
 | 
			
		||||
            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='zerver.Realm'),
 | 
			
		||||
        ),
 | 
			
		||||
 | 
			
		||||
        # Sets realm for existing ScheduledEmails
 | 
			
		||||
        migrations.RunPython(set_realm_for_existing_scheduledemails,
 | 
			
		||||
                             reverse_code=migrations.RunPython.noop),
 | 
			
		||||
 | 
			
		||||
        # Require ScheduledEmail.realm to be non-null
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='scheduledemail',
 | 
			
		||||
            name='realm',
 | 
			
		||||
            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Realm'),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -1726,6 +1726,7 @@ class AbstractScheduledJob(models.Model):
 | 
			
		||||
    scheduled_timestamp = models.DateTimeField(db_index=True)  # type: datetime.datetime
 | 
			
		||||
    # JSON representation of arguments to consumer
 | 
			
		||||
    data = models.TextField()  # type: Text
 | 
			
		||||
    realm = models.ForeignKey(Realm, on_delete=CASCADE)  # type: Realm
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 
 | 
			
		||||
@@ -148,7 +148,8 @@ class RealmTest(ZulipTestCase):
 | 
			
		||||
 | 
			
		||||
    def test_do_deactivate_realm_clears_scheduled_jobs(self) -> None:
 | 
			
		||||
        user = self.example_user('hamlet')
 | 
			
		||||
        send_future_email('zerver/emails/followup_day1', to_user_id=user.id, delay=datetime.timedelta(hours=1))
 | 
			
		||||
        send_future_email('zerver/emails/followup_day1', user.realm,
 | 
			
		||||
                          to_user_id=user.id, delay=datetime.timedelta(hours=1))
 | 
			
		||||
        self.assertEqual(ScheduledEmail.objects.count(), 1)
 | 
			
		||||
        do_deactivate_realm(user.realm)
 | 
			
		||||
        self.assertEqual(ScheduledEmail.objects.count(), 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -353,7 +353,7 @@ class LoginTest(ZulipTestCase):
 | 
			
		||||
        with queries_captured() as queries:
 | 
			
		||||
            self.register(self.nonreg_email('test'), "test")
 | 
			
		||||
        # Ensure the number of queries we make is not O(streams)
 | 
			
		||||
        self.assert_length(queries, 67)
 | 
			
		||||
        self.assert_length(queries, 69)
 | 
			
		||||
        user_profile = self.nonreg_user('test')
 | 
			
		||||
        self.assertEqual(get_session_dict_user(self.client.session), user_profile.id)
 | 
			
		||||
        self.assertFalse(user_profile.enable_stream_desktop_notifications)
 | 
			
		||||
@@ -831,7 +831,7 @@ so we didn't send them an invitation. We did send invitations to everyone else!"
 | 
			
		||||
        })
 | 
			
		||||
        with self.settings(EMAIL_BACKEND='django.core.mail.backends.console.EmailBackend'):
 | 
			
		||||
            send_future_email(
 | 
			
		||||
                "zerver/emails/invitation_reminder", to_email=data["email"],
 | 
			
		||||
                "zerver/emails/invitation_reminder", referrer.realm, to_email=data["email"],
 | 
			
		||||
                from_address=FromAddress.NOREPLY, context=context)
 | 
			
		||||
        email_jobs_to_deliver = ScheduledEmail.objects.filter(
 | 
			
		||||
            scheduled_timestamp__lte=timezone_now())
 | 
			
		||||
@@ -1179,7 +1179,8 @@ class EmailUnsubscribeTests(ZulipTestCase):
 | 
			
		||||
        # Enqueue a fake digest email.
 | 
			
		||||
        context = {'name': '', 'realm_uri': '', 'unread_pms': [], 'hot_conversations': [],
 | 
			
		||||
                   'new_users': [], 'new_streams': {'plain': []}, 'unsubscribe_link': ''}
 | 
			
		||||
        send_future_email('zerver/emails/digest', to_user_id=user_profile.id, context=context)
 | 
			
		||||
        send_future_email('zerver/emails/digest', user_profile.realm,
 | 
			
		||||
                          to_user_id=user_profile.id, context=context)
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(1, ScheduledEmail.objects.filter(user=user_profile).count())
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -374,7 +374,8 @@ class ActivateTest(ZulipTestCase):
 | 
			
		||||
 | 
			
		||||
    def test_clear_scheduled_jobs(self) -> None:
 | 
			
		||||
        user = self.example_user('hamlet')
 | 
			
		||||
        send_future_email('zerver/emails/followup_day1', to_user_id=user.id, delay=datetime.timedelta(hours=1))
 | 
			
		||||
        send_future_email('zerver/emails/followup_day1', user.realm,
 | 
			
		||||
                          to_user_id=user.id, delay=datetime.timedelta(hours=1))
 | 
			
		||||
        self.assertEqual(ScheduledEmail.objects.count(), 1)
 | 
			
		||||
        do_deactivate_user(user)
 | 
			
		||||
        self.assertEqual(ScheduledEmail.objects.count(), 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -246,6 +246,7 @@ class ConfirmationEmailWorker(QueueProcessingWorker):
 | 
			
		||||
        })
 | 
			
		||||
        send_future_email(
 | 
			
		||||
            "zerver/emails/invitation_reminder",
 | 
			
		||||
            referrer.realm,
 | 
			
		||||
            to_email=invitee.email,
 | 
			
		||||
            from_address=FromAddress.NOREPLY,
 | 
			
		||||
            context=context,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user