From e1e9d28134612ae6da30127181e432d8044001ec Mon Sep 17 00:00:00 2001 From: Camilo Nova Date: Sun, 31 Mar 2013 08:04:30 -0500 Subject: [PATCH] Tweaked failure limit so it would be more natural. Fixes #16 --- axes/decorators.py | 2 +- axes/tests.py | 29 +++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/axes/decorators.py b/axes/decorators.py index 834f13d..583a4be 100644 --- a/axes/decorators.py +++ b/axes/decorators.py @@ -333,7 +333,7 @@ def check_request(request, login_unsuccessful): user_lockable = is_user_lockable(request) # no matter what, we want to lock them out if they're past the number of # attempts allowed, unless the user is set to notlockable - if failures >= FAILURE_LIMIT and LOCK_OUT_AT_FAILURE and user_lockable: + if failures > FAILURE_LIMIT and LOCK_OUT_AT_FAILURE and user_lockable: # We log them out in case they actually managed to enter the correct # password logout(request) diff --git a/axes/tests.py b/axes/tests.py index 9391cb2..bfc7d62 100644 --- a/axes/tests.py +++ b/axes/tests.py @@ -1,7 +1,3 @@ -# Only run tests if they have axes in middleware - -# Basically a functional test - import random import string @@ -20,12 +16,15 @@ class AccessAttemptTest(TestCase): LOCKED_MESSAGE = 'Account locked: too many login attempts.' def _generate_random_string(self): - """Generates a random string""" + """Generates a random string + """ chars = string.ascii_uppercase + string.digits + return ''.join(random.choice(chars) for x in range(20)) def _random_username(self, existing_username=False): - """Returns a username, existing or not depending on params""" + """Returns a username, existing or not depending on params + """ if existing_username: return User.objects.order_by('?')[0].username @@ -40,6 +39,8 @@ class AccessAttemptTest(TestCase): return response def setUp(self): + """Creates users for testing the login + """ for i in range(0, random.randrange(10, 50)): username = "person%s" % i email = "%s@example.org" % username @@ -52,7 +53,10 @@ class AccessAttemptTest(TestCase): u.save() def test_login_max(self, existing_username=False): - for i in range(0, FAILURE_LIMIT - 1): + """Tests the login lock trying to login one more time + than failure limit + """ + for i in range(0, FAILURE_LIMIT): response = self._login(existing_username=existing_username) # Check if we are in the same login page self.assertContains(response, LOGIN_FORM_KEY) @@ -63,10 +67,15 @@ class AccessAttemptTest(TestCase): self.assertContains(response, self.LOCKED_MESSAGE) def test_with_real_username_max(self): + """Tests the login lock with a real username + """ self.test_login_max(existing_username=True) def test_login_max_with_more_attempts(self, existing_username=False): - for i in range(0, FAILURE_LIMIT - 2): + """Tests the login lock trying to login a lot of times more + than failure limit + """ + for i in range(0, FAILURE_LIMIT): response = self._login(existing_username=existing_username) # Check if we are in the same login page self.assertContains(response, LOGIN_FORM_KEY) @@ -79,9 +88,13 @@ class AccessAttemptTest(TestCase): self.assertContains(response, self.LOCKED_MESSAGE) def test_with_real_username_max_with_more(self): + """Tests the login lock for a bunch of times with a real username + """ self.test_login_max_with_more_attempts(existing_username=True) def test_valid_login(self): + """Tests a valid login for a real username + """ valid_username = self._random_username(existing_username=True) response = self.client.post(reverse('admin:index'), { 'username': valid_username,