Skip to content

Commit

Permalink
Fix issue #68
Browse files Browse the repository at this point in the history
Add VERIFICATION_TEMPLATE_CONTEXT_BUILDER settings key
  • Loading branch information
apragacz committed Oct 5, 2019
1 parent 21f44e1 commit 100bc79
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 29 deletions.
15 changes: 11 additions & 4 deletions rest_registration/api/views/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
api_view_serializer_class_getter
)
from rest_registration.exceptions import BadRequest
from rest_registration.notifications import send_verification_notification
from rest_registration.notifications.email import (
send_verification_notification
)
from rest_registration.notifications.enums import NotificationType
from rest_registration.settings import registration_settings
from rest_registration.utils.responses import get_ok_response
from rest_registration.utils.users import (
Expand Down Expand Up @@ -92,9 +95,13 @@ def register(request):
signer = RegisterSigner({
'user_id': get_user_verification_id(user),
}, request=request)
template_config = (
registration_settings.REGISTER_VERIFICATION_EMAIL_TEMPLATES)
send_verification_notification(user, signer, template_config)
template_config_data = registration_settings.REGISTER_VERIFICATION_EMAIL_TEMPLATES # noqa: E501
notification_data = {
'params_signer': signer,
}
send_verification_notification(
NotificationType.REGISTER_VERIFICATION, user, notification_data,
template_config_data)

return Response(user_data, status=status.HTTP_201_CREATED)

Expand Down
14 changes: 10 additions & 4 deletions rest_registration/api/views/register_email.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
api_view_serializer_class_getter
)
from rest_registration.exceptions import BadRequest
from rest_registration.notifications import send_verification_notification
from rest_registration.notifications.email import (
send_verification_notification
)
from rest_registration.notifications.enums import NotificationType
from rest_registration.settings import registration_settings
from rest_registration.utils.responses import get_ok_response
from rest_registration.utils.users import (
Expand Down Expand Up @@ -55,15 +58,18 @@ def register_email(request):
if user_with_email_exists(email):
raise BadRequest("This email is already registered.")

template_config = (
registration_settings.REGISTER_EMAIL_VERIFICATION_EMAIL_TEMPLATES)
template_config_data = registration_settings.REGISTER_EMAIL_VERIFICATION_EMAIL_TEMPLATES # noqa: E501
if registration_settings.REGISTER_EMAIL_VERIFICATION_ENABLED:
signer = RegisterEmailSigner({
'user_id': get_user_verification_id(user),
'email': email,
}, request=request)
notification_data = {
'params_signer': signer,
}
send_verification_notification(
user, signer, template_config, email=email)
NotificationType.REGISTER_EMAIL_VERIFICATION, user,
notification_data, template_config_data, custom_user_address=email)
else:
email_field_name = get_user_email_field_name()
old_email = getattr(user, email_field_name)
Expand Down
15 changes: 11 additions & 4 deletions rest_registration/api/views/reset_password.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
api_view_serializer_class_getter
)
from rest_registration.exceptions import UserNotFound
from rest_registration.notifications import send_verification_notification
from rest_registration.notifications.email import (
send_verification_notification
)
from rest_registration.notifications.enums import NotificationType
from rest_registration.settings import registration_settings
from rest_registration.utils.responses import get_ok_response
from rest_registration.utils.users import (
Expand Down Expand Up @@ -71,9 +74,13 @@ def send_reset_password_link(request):
'user_id': get_user_verification_id(user),
}, request=request)

template_config = (
registration_settings.RESET_PASSWORD_VERIFICATION_EMAIL_TEMPLATES)
send_verification_notification(user, signer, template_config)
template_config_data = registration_settings.RESET_PASSWORD_VERIFICATION_EMAIL_TEMPLATES # noqa: E501
notification_data = {
'params_signer': signer,
}
send_verification_notification(
NotificationType.RESET_PASSWORD_VERIFICATION, user, notification_data,
template_config_data)

return get_ok_response('Reset link sent')

Expand Down
44 changes: 27 additions & 17 deletions rest_registration/notifications/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.template.exceptions import TemplateDoesNotExist
from django.template.loader import get_template, render_to_string

from rest_registration.notifications.enums import NotificationMethod
from rest_registration.settings import registration_settings
from rest_registration.utils.common import identity
from rest_registration.utils.users import get_user_email_field_name
Expand All @@ -18,26 +19,28 @@


