diff --git a/axes/decorators.py b/axes/decorators.py index d8b195a..904a0d8 100644 --- a/axes/decorators.py +++ b/axes/decorators.py @@ -238,10 +238,12 @@ def _get_user_attempts(request): ip_address=ip, username=username, trusted=True ) - if not attempts and not LOCK_OUT_BY_COMBINATION_USER_AND_IP: + if not attempts: params = {'ip_address': ip, 'trusted': False} if USE_USER_AGENT: params['user_agent'] = ua + if LOCK_OUT_BY_COMBINATION_USER_AND_IP: + params['username'] = username attempts = AccessAttempt.objects.filter(**params) diff --git a/axes/tests.py b/axes/tests.py index d687b3b..f8e1b04 100644 --- a/axes/tests.py +++ b/axes/tests.py @@ -2,10 +2,12 @@ import random import string import time +from django.conf import settings from django.test import TestCase -from django.contrib.auth.models import User -from django.core.urlresolvers import NoReverseMatch -from django.core.urlresolvers import reverse +from django.core.urlresolvers import NoReverseMatch, reverse + +if not settings.configured: + settings.configure() from axes.decorators import COOLOFF_TIME from axes.decorators import FAILURE_LIMIT @@ -14,6 +16,7 @@ from axes.signals import user_locked_out from axes.utils import reset + class AccessAttemptTest(TestCase): """Test case using custom settings for testing """ @@ -49,6 +52,13 @@ class AccessAttemptTest(TestCase): def setUp(self): """Create a valid user for login """ + try: + from django.contrib.auth import get_user_model + except ImportError: # django < 1.5 + from django.contrib.auth.models import User + else: + User = get_user_model() + self.user = User.objects.create_superuser( username='valid-username', email='test@example.com', @@ -84,6 +94,27 @@ class AccessAttemptTest(TestCase): response = self._login() self.assertContains(response, self.LOCKED_MESSAGE) + def test_failure_username_ip(self): + """Tests the login lock based on a combination of username + and IP address + """ + with self.settings(AXES_LOCK_OUT_BY_COMBINATION_USER_AND_IP=True): + for i in range(1, FAILURE_LIMIT): # test until one try before the limit + response = self._login() + # Check if we are in the same login page + self.assertContains(response, self.LOGIN_FORM_KEY) + + # So, we shouldn't have gotten a lock-out yet. + # But we should get one now + response = self._login() + self.assertContains(response, self.LOCKED_MESSAGE) + + + self.user.username='other-user' + self.user.save() + response = self._login() + self.test_valid_login() + def test_valid_login(self): """Tests a valid login for a real username """