diff options
Diffstat (limited to 'webapp/django/contrib/auth/tokens.py')
-rw-r--r-- | webapp/django/contrib/auth/tokens.py | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/webapp/django/contrib/auth/tokens.py b/webapp/django/contrib/auth/tokens.py new file mode 100644 index 0000000000..c9b353583c --- /dev/null +++ b/webapp/django/contrib/auth/tokens.py @@ -0,0 +1,66 @@ +from datetime import date +from django.conf import settings +from django.utils.http import int_to_base36, base36_to_int + +class PasswordResetTokenGenerator(object): + """ + Stratgy object used to generate and check tokens for the password + reset mechanism. + """ + def make_token(self, user): + """ + Returns a token that can be used once to do a password reset + for the given user. + """ + return self._make_token_with_timestamp(user, self._num_days(self._today())) + + def check_token(self, user, token): + """ + Check that a password reset token is correct for a given user. + """ + # Parse the tokem + try: + ts_b36, hash = token.split("-") + except ValueError: + return False + + try: + ts = base36_to_int(ts_b36) + except ValueError: + return False + + # Check that the timestamp/uid has not been tampered with + if self._make_token_with_timestamp(user, ts) != token: + return False + + # Check the timestamp is within limit + if (self._num_days(self._today()) - ts) > settings.PASSWORD_RESET_TIMEOUT_DAYS: + return False + + return True + + def _make_token_with_timestamp(self, user, timestamp): + # timestamp is number of days since 2001-1-1. Converted to + # base 36, this gives us a 3 digit string until about 2121 + ts_b36 = int_to_base36(timestamp) + + # By hashing on the internal state of the user and using state + # that is sure to change (the password salt will change as soon as + # the password is set, at least for current Django auth, and + # last_login will also change), we produce a hash that will be + # invalid as soon as it is used. + # We limit the hash to 20 chars to keep URL short + from django.utils.hashcompat import sha_constructor + hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + + user.password + unicode(user.last_login) + + unicode(timestamp)).hexdigest()[::2] + return "%s-%s" % (ts_b36, hash) + + def _num_days(self, dt): + return (dt - date(2001,1,1)).days + + def _today(self): + # Used for mocking in tests + return date.today() + +default_token_generator = PasswordResetTokenGenerator() |