-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bug 859875 - watch page for email notification
add django-tidings update/copy/refactor wiki events code from SUMO remove notifications from apps in use restore and move watch view tests
- Loading branch information
1 parent
f2f5ab1
commit f31022b
Showing
15 changed files
with
315 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
import contextlib | ||
import logging | ||
from functools import wraps | ||
|
||
from django.conf import settings | ||
from django.core.mail import EmailMultiAlternatives | ||
from django.utils import translation | ||
|
||
import jingo | ||
import tower | ||
from test_utils import RequestFactory | ||
|
||
|
||
log = logging.getLogger('mdn.email') | ||
|
||
|
||
@contextlib.contextmanager | ||
def uselocale(locale): | ||
"""Context manager for setting locale and returning | ||
to previous locale. | ||
This is useful for when doing translations for things run by | ||
celery workers or out of the HTTP request handling path. | ||
>>> with uselocale('xx'): | ||
... subj = _('Subject of my email') | ||
... msg = render_email(email_template, email_kwargs) | ||
... mail.send_mail(subj, msg, ...) | ||
... | ||
In Kitsune, you can get the right locale from Profile.locale and | ||
also request.LANGUAGE_CODE. | ||
If Kitsune is handling an HTTP request already, you don't have to | ||
run uselocale---the locale will already be set correctly. | ||
""" | ||
currlocale = translation.get_language() | ||
tower.activate(locale) | ||
yield | ||
tower.activate(currlocale) | ||
|
||
|
||
def safe_translation(f): | ||
"""Call `f` which has first argument `locale`. If `f` raises an | ||
exception indicative of a bad localization of a string, try again in | ||
`settings.WIKI_DEFAULT_LANGUAGE`. | ||
NB: This means `f` will be called up to two times! | ||
""" | ||
@wraps(f) | ||
def wrapper(locale, *args, **kwargs): | ||
try: | ||
with uselocale(locale): | ||
return f(locale, *args, **kwargs) | ||
except (TypeError, KeyError, ValueError, IndexError) as e: | ||
# Types of errors, and examples. | ||
# | ||
# TypeError: Not enough arguments for string | ||
# '%s %s %s' % ('foo', 'bar') | ||
# KeyError: Bad variable name | ||
# '%(Foo)s' % {'foo': 10} or '{Foo}'.format(foo=10') | ||
# ValueError: Incomplete Format, or bad format string. | ||
# '%(foo)a' or '%(foo)' or '{foo' | ||
# IndexError: Not enough arguments for .format() style string. | ||
# '{0} {1}'.format(42) | ||
log.error('Bad translation in locale "%s": %s', locale, e) | ||
|
||
with uselocale(settings.WIKI_DEFAULT_LANGUAGE): | ||
return f(settings.WIKI_DEFAULT_LANGUAGE, *args, **kwargs) | ||
|
||
return wrapper | ||
|
||
|
||
def render_email(template, context): | ||
"""Renders a template in the currently set locale. | ||
Falls back to WIKI_DEFAULT_LANGUAGE in case of error. | ||
""" | ||
|
||
@safe_translation | ||
def _render(locale): | ||
"""Render an email in the given locale. | ||
Because of safe_translation decorator, if this fails, | ||
the function will be run again in English. | ||
""" | ||
req = RequestFactory() | ||
req.META = {} | ||
req.locale = locale | ||
|
||
return jingo.render_to_string(req, template, context) | ||
|
||
return _render(translation.get_language()) | ||
|
||
|
||
def emails_with_users_and_watches(subject, | ||
text_template, | ||
html_template, | ||
context_vars, | ||
users_and_watches, | ||
from_email=settings.TIDINGS_FROM_ADDRESS, | ||
default_locale=settings.WIKI_DEFAULT_LANGUAGE, | ||
**extra_kwargs): | ||
"""Return iterable of EmailMessages with user and watch values substituted. | ||
A convenience function for generating emails by repeatedly | ||
rendering a Django template with the given ``context_vars`` plus a | ||
``user`` and ``watches`` key for each pair in | ||
``users_and_watches`` | ||
.. Note:: | ||
This is a locale-aware re-write of the same function in django-tidings. | ||
It's kind of goofy--I ain't gonna lie. | ||
:arg subject: lazy gettext subject string | ||
:arg text_template: path to text template file | ||
:arg html_template: path to html template file | ||
:arg context_vars: a map which becomes the Context passed in to the | ||
template and the subject string | ||
:arg from_email: the from email address | ||
:arg default_local: the local to default to if not user.profile.locale | ||
:arg extra_kwargs: additional kwargs to pass into EmailMessage constructor | ||
:returns: generator of EmailMessage objects | ||
""" | ||
@safe_translation | ||
def _make_mail(locale, user, watch): | ||
context_vars['user'] = user | ||
context_vars['watch'] = watch[0] | ||
context_vars['watches'] = watch | ||
|
||
msg = EmailMultiAlternatives( | ||
subject.format(**context_vars), | ||
render_email(text_template, context_vars), | ||
from_email, | ||
[user.email], | ||
**extra_kwargs) | ||
|
||
if html_template: | ||
msg.attach_alternative( | ||
render_email(html_template, context_vars), 'text/html') | ||
|
||
return msg | ||
|
||
for u, w in users_and_watches: | ||
if hasattr(u, 'profile'): | ||
locale = u.profile.locale | ||
else: | ||
locale = default_locale | ||
|
||
yield _make_mail(locale, u, w) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,6 @@ | |
mock_post_mindtouch_user) | ||
|
||
from dekicompat.backends import DekiUserBackend, MINDTOUCH_USER_XML | ||
from notifications.tests import watch | ||
from sumo.helpers import urlparams | ||
from sumo.tests import TestCase, LocalizingClient | ||
from sumo.urlresolvers import reverse | ||
|
@@ -331,29 +330,6 @@ def test_new_user_activation(self, get_current): | |
user = User.objects.get(pk=user.pk) | ||
assert user.is_active | ||
|
||
@mock_put_mindtouch_user | ||
@mock_post_mindtouch_user | ||
@mock.patch_object(Site.objects, 'get_current') | ||
def test_new_user_claim_watches(self, get_current): | ||
"""Claim user watches upon activation.""" | ||
old, settings.CELERY_ALWAYS_EAGER = settings.CELERY_ALWAYS_EAGER, True | ||
|
||
get_current.return_value.domain = 'su.mo.com' | ||
|
||
watch(email='[email protected]', save=True) | ||
|
||
now = time() | ||
username = 'sumo%s' % now | ||
user = RegistrationProfile.objects.create_inactive_user( | ||
username, 'testpass', '[email protected]') | ||
key = RegistrationProfile.objects.all()[0].activation_key | ||
self.client.get(reverse('users.activate', args=[key]), follow=True) | ||
|
||
# Watches are claimed. | ||
assert user.watch_set.exists() | ||
|
||
settings.CELERY_ALWAYS_EAGER = old | ||
|
||
@mock_get_deki_user | ||
def test_duplicate_username(self): | ||
response = self.client.post(reverse('users.register'), | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,22 @@ | ||
{% load i18n %} | ||
{# L10n: This is an email. Whitespace matters! #} | ||
{% blocktrans %} | ||
{{ creator }} created a new revision to the document | ||
{{ document_title }}. | ||
|
||
To view this document's history, click the following | ||
link, or paste it into your browser's location bar: | ||
{% endblocktrans %} | ||
https://{{ host }}{{ url }} | ||
{# This is an email. Whitespace matters! #} | ||
{% from "includes/unsubscribe_text.ltxt" import unsubscribe_text with context %} | ||
{% autoescape false %} | ||
{% trans creator=creator, document_title=document_title %} | ||
{{ creator }} created a new revision to the document {{ document_title }}. | ||
{% endtrans %} | ||
|
||
|
||
{% trans %} | ||
To view this document's history, click the following link, or paste it | ||
into your browser's location bar: | ||
{% endtrans %} | ||
|
||
|
||
https://{{ host }}{{ history_url }} | ||
|
||
-- | ||
{# L10n: This is in an email. #} | ||
{{ _('Changes:') }} | ||
{{ diff|safe }} | ||
|
||
{{ unsubscribe_text(watch) }}{% endautoescape %} |
Oops, something went wrong.