Skip to content

Commit

Permalink
Merge pull request #134 from incuna/verify-token-age
Browse files Browse the repository at this point in the history
Make token expires for AccountVerifyView
  • Loading branch information
LilyFoote committed Sep 2, 2015
2 parents bfdf713 + db0d6e2 commit 8a40bd8
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 1 deletion.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## v13.1.0

* Make token to verify account to expires if `VERIFY_ACCOUNT_EXPIRY` is set to
a value in seconds.

### Notes

* If `VERIFY_ACCOUNT_EXPIRY` is not set the token will never expire.

## v13.0.0

* Make `RegistrationSerializer` and `EmailSerializerBase` fields a tuple.
Expand Down
26 changes: 26 additions & 0 deletions user_management/api/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from django.core import mail
from django.core.cache import cache
from django.core.urlresolvers import reverse
from django.test.utils import override_settings
from django.utils import timezone
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
Expand Down Expand Up @@ -676,6 +677,31 @@ def test_post_invalid_token(self):
response = view(request, token=token)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_default_expiry_token(self):
"""Assert `DEFAULT_VERIFY_ACCOUNT_EXPIRY` doesn't expire by default."""
user = UserFactory.create()
token = user.generate_validation_token()
request = self.create_request('post', auth=False)
view = self.view_class.as_view()

with patch('django.core.signing.loads') as signing_loads:
signing_loads.return_value = {'email': user.email}
view(request, token=token)

signing_loads.assert_called_once_with(token, max_age=None)

@override_settings(VERIFY_ACCOUNT_EXPIRY=0)
def test_post_expired_token(self):
"""Assert token expires."""
user = UserFactory.create()
token = user.generate_validation_token()
request = self.create_request('post', auth=False)
view = self.view_class.as_view()

response = view(request, token=token)

self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_post_verified_email(self):
"""Assert verified user cannot verify email."""
user = UserFactory.create(email_verified=True)
Expand Down
13 changes: 12 additions & 1 deletion user_management/api/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.conf import settings
from django.contrib.auth import get_user_model, signals
from django.contrib.auth.tokens import default_token_generator
from django.core import signing
Expand Down Expand Up @@ -217,15 +218,25 @@ class VerifyAccountView(views.APIView):
"""
permission_classes = [AllowAny]
ok_message = _('Your account has been verified.')
# Default token never expires.
DEFAULT_VERIFY_ACCOUNT_EXPIRY = None

def initial(self, request, *args, **kwargs):
"""
Use `token` to allow one-time access to a view.
Token expiry can be set in `settings` with `VERIFY_ACCOUNT_EXPIRY` and is
set in seconds.
Set user as a class attribute or raise an `InvalidExpiredToken`.
"""
try:
email_data = signing.loads(kwargs['token'])
max_age = settings.VERIFY_ACCOUNT_EXPIRY
except AttributeError:
max_age = self.DEFAULT_VERIFY_ACCOUNT_EXPIRY

try:
email_data = signing.loads(kwargs['token'], max_age=max_age)
except signing.BadSignature:
raise exceptions.InvalidExpiredToken

Expand Down

0 comments on commit 8a40bd8

Please sign in to comment.