Skip to content

Instantly share code, notes, and snippets.

@ferndot
Created October 31, 2018 14:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ferndot/8938f7ab66d5f38f6f9449ea86e1c871 to your computer and use it in GitHub Desktop.
Save ferndot/8938f7ab66d5f38f6f9449ea86e1c871 to your computer and use it in GitHub Desktop.
django-simple-email-confirmation-drf
from django.conf import settings
from templated_mail.mail import BaseEmailMessage
class VerificationEmail(BaseEmailMessage):
template_name = 'email/email_verification.html'
def get_context_data(self):
# Get context and user
context = super().get_context_data()
user = context.get('user')
# Add needed context variables
context['uid'] = user.pk
context['url'] = settings.EMAIL_VERIFICATION_URL.format(**context)
return context
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from simple_email_confirmation.models import (
SimpleEmailConfirmationUserMixin,
EmailAddress,
)
from . import emails
class User(
SimpleEmailConfirmationUserMixin,
AbstractUser,
):
# Other stuff
def send_confirmation_email(self, email):
if hasattr(settings, 'EMAIL_VERIFICATION_URL'):
# Send email
token = EmailAddress.objects.get(user=self, email=email).key
emails.VerificationEmail(context={
'user': self,
'token': token,
}).send(to=[email])
from rest_framework import serializers
from simple_email_confirmation.models import EmailAddress
class EmailAddressSerializer(serializers.ModelSerializer):
class Meta:
model = EmailAddress
fields = (
'pk',
'email',
'is_confirmed',
'is_primary',
)
class ConfirmEmailAddressSerializer(serializers.Serializer):
confirmation_key = serializers.CharField()
class SetPrimaryEmailAddressSerializer(serializers.Serializer):
pass
from django.dispatch import receiver
from simple_email_confirmation.signals import unconfirmed_email_created
@receiver(unconfirmed_email_created)
def send_confirmation_email(sender, email, **kwargs):
sender.send_confirmation_email(email)
from django.db import IntegrityError
from rest_framework import viewsets, status, serializers as drf_serializers
from rest_framework.response import Response
from rest_framework.decorators import action
from simple_email_confirmation.models import EmailAddress
from simple_email_confirmation.exceptions import (
EmailConfirmationExpired, EmailIsPrimary, EmailNotConfirmed,
)
from . import serializers
class EmailViewSet(viewsets.ModelViewSet):
serializer_class = serializers.EmailAddressSerializer
def get_queryset(self):
return EmailAddress.objects.filter(user=self.request.user)
def get_serializer_class(self):
if self.action == 'send_confirmation':
return drf_serializers.Serializer()
elif self.action == 'confirm':
return serializers.ConfirmEmailAddressSerializer
elif self.action == 'set_primary':
return serializers.SetPrimaryEmailAddressSerializer
return super().get_serializer_class()
def create(self, request, *args, **kwargs):
try:
# Add the new unconfirmed email
request.user.add_unconfirmed_email(request.data['email'])
return Response({'status': 'success'})
except IntegrityError:
return Response(
{'errors': ['Email already exists']},
status=status.HTTP_400_BAD_REQUEST,
)
def destroy(self, request, *args, **kwargs):
email = self.get_object()
try:
# Delete the email
request.user.remove_email(email.email)
return Response({'status': 'success'})
except EmailIsPrimary:
return Response(
{'errors': ['Cannot delete the primary email']},
status=status.HTTP_400_BAD_REQUEST,
)
@action(methods=['post'], detail=True)
def send_confirmation(self, request, pk=None):
"""
Send a confirmation email.
"""
# Retrive email
email = self.get_object()
# Confirm email
email.user.reset_email_confirmation(email.email)
email.user.send_confirmation_email(email.email)
# Success!
return Response({'status': 'success'})
@action(methods=['post'], detail=True)
def confirm(self, request, pk=None):
"""
Confirm an email.
"""
# Retrive email
email = self.get_object()
try:
# Confirm email
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
email.user.confirm_email(
confirmation_key=serializer.data['confirmation_key']
)
# Success!
return Response({'status': 'success'})
except (EmailConfirmationExpired, EmailAddress.DoesNotExist):
return Response(
{'errors': ['Confirmation key is not valid']},
status=status.HTTP_400_BAD_REQUEST,
)
@action(methods=['patch'], detail=True)
def set_primary(self, request, pk=None):
"""
Set an email as primary.
"""
# Retrive email
email = self.get_object()
try:
# Set email as primary
email.user.set_primary_email(email.email)
# Success!
return Response({'status': 'success'})
except EmailNotConfirmed:
return Response(
{'errors': [
'Email must be confirmed before it can be set as primary'
]},
status=status.HTTP_400_BAD_REQUEST,
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment