Skip to content

Commit

Permalink
Merge pull request #19 from slavistoev/password-reset
Browse files Browse the repository at this point in the history
Password reset
  • Loading branch information
TitaniumTries authored Apr 28, 2022
2 parents 91827da + cccafdf commit 12cc784
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 40 deletions.
1 change: 1 addition & 0 deletions templates/registration/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
{% csrf_token %}
{{form|crispy}}
<p>Don't have an account? Create one <a href='{% url "users:register" %}'>here.</a></p>
<p>Forgot your password? Reset it <a href='{% url "users:password_reset" %}'>here.</a></p>
<p>Resend email verification <a href='{% url "users:resend_email" %}'>here.</a></p>
<button type='submit' class='btn btn-success'>Login</button>
</form>
Expand Down
8 changes: 0 additions & 8 deletions templates/registration/password_change_done.html

This file was deleted.

4 changes: 3 additions & 1 deletion templates/registration/password_change_form.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
{% extends "base.html" %}
{% load crispy_forms_filters %}
{% load crispy_forms_tags %}

{% block title %}Change your password{% endblock %}

{% block content %}
<h1>Change your password</h1>
<p>Use the form below to change your password.</p>
<form method="post">
{{ form.as_p }}
{{ form|crispy }}
<p><input type="submit" value="Change" /></p>
{% csrf_token %}
</form>
Expand Down
15 changes: 15 additions & 0 deletions templates/registration/password_reset_confirm.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{% extends "base.html" %}
{% load crispy_forms_filters %}
{% load crispy_forms_tags %}

{% block title %}Reset your password{% endblock %}

{% block content %}
<h1>Reset your password</h1>
<p>Use the form below to reset your password.</p>
<form method="post">
{{ form|crispy }}
<p><input type="submit" value="Reset" /></p>
{% csrf_token %}
</form>
{% endblock %}
7 changes: 7 additions & 0 deletions templates/registration/password_reset_done.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% extends "base.html" %}

{% block title %}Password reset email sent.{% endblock %}

{% block content %}
<p>Haven't received an email? Resend email for password reset <a href='{% url "users:password_reset" %}'>here.</a></p>
{% endblock %}
12 changes: 12 additions & 0 deletions templates/registration/password_reset_email.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{% autoescape off %}


Hi {{user.username}}

Please use the link below to verify your account.


http://{{domain}}{% url 'users:password_reset_confirm' uidb64=uid token=token %}


{% endautoescape %}
16 changes: 16 additions & 0 deletions templates/registration/password_reset_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% extends "base.html" %}
{% load crispy_forms_filters %}
{% load crispy_forms_tags %}

{% block title %}Reset password through email.{% endblock %}

{% block content %}
<h1>Reset your password through email.</h1>
<p>Fill in your email to reset your password.</p>
<form method="post">
{{ form|crispy}}
<p>Resend email verification <a href='{% url "users:resend_email" %}'>here.</a></p>
<p><input type="submit" value="Reset" /></p>
{% csrf_token %}
</form>
{% endblock %}
2 changes: 2 additions & 0 deletions templates/registration/resend-email-verification.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
{% load crispy_forms_tags %}

{% block content %}
<h1>Resend email verification.</h1>
<p>Fill in your email to receive another verification.</p>
<form method='POST' class='form-group'>
{% csrf_token %}
{{form|crispy}}
Expand Down
6 changes: 6 additions & 0 deletions templates/registration/reset-fail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% extends "base.html" %}
{% block title %}Password reset failed{% endblock %}

{% block content %}
<p>Resend email for password reset <a href='{% url "users:password_reset" %}'>here.</a></p>
{% endblock %}
96 changes: 90 additions & 6 deletions users/forms.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
from urllib import request
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, UsernameField, UserChangeForm
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, UsernameField, PasswordResetForm
from django.forms import ModelForm
from django.utils.translation import gettext_lazy as _
from django.utils.safestring import mark_safe

from .models import CustomUser

from django.core.exceptions import ValidationError
from .utilities import send_verification_email
from django.contrib.auth import authenticate


class CustomUserCreationForm(UserCreationForm):
class Meta:
Expand All @@ -30,11 +36,89 @@ class CustomUserAuthenticationForm(AuthenticationForm):
error_messages = {
**AuthenticationForm.error_messages,
'invalid_login': _(
"Please enter a correct username or email, and password. Note that both fields may be case-sensitive."
mark_safe("Please enter a correct username or email, and password.<br/>Note that both fields may be case-sensitive.")
),
}

class ResendEmailVerificationForm(ModelForm):
class Meta:
model = CustomUser
fields = ("email",)
def clean(self):
username = self.cleaned_data.get("username")
password = self.cleaned_data.get("password")
if username is not None and password:
self.user_cache = authenticate(
self.request, username=username, password=password
)
if self.user_cache is None:
self.add_error('username', ValidationError(
self.error_messages["invalid_login"],
code="invalid_login",
params={"username": self.username_field.verbose_name},
))
self.add_error('password', '')
else:
self.confirm_login_allowed(self.user_cache)
return self.cleaned_data


class ResendEmailVerificationForm(forms.Form):
email = forms.EmailField(
label=_("Email"),
max_length=254,
widget=forms.EmailInput(attrs={"autocomplete": "email"}),
)

error_messages = {
"user_not_found": _("User with this email not found!"),
"email_already_verified": _("User\'s email already verified!"),
}

def clean_email(self):
email = self.cleaned_data['email']
try:
self.user = CustomUser.objects.get(email__iexact=email)
except Exception as e:
self.user = None

if self.user:
if self.user.email_verified == True:
raise ValidationError(
self.error_messages["email_already_verified"],
code="email_already_verified",
)
else:
raise ValidationError(
self.error_messages["user_not_found"],
code="user_not_found",
)

return email

def save(self, request):
send_verification_email(request, self.user)


class CustomPasswordResetForm(PasswordResetForm):
error_messages = {
"user_not_found": _("User with this email not found!"),
"email_not_verified": _("User's email is not verified!"),
}

def clean_email(self):
email = self.cleaned_data['email']
try:
self.user = CustomUser.objects.get(email__iexact=email)
except Exception as e:
self.user = None

if self.user:
if self.user.email_verified == False:
raise ValidationError(
self.error_messages["email_not_verified"],
code="email_not_verified",
)
else:
raise ValidationError(
self.error_messages["user_not_found"],
code="user_not_found",
)

return email
4 changes: 4 additions & 0 deletions users/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
from django.contrib.auth.decorators import login_required
from . import views
from django.views.generic import TemplateView
from django.contrib.auth.views import PasswordResetDoneView, PasswordResetCompleteView

urlpatterns = [
path('register/', views.SignUpView.as_view(), name='register'),
path('login/', views.CustomLoginView.as_view(), name='login'),
path("password_change/", views.CustomPasswordChangeView.as_view(), name="password_change"),
path("password_reset/", views.CustomPasswordResetView.as_view(), name="password_reset"),
path("reset/<uidb64>/<token>/", views.CustomPasswordResetConfirmView.as_view(), name="password_reset_confirm"),
path('', include('django.contrib.auth.urls')),
path('dashboard/', login_required(TemplateView.as_view(template_name="users/dashboard.html")), name='dashboard'),
path('edit/', views.EditView.as_view(), name='edit_account'),
Expand Down
Loading

0 comments on commit 12cc784

Please sign in to comment.