def send_verification_notification(
user, params_signer, template_config_data, email=None):
notification_type, user, data, template_config_data,
custom_user_address=None):
if custom_user_address is None:
user_address = get_user_address(user)
else:
user_address = custom_user_address
notification = create_verification_notification(
user, params_signer, template_config_data, email=email)
notification_type, user, user_address, data, template_config_data)
send_notification(notification)


def create_verification_notification(
user, params_signer, template_config_data, email=None):
if email is None:
email_field_name = get_user_email_field_name()
email = getattr(user, email_field_name)

notification_type, user, user_address, data,
template_config_data):
from_email = registration_settings.VERIFICATION_FROM_EMAIL
reply_to_email = (registration_settings.VERIFICATION_REPLY_TO_EMAIL or
from_email)
context = {
'user': user,
'email': email,
'verification_url': params_signer.get_url(),
}
template_context_builder = registration_settings.VERIFICATION_TEMPLATE_CONTEXT_BUILDER # noqa: E501
context = template_context_builder(
user, user_address, data,
notification_type=notification_type,
notification_method=NotificationMethod.EMAIL)
template_config = parse_template_config(template_config_data)

subject = render_to_string(
Expand All @@ -47,7 +50,8 @@ def create_verification_notification(
template_config.text_body_template_name, context=context))

email_msg = EmailMultiAlternatives(
subject, text_body, from_email, [email], reply_to=[reply_to_email])
subject, text_body, from_email, [user_address],
reply_to=[reply_to_email])

if template_config.html_body_template_name:
html_body = render_to_string(
Expand All @@ -57,6 +61,16 @@ def create_verification_notification(
return email_msg


def send_notification(notification):
notification.send()


def get_user_address(user):
email_field_name = get_user_email_field_name()
email = getattr(user, email_field_name)
return email


def parse_template_config(template_config_data):
"""
>>> from tests import doctest_utils
Expand Down Expand Up @@ -203,7 +217,3 @@ def _validate_template_name_existence(template_name):
raise ImproperlyConfigured(
'Template {template_name!r} does not exists'.format(
template_name=template_name))


def send_notification(notification):
notification.send()
11 changes: 11 additions & 0 deletions rest_registration/notifications/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from enum import Enum, auto


class NotificationType(Enum):
REGISTER_VERIFICATION = auto()
REGISTER_EMAIL_VERIFICATION = auto()
RESET_PASSWORD_VERIFICATION = auto()


class NotificationMethod(Enum):
EMAIL = auto()
34 changes: 34 additions & 0 deletions rest_registration/settings_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,41 @@ def __new__(
It is be solely up to the implementer of custom builder function
to encode the signed values properly in the URL.
"""),
),
Field(
'VERIFICATION_TEMPLATE_CONTEXT_BUILDER',
default='rest_registration.utils.verification.build_default_template_context', # noqa: E501
import_string=True,
help=dedent("""\
The builder function receives these parameters as
positional arguments:
* ``user`` - the user which is to be notified.
* ``user_address`` - the user address, which can be the
user e-mail, phone number, etc.
* ``data`` - dictionary; in most cases it contains only
one entry, which is the ``param_signer``
under ``'param_signer'`` key. The implementer of the
custom builder function should be aware that the contents
of the dictionary are dynamic and write defensive code
to account that.
and these parameters as keyword arguments:
* ``notification_type`` - value of
``rest_registration.notifications.enums.NotificationType``
enum.
* ``notification_method`` - value of
``rest_registration.notifications.enums.NotificationMethod``
enum. Currently there is only one choice which is
``NotificationMethod.EMAIL``.
It is possible that in the future, additional keyword arguments
may be added. Therefore the implementer
of the custom builder function should take account of that,
for instance by adding ``**kwargs`` in the signature
of the function.
"""),
),
]

Expand Down
13 changes: 13 additions & 0 deletions rest_registration/utils/verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,16 @@ def build_default_verification_url(signer):
if signer.request:
url = signer.request.build_absolute_uri(url)
return url


def build_default_template_context(
user, user_address, data,
notification_type=None, notification_method=None):
context = {
'user': user,
'email': user_address,
}
params_signer = data.get('params_signer')
if params_signer:
context['verification_url'] = params_signer.get_url()
return context

0 comments on commit 100bc79

Please sign in to comment.