From 5f42ebdf74e2888d499c3e1c87e78c3fd0f89a8c Mon Sep 17 00:00:00 2001 From: Bobby Date: Mon, 1 Aug 2022 19:20:26 +0530 Subject: feature: change user email address --- blog/templates/account.html | 3 +- .../templates/email_change_verification_email.html | 12 +++++ users/templates/verification_email.html | 2 +- users/tokens.py | 12 +++++ users/urls.py | 2 + users/views.py | 51 +++++++++++++++++++++- 6 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 users/templates/email_change_verification_email.html diff --git a/blog/templates/account.html b/blog/templates/account.html index 3c63eaa4..6e07cb6d 100644 --- a/blog/templates/account.html +++ b/blog/templates/account.html @@ -72,7 +72,8 @@ -
+ + {% csrf_token %}
Change Email diff --git a/users/templates/email_change_verification_email.html b/users/templates/email_change_verification_email.html new file mode 100644 index 00000000..4e803855 --- /dev/null +++ b/users/templates/email_change_verification_email.html @@ -0,0 +1,12 @@ +{% autoescape off %} +Hi {{ user }}, + +We received a request to change you email address on {{ site_name }}. To verify your email address, please click the link below. +{{ protocol }}{{ domain }}{% url 'users:changeemail' uidb64=uid token=token %} + +Please ignore this email if you did not make this request. + +Thanks, +{{ site_name }} Team + +{% endautoescape %} \ No newline at end of file diff --git a/users/templates/verification_email.html b/users/templates/verification_email.html index 9a96e31b..554aceb5 100644 --- a/users/templates/verification_email.html +++ b/users/templates/verification_email.html @@ -1,7 +1,7 @@ {% autoescape off %} Hi {{ user }}, -Thanks for registering an account on {{ site_name }}. To verify your email address, please click the link below.

+Thanks for registering an account on {{ site_name }}. To verify and change your email address, please click the link below. {{ protocol }}{{ domain }}{% url 'users:verifyemail' uidb64=uid token=token %} Thanks, diff --git a/users/tokens.py b/users/tokens.py index 7bc5bc90..c127fa45 100644 --- a/users/tokens.py +++ b/users/tokens.py @@ -1,4 +1,7 @@ +import cryptocode +import os from django.contrib.auth.tokens import PasswordResetTokenGenerator +from dotenv import load_dotenv from six import text_type class AccountActivationTokenGenerator(PasswordResetTokenGenerator): @@ -8,4 +11,13 @@ class AccountActivationTokenGenerator(PasswordResetTokenGenerator): text_type(user.is_active) ) +class EmailChangeTokenGenerator(): + def encrypt(self, email): + auth_string = os.getenv('AUTHORIZATION_STRING') + return cryptocode.encrypt(email, auth_string) + + def decrypt(self, token): + auth_string = os.getenv('AUTHORIZATION_STRING') + return cryptocode.decrypt(token, auth_string) + account_activation_token = AccountActivationTokenGenerator() diff --git a/users/urls.py b/users/urls.py index b7cd5f82..48b1d87b 100644 --- a/users/urls.py +++ b/users/urls.py @@ -11,6 +11,8 @@ urlpatterns = [ path('changepassword', views.change_password, name='changepassword'), path('sendverificationemail', views.send_verification_email, name='sendverificationemail'), path('verifyemail//', views.verify_email, name='verifyemail'), + path('sendchangeuseremail', views.send_change_user_email, name='sendchangeuseremail'), + path('changeemail//', views.change_email, name='changeemail'), ] # Configure Admin Site diff --git a/users/views.py b/users/views.py index f4405a38..ce3b2c6f 100644 --- a/users/views.py +++ b/users/views.py @@ -11,7 +11,7 @@ from django.utils.html import strip_tags from django.utils.encoding import force_bytes from django.utils.http import urlsafe_base64_encode from django.contrib.sites.shortcuts import get_current_site -from .tokens import account_activation_token +from .tokens import account_activation_token, EmailChangeTokenGenerator from django.utils.http import urlsafe_base64_decode # Create your views here. @@ -136,4 +136,51 @@ def verify_email(request, uidb64, token): return redirect('/') else: messages.error(request, 'The verification link is invalid!') - return redirect('/') \ No newline at end of file + return redirect('/') + +def send_change_user_email(request): + user = request.user + new_email = request.POST['email'] + if user is not None: + # check if email is already in use + if User.objects.filter(email=new_email).exists(): + messages.error(request, 'Email is already in use!') + # Redirect to referrer + return HttpResponseRedirect(request.META.get('HTTP_REFERER')) + # Check if the new and the old email are the same + if user.email == new_email: + messages.error(request, 'New email is the same as the old one!') + return HttpResponseRedirect(request.META.get('HTTP_REFERER')) + # Send verification email + subject = 'Verify your email address' + message = render_to_string('email_change_verification_email.html', { + 'user': user.username if user.first_name is None else user.first_name, + 'site_name': 'That Computer Scientist', + 'uid': urlsafe_base64_encode(force_bytes(user.pk)), + 'token': EmailChangeTokenGenerator().encrypt(new_email), + 'protocol': 'https://' if request.is_secure() else 'http://', + 'domain': get_current_site(request).domain, + }) + message = strip_tags(message) + send_mail(subject, message, 'That Computer Scientist <' + settings.EMAIL_HOST_USER + '>', [new_email]) + messages.success(request, 'Verification email was sent! Please check your email.') + return HttpResponseRedirect(request.META.get('HTTP_REFERER')) + else: + messages.error(request, 'Unable to change email! Please try again later.') + return HttpResponseRedirect(request.META.get('HTTP_REFERER')) + +def change_email(request, uidb64, token): + try: + uid = urlsafe_base64_decode(uidb64).decode() + user = User.objects.get(pk=uid) + new_email = EmailChangeTokenGenerator().decrypt(token) + except (TypeError, ValueError, OverflowError, User.DoesNotExist): + user = None + if user is not None: + user.email = new_email + user.save() + messages.success(request, 'Email was successfully changed!') + return redirect('/account') + else: + messages.error(request, 'The verification link is invalid!') + return redirect('/') -- cgit v1.2.3