Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions password_reset/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from django.template import loader
from django.utils import timezone
from django.views import generic
from django.contrib.auth.hashers import get_hasher

from .forms import PasswordRecoveryForm, PasswordResetForm
from .utils import get_user_model, get_username
Expand All @@ -20,6 +21,9 @@ class SaltMixin(object):
salt = 'password_recovery'
url_salt = 'password_recovery_url'

def hash_password(self, psw):
return get_hasher().encode(psw, self.salt)


def loads_with_timestamp(value, salt):
"""Returns the unsigned value along with its timestamp, the time when it
Expand Down Expand Up @@ -82,7 +86,14 @@ def send_notification(self):
'site': self.get_site(),
'user': self.user,
'username': get_username(self.user),
'token': signing.dumps(self.user.pk, salt=self.salt),
'token': signing.dumps(
{
'pk': self.user.pk,
'psw': self.hash_password(
self.user.password
)
},
salt=self.salt),
'secure': self.request.is_secure(),
}
body = loader.render_to_string(self.email_template_name,
Expand Down Expand Up @@ -121,12 +132,25 @@ def dispatch(self, request, *args, **kwargs):
self.kwargs = kwargs

try:
pk = signing.loads(kwargs['token'], max_age=self.token_expires,
salt=self.salt)
unsigned_pk_hash = signing.loads(kwargs['token'],
max_age=self.token_expires,
salt=self.salt)
except signing.BadSignature:
return self.invalid()

try:
pk = unsigned_pk_hash['pk']
password = unsigned_pk_hash['psw']
except KeyError:
return self.invalid()

self.user = get_object_or_404(get_user_model(), pk=pk)

# Ensure the hashed password is same to prevent link to be reused
# TODO: this is assuming the password is changed
if password != self.hash_password(self.user.password):
return self.invalid()

return super(Reset, self).dispatch(request, *args, **kwargs)

def invalid(self):
Expand Down