diff --git a/bugsink/urls.py b/bugsink/urls.py index e56579b..db41675 100644 --- a/bugsink/urls.py +++ b/bugsink/urls.py @@ -7,7 +7,7 @@ from django.contrib.auth import views as auth_views from alerts.views import debug_email as debug_alerts_email from users.views import debug_email as debug_users_email from bugsink.app_settings import get_settings -from users.views import signup, confirm_email +from users.views import signup, confirm_email, resend_confirmation from .views import home, trigger_error, favicon @@ -21,6 +21,7 @@ urlpatterns = [ path('', home, name='home'), path("accounts/signup/", signup, name="signup"), + path("accounts/resend-confirmation/", resend_confirmation, name="resend_confirmation"), path("accounts/confirm-email//", confirm_email, name="confirm_email"), path("accounts/login/", auth_views.LoginView.as_view(template_name="bugsink/login.html"), name="login"), diff --git a/templates/signup.html b/templates/signup.html index 6e8f097..7234ee6 100644 --- a/templates/signup.html +++ b/templates/signup.html @@ -23,7 +23,7 @@
{{ error }}
{% endfor %} {% elif form.username.help_text %} -
{{ form.username.help_text }}
+
{{ form.username.help_text|safe }}
{% endif %} @@ -34,7 +34,7 @@
{{ error }}
{% endfor %} {% elif form.password1.help_text %} -
{{ form.password1.help_text }}
+
{{ form.password1.help_text|safe }}
{% endif %} @@ -45,7 +45,7 @@
{{ error }}
{% endfor %} {% elif form.password2.help_text %} -
{{ form.password2.help_text }}
+
{{ form.password2.help_text|safe }}
{% endif %} diff --git a/users/forms.py b/users/forms.py index 0e04e15..f8cd92a 100644 --- a/users/forms.py +++ b/users/forms.py @@ -1,9 +1,14 @@ +import urllib.parse + +from django import forms +from django.urls import reverse from django.contrib.auth.forms import UserCreationForm as BaseUserCreationForm from django.core.validators import EmailValidator from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError from django.contrib.auth import password_validation from django.forms import ModelForm +from django.utils.html import escape, mark_safe UserModel = get_user_model() @@ -30,6 +35,14 @@ class UserCreationForm(BaseUserCreationForm): model = UserModel fields = ("username",) + def clean_username(self): + if UserModel.objects.filter(username=self.cleaned_data['username'], is_active=False).exists(): + raise ValidationError(mark_safe( + 'This email is already registered but not yet confirmed. Please check your email for the confirmation ' + 'link or request it again.')) + return self.cleaned_data['username'] + def _post_clean(self): # copy of django.contrib.auth.forms.UserCreationForm._post_clean; but with password1 instead of password2; I'd # say it's better UX to complain where the original error is made @@ -51,3 +64,7 @@ class UserCreationForm(BaseUserCreationForm): if commit: user.save() return user + + +class ResendConfirmationForm(forms.Form): + email = forms.EmailField() diff --git a/users/templates/users/resend_confirmation.html b/users/templates/users/resend_confirmation.html new file mode 100644 index 0000000..8f476c0 --- /dev/null +++ b/users/templates/users/resend_confirmation.html @@ -0,0 +1,42 @@ +{% extends "barest_base.html" %} +{% load static %} + +{% block title %}Resend confirmation ยท {{ site_title }}{% endblock %} + +{% block content %} + +
{# the cyan background #} +
{# the centered box #} +
{# the logo #} + Bugsink +
+ +
+ +
+ {% csrf_token %} + +
+ + {% if form.email.errors %} + {% for error in form.email.errors %} +
{{ error }}
+ {% endfor %} + {% elif form.email.help_text %} +
{{ form.email.help_text|safe }}
+ {% endif %} +
+ + +
+ + +
+ +
+
+ +{% endblock %} diff --git a/users/views.py b/users/views.py index 4b4aa54..de08dc8 100644 --- a/users/views.py +++ b/users/views.py @@ -8,7 +8,7 @@ from django.utils import timezone from bugsink.app_settings import get_settings, CB_ANYBODY -from .forms import UserCreationForm +from .forms import UserCreationForm, ResendConfirmationForm from .models import EmailVerification from .tasks import send_confirm_email @@ -69,6 +69,24 @@ def confirm_email(request, token): return render(request, "users/email_confirmed.html") +def resend_confirmation(request): + if request.method == 'POST': + form = ResendConfirmationForm(request.POST) + + if form.is_valid(): + user = UserModel.objects.get(username=form.cleaned_data['email']) + if user.is_active: + raise Http404("This email is already confirmed.") + + verification = EmailVerification.objects.create(user=user, email=user.username) + send_confirm_email.delay(user.username, verification.token) + return render(request, "users/confirm_email_sent.html", {"email": user.username}) + else: + form = ResendConfirmationForm(data=request.GET) + + return render(request, "users/resend_confirmation.html", {"form": form}) + + DEBUG_CONTEXTS = { "confirm_email": { "site_title": get_settings().SITE_TITLE,