NDOJ/judge/views/email.py

122 lines
4.2 KiB
Python
Raw Permalink Normal View History

2023-08-25 20:36:38 +00:00
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
2023-08-26 04:50:03 +00:00
from django.contrib.auth.hashers import check_password
2023-08-25 20:36:38 +00:00
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"))
2023-08-26 04:50:03 +00:00
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
def __init__(self, *args, **kwargs):
self.user = kwargs.pop("user", None)
super().__init__(*args, **kwargs)
2023-08-25 20:36:38 +00:00
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
2023-08-26 04:50:03 +00:00
def clean_password(self):
password = self.cleaned_data.get("password")
if not self.user.check_password(password):
raise forms.ValidationError("Invalid password")
return password
2023-08-25 20:36:38 +00:00
@login_required
def email_change_view(request):
2023-08-26 04:50:03 +00:00
form = EmailChangeForm(request.POST or None, user=request.user)
2023-08-25 20:36:38 +00:00
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
2023-08-25 20:44:27 +00:00
subject = settings.SITE_NAME + " - " + _("Email Change Request")
2023-08-25 20:36:38 +00:00
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)
2023-08-25 20:58:59 +00:00
send_mail(
subject,
message,
settings.EMAIL_HOST_USER,
[new_email],
html_message=message,
)
2023-08-25 20:36:38 +00:00
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):
profile = Profile.objects.get(user=user)
new_email = profile.email_change_pending
if new_email and not User.objects.filter(email=new_email).exists():
2023-08-25 20:36:38 +00:00
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"),
},
)