Skip to content

Commit

Permalink
Merge 6e47ec2 into 90c71f3
Browse files Browse the repository at this point in the history
  • Loading branch information
rishig committed Dec 16, 2017
2 parents 90c71f3 + 6e47ec2 commit b62f729
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 14 deletions.
3 changes: 1 addition & 2 deletions static/js/invite.js
Expand Up @@ -70,8 +70,7 @@ exports.initialize = function () {
},
success: function () {
$('#submit-invitation').button('reset');
invite_status.text(i18n.t('User invited successfully.',
{count: (invitee_emails.val().match(/@/g) || []).length}))
invite_status.text(i18n.t('User(s) invited successfully.'))
.addClass('alert-success')
.show();
invitee_emails.val('');
Expand Down
10 changes: 9 additions & 1 deletion zerver/lib/actions.py
Expand Up @@ -582,17 +582,25 @@ def do_deactivate_realm(realm: Realm) -> None:
realm.deactivated = True
realm.save(update_fields=["deactivated"])

event_time = timezone_now()
RealmAuditLog.objects.create(
realm=realm, event_type='realm_deactivated', event_time=event_time)

ScheduledEmail.objects.filter(realm=realm).delete()
for user in active_humans_in_realm(realm):
# Don't deactivate the users, but do delete their sessions so they get
# bumped to the login screen, where they'll get a realm deactivation
# notice when they try to log in.
delete_user_sessions(user)
clear_scheduled_emails(user.id)

def do_reactivate_realm(realm: Realm) -> None:
realm.deactivated = False
realm.save(update_fields=["deactivated"])

event_time = timezone_now()
RealmAuditLog.objects.create(
realm=realm, event_type='realm_reactivated', event_time=event_time)

def do_deactivate_user(user_profile: UserProfile,
acting_user: Optional[UserProfile]=None,
_cascade: bool=True) -> None:
Expand Down
2 changes: 1 addition & 1 deletion zerver/lib/digest.py
Expand Up @@ -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)
4 changes: 2 additions & 2 deletions zerver/lib/notifications.py
Expand Up @@ -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:
Expand Down
10 changes: 7 additions & 3 deletions zerver/lib/send_email.py
Expand Up @@ -4,7 +4,7 @@
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
Expand Down Expand Up @@ -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}
Expand All @@ -112,12 +112,16 @@ 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]}

ScheduledEmail.objects.create(
type=EMAIL_TYPES[template_name],
scheduled_timestamp=timezone_now() + delay,
realm=realm,
data=ujson.dumps(email_fields),
**to_field)
51 changes: 51 additions & 0 deletions zerver/migrations/0128_scheduledemail_realm.py
@@ -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'),
),
]
1 change: 1 addition & 0 deletions zerver/models.py
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion zerver/tests/test_realm.py
Expand Up @@ -148,7 +148,8 @@ def test_do_deactivate_realm_clears_user_realm_cache(self) -> None:

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)
Expand Down
7 changes: 4 additions & 3 deletions zerver/tests/test_signup.py
Expand Up @@ -353,7 +353,7 @@ def test_register(self) -> None:
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)
Expand Down Expand Up @@ -831,7 +831,7 @@ def test_invitation_reminder_email(self) -> None:
})
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())
Expand Down Expand Up @@ -1179,7 +1179,8 @@ def test_digest_unsubscribe(self) -> None:
# 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())

Expand Down
3 changes: 2 additions & 1 deletion zerver/tests/test_users.py
Expand Up @@ -374,7 +374,8 @@ def test_api_with_insufficient_permissions(self) -> None:

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)
Expand Down
1 change: 1 addition & 0 deletions zerver/worker/queue_processors.py
Expand Up @@ -246,6 +246,7 @@ def consume(self, data):
})
send_future_email(
"zerver/emails/invitation_reminder",
referrer.realm,
to_email=invitee.email,
from_address=FromAddress.NOREPLY,
context=context,
Expand Down

0 comments on commit b62f729

Please sign in to comment.