Skip to content

Commit

Permalink
Complete Password Reset Customization
Browse files Browse the repository at this point in the history
Instead of the standard Django password reset pages,
I have added custom password reset pages.
In addition, I've added further RegEx for
defensive programming for login/registration.
  • Loading branch information
TravelTimN committed Jul 5, 2019
1 parent d5daffa commit 39749a2
Show file tree
Hide file tree
Showing 12 changed files with 404 additions and 238 deletions.
44 changes: 27 additions & 17 deletions project/accounts/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from accounts.models import Profile


Expand All @@ -18,49 +19,58 @@ class UserRegistrationForm(UserCreationForm):
label="Username",
min_length=5,
max_length=15,
widget=forms.TextInput(attrs={"autocomplete": "new-password"}),
widget=forms.TextInput(),
required=True)
email = forms.CharField(
label="Email Address",
min_length=5,
max_length=75,
widget=forms.EmailInput(attrs={"autocomplete": "new-password"}),
widget=forms.EmailInput(),
required=True)
first_name = forms.CharField(
label="First Name",
min_length=2,
max_length=40,
widget=forms.TextInput(attrs={"autocomplete": "new-password"}),
widget=forms.TextInput(),
required=True)
last_name = forms.CharField(
label="Last Name",
min_length=2,
max_length=40,
widget=forms.TextInput(attrs={"autocomplete": "new-password"}),
widget=forms.TextInput(),
required=True)
password1 = forms.CharField(
label="Password",
min_length=5,
max_length=20,
widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}),
required=True)
min_length=8,
max_length=25,
widget=forms.PasswordInput(),
required=True,
validators=[RegexValidator(
"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&-]{8,25}$",
message=("Passwords should contain a lowercase (a-z),\
an uppercase (A-Z), and a number (0-9).\
Optional special characters: @$!%*?&-"))])
password2 = forms.CharField(
label="Repeat Password",
min_length=5,
max_length=20,
widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}),
min_length=8,
max_length=25,
widget=forms.PasswordInput(),
required=True)

class Meta:
model = User
fields = ["username", "email", "first_name", "last_name", "password1", "password2"]
fields = [
"username", "email",
"first_name", "last_name",
"password1", "password2"]

def clean_email(self):
email = self.cleaned_data.get("email")
username = self.cleaned_data.get("username")
if User.objects.filter(
email=email).exclude(username=username):
raise forms.ValidationError("Email address must be unique")
raise forms.ValidationError(
f"A user with that email address already exists.")
return email

def clean_password2(self):
Expand All @@ -78,25 +88,25 @@ class UserUpdateForm(forms.ModelForm):
label="Username",
min_length=5,
max_length=15,
widget=forms.TextInput(attrs={"autocomplete": "new-password"}),
widget=forms.TextInput(),
required=False)
email = forms.CharField(
label="Email Address",
min_length=5,
max_length=75,
widget=forms.EmailInput(attrs={"autocomplete": "new-password"}),
widget=forms.EmailInput(),
required=False)
first_name = forms.CharField(
label="First Name",
min_length=2,
max_length=40,
widget=forms.TextInput(attrs={"autocomplete": "new-password"}),
widget=forms.TextInput(),
required=False)
last_name = forms.CharField(
label="Last Name",
min_length=2,
max_length=40,
widget=forms.TextInput(attrs={"autocomplete": "new-password"}),
widget=forms.TextInput(),
required=False)

class Meta:
Expand Down
4 changes: 2 additions & 2 deletions project/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class Profile(models.Model):
def __str__(self):
return f"{self.user.username}'s Profile"

