Switched newsletterissue numbering to a more generic field. Added newsletterview...
[philo.git] / contrib / waldo / tokens.py
1 """
2 Based on django.contrib.auth.tokens
3 """
4
5
6 from datetime import date
7 from django.conf import settings
8 from django.utils.http import int_to_base36, base36_to_int
9 from django.contrib.auth.tokens import PasswordResetTokenGenerator
10
11
12 REGISTRATION_TIMEOUT_DAYS = getattr(settings, 'WALDO_REGISTRATION_TIMEOUT_DAYS', 1)
13 EMAIL_TIMEOUT_DAYS = getattr(settings, 'WALDO_EMAIL_TIMEOUT_DAYS', 1)
14
15
16 class RegistrationTokenGenerator(PasswordResetTokenGenerator):
17         """
18         Strategy object used to generate and check tokens for the user registration mechanism.
19         """
20         def check_token(self, user, token):
21                 """
22                 Check that a registration token is correct for a given user.
23                 """
24                 # If the user is active, the hash can't be valid.
25                 if user.is_active:
26                         return False
27                 
28                 # Parse the token
29                 try:
30                         ts_b36, hash = token.split('-')
31                 except ValueError:
32                         return False
33                 
34                 try:
35                         ts = base36_to_int(ts_b36)
36                 except ValueError:
37                         return False
38                 
39                 # Check that the timestamp and uid have not been tampered with.
40                 if self._make_token_with_timestamp(user, ts) != token:
41                         return False
42                 
43                 # Check that the timestamp is within limit
44                 if (self._num_days(self._today()) - ts) > REGISTRATION_TIMEOUT_DAYS:
45                         return False
46                 
47                 return True
48         
49         def _make_token_with_timestamp(self, user, timestamp):
50                 ts_b36 = int_to_base36(timestamp)
51                 
52                 # By hashing on the internal state of the user and using state that is
53                 # sure to change, we produce a hash that will be invalid as soon as it
54                 # is used.
55                 from django.utils.hashcompat import sha_constructor
56                 hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + unicode(user.is_active) + user.last_login.strftime('%Y-%m-%d %H:%M:%S') + unicode(timestamp)).hexdigest()[::2]
57                 return '%s-%s' % (ts_b36, hash)
58
59
60 registration_token_generator = RegistrationTokenGenerator()
61
62
63 class EmailTokenGenerator(PasswordResetTokenGenerator):
64         """
65         Strategy object used to generate and check tokens for a user email change mechanism.
66         """
67         def make_token(self, user, email):
68                 """
69                 Returns a token that can be used once to do an email change for the given user and email.
70                 """
71                 return self._make_token_with_timestamp(user, email, self._num_days(self._today()))
72         
73         def check_token(self, user, email, token):
74                 if email == user.email:
75                         return False
76                 
77                 # Parse the token
78                 try:
79                         ts_b36, hash = token.split('-')
80                 except ValueError:
81                         return False
82                 
83                 try:
84                         ts = base36_to_int(ts_b36)
85                 except ValueError:
86                         return False
87                 
88                 # Check that the timestamp and uid have not been tampered with.
89                 if self._make_token_with_timestamp(user, email, ts) != token:
90                         return False
91                 
92                 # Check that the timestamp is within limit
93                 if (self._num_days(self._today()) - ts) > EMAIL_TIMEOUT_DAYS:
94                         return False
95                 
96                 return True
97         
98         def _make_token_with_timestamp(self, user, email, timestamp):
99                 ts_b36 = int_to_base36(timestamp)
100                 
101                 from django.utils.hashcompat import sha_constructor
102                 hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + user.email + email + unicode(timestamp)).hexdigest()[::2]
103                 return '%s-%s' % (ts_b36, hash)
104
105
106 email_token_generator = EmailTokenGenerator()