diff --git a/misago/account/forms.py b/misago/account/forms.py index 4fb3c28d1e..c4338feb1e 100644 --- a/misago/account/forms.py +++ b/misago/account/forms.py @@ -364,12 +364,6 @@ def clean(self): ), ) - self.email_cache = cleaned_data["new_email"] - - if not self.errors: - self["new_email"].value = "" - self["confirm_email"].value = "" - return cleaned_data diff --git a/misago/account/views/settings.py b/misago/account/views/settings.py index dfda0a4069..320de18f1c 100644 --- a/misago/account/views/settings.py +++ b/misago/account/views/settings.py @@ -2,11 +2,11 @@ from django.conf import settings from django.contrib import messages -from django.contrib.auth import logout +from django.contrib.auth import get_user_model, logout from django.core.exceptions import PermissionDenied from django.forms import Form from django.http import Http404, HttpRequest, HttpResponse -from django.shortcuts import redirect, render +from django.shortcuts import get_object_or_404, redirect, render from django.utils.translation import gettext as _, pgettext, pgettext_lazy from django.views import View @@ -36,6 +36,8 @@ ) from ..menus import account_settings_menu +User = get_user_model() + def raise_if_not_authenticated(request): if not request.user.is_authenticated: @@ -103,15 +105,21 @@ def get(self, request: HttpRequest) -> HttpResponse: def post(self, request: HttpRequest) -> HttpResponse: form = self.get_form_instance(request) if form.is_valid(): - self.save_form(request, form) + return self.handle_valid_form(request, form) - messages.success(request, self.success_message) + return self.handle_invalid_form(request, form) + + def handle_valid_form(self, request: HttpRequest, form: Form) -> HttpResponse: + self.save_form(request, form) - if request.is_htmx and self.template_htmx_name: - return self.render(request, self.template_htmx_name, {"form": form}) + messages.success(request, self.success_message) + + if request.is_htmx and self.template_htmx_name: + return self.render(request, self.template_htmx_name, {"form": form}) - return redirect(request.path_info) + return redirect(request.path_info) + def handle_invalid_form(self, request: HttpRequest, form: Form) -> HttpResponse: messages.error(request, _("Form contains errors")) if request.is_htmx and self.template_htmx_name: @@ -273,10 +281,11 @@ def save_form(self, request: HttpRequest, form: Form) -> None: class AccountEmailView(AccountSettingsFormView): template_name = "misago/account/settings/email.html" template_htmx_name = "misago/account/settings/email_form.html" - email_template_name = "misago/emails/email_change_confirm" + template_htmx_success_name = "misago/account/settings/email_form_completed.html" + email_template_name = "misago/emails/email_confirm_change" success_message = pgettext_lazy( - "account settings email confirm", "Confirm email change" + "account settings email confirm", "Confirmation email sent" ) def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: @@ -285,6 +294,16 @@ def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpRespo return super().dispatch(request, *args, **kwargs) + def get(self, request: HttpRequest) -> HttpResponse: + form = self.get_form_instance(request) + + if request.is_htmx: + template_name = self.template_htmx_name + else: + template_name = self.template_name + + return self.render(request, template_name, {"form": form}) + def get_form_instance(self, request: HttpRequest) -> AccountEmailForm: if request.method == "POST": return AccountEmailForm( @@ -298,6 +317,20 @@ def get_form_instance(self, request: HttpRequest) -> AccountEmailForm: request=request, ) + def handle_valid_form(self, request: HttpRequest, form: Form) -> HttpResponse: + self.save_form(request, form) + + if request.is_htmx and self.template_htmx_name: + messages.success(request, self.success_message) + return self.render( + request, + self.template_htmx_success_name, + {"new_email": form.cleaned_data["new_email"]}, + ) + + request.session["misago_new_email"] = form.cleaned_data["new_email"] + return redirect(request.path_info) + def save_form(self, request: HttpRequest, form: Form) -> None: new_email = form.cleaned_data["new_email"] token = create_email_change_token(request.user, form.cleaned_data["new_email"]) @@ -308,7 +341,7 @@ def save_form(self, request: HttpRequest, form: Form) -> None: mail = build_mail( request.user, pgettext( - "email change confirm email subject", + "email confirm change email subject", "Change your email on the %(forum_name)s forums", ) % {"forum_name": request.settings.forum_name}, @@ -322,6 +355,42 @@ def save_form(self, request: HttpRequest, form: Form) -> None: mail.send(fail_silently=True) +def account_email_change_confirm_sent(request): + new_email = request.session.pop("misago_new_email", None) + if not new_email: + raise Http404() + + return render( + request, + "misago/account/settings/email_confirm_sent.html", + {"new_email": new_email}, + ) + + +def account_email_change_confirm(request, user_id, token): + user = get_object_or_404(User.objects, id=user_id, is_active=True) + + try: + new_email = read_email_change_token(user, token) + except EmailChangeTokenError: + raise NotImplementedError("TODO") + + # TODO: verify user is not banned + # TODO: verify new email is still valid + + if new_email != user.email: + user.set_email(new_email) + user.save() + + # TODO: write template + # TODO: write tests + return render( + request, + "misago/account/settings/email_changed.html", + {"username": user.username}, + ) + + class AccountDownloadDataView(AccountSettingsView): template_name = "misago/account/settings/download_data.html" template_htmx_name = "misago/account/settings/download_data_form.html" diff --git a/misago/templates/misago/account/settings/email_form.html b/misago/templates/misago/account/settings/email_form.html index 0940797b5b..8816c94a96 100644 --- a/misago/templates/misago/account/settings/email_form.html +++ b/misago/templates/misago/account/settings/email_form.html @@ -3,23 +3,6 @@ {% include "misago/snackbars.html" %} {% endif %}
- {% if form.email_cache %} -
-
-

- {% trans "Confirm email address change" context "account email page" %} -

-
-
- {% capture trimmed as new_email %} - {{ form.email_cache }} - {% endcapture %} - {% blocktrans trimmed with email=new_email|safe context "account email page" %} - To confirm the change of your email address please click the confirmation link in a message that was sent to "{{ email }}". - {% endblocktrans %} -
-
- {% endif %}
+
+
+

+ {% trans "Confirm email address change" context "account email page" %} +

+
+
+ {% capture trimmed as new_email %} + {{ new_email }} + {% endcapture %} +

+ {% blocktrans trimmed with email=new_email|safe context "account email page" %} + To confirm the change of your email address please click the confirmation link in a message that was sent to "{{ email }}". + {% endblocktrans %} +

+
+ +
+
\ No newline at end of file diff --git a/misago/templates/misago/emails/email_change_confirm.html b/misago/templates/misago/emails/email_confirm_change.html similarity index 78% rename from misago/templates/misago/emails/email_change_confirm.html rename to misago/templates/misago/emails/email_confirm_change.html index ae29db1712..69234508e4 100644 --- a/misago/templates/misago/emails/email_change_confirm.html +++ b/misago/templates/misago/emails/email_confirm_change.html @@ -3,15 +3,15 @@ {% block content %} -{% blocktrans trimmed with user=user context "email change confirm email" %} +{% blocktrans trimmed with user=user context "email confirm change email" %} {{ user }}, you are receiving this message because you are changing your e-mail address. {% endblocktrans %}

-{% trans "Confirm change" context "email change confirm email cta" %} +{% trans "Confirm change" context "email confirm change email cta" %}

-{% blocktrans trimmed count expires_in=expires_in context "email change confirm email" %} +{% blocktrans trimmed count expires_in=expires_in context "email confirm change email" %} This link will remain active for {{ expires_in }} hour from the time this message has been sent. {% plural %} This link will remain active for {{ expires_in }} hours from the time this message has been sent. diff --git a/misago/templates/misago/emails/email_change_confirm.txt b/misago/templates/misago/emails/email_confirm_change.txt similarity index 79% rename from misago/templates/misago/emails/email_change_confirm.txt rename to misago/templates/misago/emails/email_confirm_change.txt index 3767ed0a23..4fa97547c5 100644 --- a/misago/templates/misago/emails/email_change_confirm.txt +++ b/misago/templates/misago/emails/email_confirm_change.txt @@ -3,16 +3,16 @@ {% block content %} -{% blocktrans trimmed with user=user context "email change confirm email" %} +{% blocktrans trimmed with user=user context "email confirm change email" %} {{ user }}, you are receiving this message because you are changing your e-mail address. {% endblocktrans %} -{% blocktrans trimmed context "email change confirm email" %} +{% blocktrans trimmed context "email confirm change email" %} To confirm the change, click the following link: {% endblocktrans %} {{ settings.forum_address }}{{ token }} -{% blocktrans trimmed count expires_in=expires_in context "email change confirm email" %} +{% blocktrans trimmed count expires_in=expires_in context "email confirm change email" %} This link will remain active for {{ expires_in }} hour from the time this message has been sent. {% plural %} This link will remain active for {{ expires_in }} hours from the time this message has been sent.