def save(self):
super().save()
def save(self, *args, **kwargs):
super(Profile, self).save(*args, **kwargs)
"""
- installed 'django-cleanup' to auto-remove old image.
- installed 'pillow' to resize larger images.
Expand Down
2 changes: 1 addition & 1 deletion project/accounts/templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
{% block content %}
<section class="form">

<h4 class="white-text text-shadow-2 center">Log In</h4>
<h3 class="white-text text-shadow-2 bold center">Log In</h3>
<div class="divider white"></div>

<form method="POST" class="text-shadow-2">
Expand Down
51 changes: 7 additions & 44 deletions project/accounts/templates/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<div class="card-content white-text">
<div class="row">
<div class="col s12 m4 center">
<img src="{{ user.profile.image.url }}" alt="{{ user }} Photo" class="responsive-img white">
<img src="{{ user.profile.image.url }}" alt="{{ user }} Photo" class="responsive-img">
</div>
<div class="col s12 m8">
<div class="row">
Expand Down Expand Up @@ -59,17 +59,17 @@ <h4 class="bold">{{ user.username }}</h4>
Profile
<i class="fas fa-user hide-on-small-and-down" aria-hidden="true"></i>
</a>
<a href="#modal-profile-password" class="btn modal-trigger amber">
<a href="{% url 'password_reset' %}" class="btn amber">
Password
<i class="fas fa-key hide-on-small-and-down" aria-hidden="true"></i>
</a>
<br class="hide-on-med-and-up">
<a href="#" class="btn red">
My Bugs
Bugs
<i class="fas fa-bug hide-on-small-and-down" aria-hidden="true"></i>
</a>
<a href="#" class="btn blue">
My Features
Features
<i class="fas fa-magic hide-on-small-and-down" aria-hidden="true"></i>
</a>
</div>
Expand All @@ -78,12 +78,10 @@ <h4 class="bold">{{ user.username }}</h4>
</div>


<!-- PROFILE MODALS -->

<!-- edit profile -->
<!-- PROFILE MODAL -->
<div id="modal-profile-edit" class="modal white-text">
<div class="modal-content center-align">
<h4>Edit Profile</h4>
<h4 class="bold">Edit Profile</h4>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="row">
Expand Down Expand Up @@ -119,39 +117,4 @@ <h4>Edit Profile</h4>
</form>
</div>
</div>

<!-- change password -->
<div id="modal-profile-password" class="modal white-text">
<div class="modal-content center-align">
<h4>Change Password</h4>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="row">
<div class="col s12 m6">

</div>
<div class="col s12 m6">

</div>
<div class="col s12 m6">

</div>
<div class="col s12 m6">

</div>
</div>
<div class="row center-align">
<div class="col s12 m6 offset-m3">
<button type="submit" class="btn btn-large green bold text-shadow-2">
Save
<i class="fas fa-save right"></i>
</button>
</div>
</div>
</form>
</div>
</div>


<!--<a href="{% url 'password_reset' %}">Reset Password</a>-->
{% endblock %}
{% endblock %}
2 changes: 1 addition & 1 deletion project/accounts/templates/register.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
{% block content %}
<section class="form">

<h4 class="white-text text-shadow-2 center">Register</h4>
<h3 class="white-text text-shadow-2 bold center">Register</h3>
<div class="divider white"></div>

<form method="POST" class="text-shadow-2">
Expand Down
4 changes: 2 additions & 2 deletions project/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def login(request):
return redirect(reverse("profile"))
else:
messages.error(
request, f"Your username or password is incorrect.")
request, f"Username or Password is incorrect.")
else:
login_form = UserLoginForm()

Expand Down Expand Up @@ -68,7 +68,7 @@ def register(request):
return redirect(reverse("profile"))
else:
messages.error(
request, f"Error with registration, please try again!")
request, f"Error with registration. Please try again!")
else:
register_form = UserRegistrationForm()

Expand Down
7 changes: 7 additions & 0 deletions project/main/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,10 @@

# KILL SESSION ON CLOSE
SESSION_EXPIRE_AT_BROWSER_CLOSE = True

# PASSWORD RESET SETTINGS
EMAIL_USE_TLS = True
EMAIL_HOST = "smtp.gmail.com"
EMAIL_HOST_USER = os.getenv("EMAIL_ADDRESS")
EMAIL_HOST_PASSWORD = os.getenv("EMAIL_PASSWORD")
EMAIL_PORT = 587
Loading

0 comments on commit 39749a2

Please sign in to comment.