105 lines
3.5 KiB
Python
105 lines
3.5 KiB
Python
|
from django.contrib.auth.tokens import default_token_generator
|
||
|
from django.core.mail import send_mail
|
||
|
from django.shortcuts import render, redirect
|
||
|
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
|
||
|
from django.utils.encoding import force_bytes, force_text
|
||
|
from django.conf import settings
|
||
|
from django import forms
|
||
|
from django.utils.translation import gettext_lazy as _
|
||
|
from django.urls import reverse
|
||
|
from django.contrib.auth.decorators import login_required
|
||
|
from django.contrib.auth.models import User
|
||
|
|
||
|
from urllib.parse import urlencode, urlunparse, urlparse
|
||
|
|
||
|
from judge.models import Profile
|
||
|
from judge.utils.email_render import render_email_message
|
||
|
|
||
|
|
||
|
class EmailChangeForm(forms.Form):
|
||
|
new_email = forms.EmailField(label=_("New Email"))
|
||
|
|
||
|
def clean_new_email(self):
|
||
|
new_email = self.cleaned_data.get("new_email")
|
||
|
if User.objects.filter(email=new_email).exists():
|
||
|
raise forms.ValidationError(_("An account with this email already exists."))
|
||
|
return new_email
|
||
|
|
||
|
|
||
|
@login_required
|
||
|
def email_change_view(request):
|
||
|
form = EmailChangeForm(request.POST or None)
|
||
|
|
||
|
if request.method == "POST" and form.is_valid():
|
||
|
new_email = request.POST.get("new_email")
|
||
|
user = request.user
|
||
|
profile = request.profile
|
||
|
|
||
|
# Generate a token for email verification
|
||
|
token = default_token_generator.make_token(user)
|
||
|
uid = urlsafe_base64_encode(force_bytes(user.pk))
|
||
|
|
||
|
# Send the email to the user
|
||
|
subject = _(f"{settings.SITE_NAME} - Email Change Request")
|
||
|
email_contexts = {
|
||
|
"message": _(
|
||
|
"We have received a request to change your email to this email. Click the button below to change your email:"
|
||
|
),
|
||
|
"title": _("Email Change"),
|
||
|
"button_text": _("Change Email"),
|
||
|
"url_path": reverse(
|
||
|
"email_change_verify", kwargs={"uidb64": uid, "token": token}
|
||
|
),
|
||
|
}
|
||
|
message = render_email_message(request, email_contexts)
|
||
|
send_mail(subject, message, settings.EMAIL_HOST_USER, [new_email])
|
||
|
profile.email_change_pending = new_email
|
||
|
profile.save()
|
||
|
return redirect("email_change_pending")
|
||
|
|
||
|
return render(
|
||
|
request,
|
||
|
"email_change/email_change.html",
|
||
|
{
|
||
|
"form": form,
|
||
|
"title": _("Change email"),
|
||
|
},
|
||
|
)
|
||
|
|
||
|
|
||
|
def verify_email_view(request, uidb64, token):
|
||
|
try:
|
||
|
uid = force_text(urlsafe_base64_decode(uidb64))
|
||
|
user = User.objects.get(pk=uid)
|
||
|
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
|
||
|
user = None
|
||
|
if user is not None and default_token_generator.check_token(user, token):
|
||
|
# Update the user's email address
|
||
|
profile = Profile.objects.get(user=user)
|
||
|
new_email = profile.email_change_pending
|
||
|
if new_email:
|
||
|
user.email = new_email
|
||
|
profile.email_change_pending = None
|
||
|
user.save()
|
||
|
profile.save()
|
||
|
|
||
|
return render(
|
||
|
request,
|
||
|
"email_change/email_change_success.html",
|
||
|
{"title": _("Success"), "user": user},
|
||
|
)
|
||
|
|
||
|
return render(
|
||
|
request, "email_change/email_change_failure.html", {"title": _("Invalid")}
|
||
|
)
|
||
|
|
||
|
|
||
|
def email_change_pending_view(request):
|
||
|
return render(
|
||
|
request,
|
||
|
"email_change/email_change_pending.html",
|
||
|
{
|
||
|
"title": _("Email change pending"),
|
||
|
},
|
||
|
)
|