From 2ee602b9dd613d363aa8fb17acbcd5fd566dccf9 Mon Sep 17 00:00:00 2001 From: Ken Cochrane Date: Wed, 31 Dec 2014 12:19:06 -0500 Subject: [PATCH] fixed unit tests --- defender/decorators.py | 11 ++++----- defender/models.py | 1 - defender/test_settings.py | 5 ++--- defender/tests.py | 47 +++++++++++++++++---------------------- 4 files changed, 29 insertions(+), 35 deletions(-) diff --git a/defender/decorators.py b/defender/decorators.py index f2ddc0b..b4cd40a 100644 --- a/defender/decorators.py +++ b/defender/decorators.py @@ -1,7 +1,7 @@ import logging import socket -from redis import StrictRedis +import redis from django.conf import settings from django.http import HttpResponse from django.http import HttpResponseRedirect @@ -50,7 +50,7 @@ VERBOSE = getattr(settings, 'DEFENDER_VERBOSE', True) ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. " "Note that both fields are case-sensitive.") -redis_server = StrictRedis( +redis_server = redis.StrictRedis( host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB, password=REDIS_PASSWORD) log = logging.getLogger(__name__) @@ -175,13 +175,13 @@ def get_user_attempts(request): def block_ip(ip): """ given the ip, block it""" key = get_ip_blocked_cache_key(ip) - redis_server.set(key, COOLOFF_TIME) + redis_server.set(key, 'blocked', COOLOFF_TIME) def block_username(username): """ given the username block it. """ key = get_username_blocked_cache_key(username) - redis_server.set(key, COOLOFF_TIME) + redis_server.set(key, 'blocked', COOLOFF_TIME) def record_failed_attempt(ip, username): @@ -239,6 +239,7 @@ def is_already_locked(request): # ip blocked? ip_blocked = redis_server.get(get_ip_blocked_cache_key(ip_address)) + if not ip_blocked: ip_blocked = False @@ -261,7 +262,7 @@ def check_request(request, login_unsuccessful): result = record_failed_attempt(ip_address, username) else: # user logged in -- forget the failed attempts - reset_failed_attempts(ip_address, username) + reset_failed_attempts(ip=ip_address, username=username) return result diff --git a/defender/models.py b/defender/models.py index 16276a5..2836901 100644 --- a/defender/models.py +++ b/defender/models.py @@ -29,5 +29,4 @@ class AccessAttempt(models.Model): ) class Meta: - abstract = True ordering = ['-attempt_time'] diff --git a/defender/test_settings.py b/defender/test_settings.py index 1bf7006..865e9e0 100644 --- a/defender/test_settings.py +++ b/defender/test_settings.py @@ -40,6 +40,5 @@ SECRET_KEY = 'too-secret-for-test' LOGIN_REDIRECT_URL = '/admin' -AXES_LOGIN_FAILURE_LIMIT = 10 -from datetime import timedelta -AXES_COOLOFF_TIME = timedelta(seconds=2) +DEFENDER_LOGIN_FAILURE_LIMIT = 10 +DEFENDER_COOLOFF_TIME = 2 diff --git a/defender/tests.py b/defender/tests.py index 5d73b5c..e9fedd5 100644 --- a/defender/tests.py +++ b/defender/tests.py @@ -13,11 +13,12 @@ from defender.decorators import ( COOLOFF_TIME, FAILURE_LIMIT, reset_failed_attempts) +redis_client = mockredis.mock_strict_redis_client() + # Django >= 1.7 compatibility try: ADMIN_LOGIN_URL = reverse('admin:login') - LOGIN_FORM_KEY = '
' + LOGIN_FORM_KEY = '' except NoReverseMatch: ADMIN_LOGIN_URL = reverse('admin:index') LOGIN_FORM_KEY = 'this_is_the_login_form' @@ -29,23 +30,13 @@ class AccessAttemptTest(TestCase): VALID_USERNAME = 'valid' LOCKED_MESSAGE = 'Account locked: too many login attempts.' - @patch('redis.StrictRedis', mockredis.mock_strict_redis_client) - def the_test(self): - from redis import StrictRedis - print(StrictRedis) - - def the_test2(self): - from redis import StrictRedis - dir(StrictRedis) - print(StrictRedis) - def _get_random_str(self): """ Returns a random str """ chars = string.ascii_uppercase + string.digits return ''.join(random.choice(chars) for x in range(20)) - @patch('redis.StrictRedis', mockredis.mock_strict_redis_client) + @patch('defender.decorators.redis_server', redis_client) def _login(self, is_valid=False, user_agent='test-browser'): """Login a user. A valid credential is used when is_valid is True, otherwise it will use a random string to make a failed login. @@ -55,11 +46,12 @@ class AccessAttemptTest(TestCase): response = self.client.post(ADMIN_LOGIN_URL, { 'username': username, 'password': username, - 'this_is_the_login_form': 1, + LOGIN_FORM_KEY: 1, }, HTTP_USER_AGENT=user_agent) return response + @patch('defender.decorators.redis_server', redis_client) def setUp(self): """Create a valid user for login """ @@ -69,7 +61,11 @@ class AccessAttemptTest(TestCase): password=self.VALID_USERNAME, ) - @patch('redis.StrictRedis', mockredis.mock_strict_redis_client) + def tearDown(self): + """ clean up the db """ + redis_client.flushdb() + + @patch('defender.decorators.redis_server', redis_client) def test_failure_limit_once(self): """Tests the login lock trying to login one more time than failure limit @@ -84,7 +80,7 @@ class AccessAttemptTest(TestCase): response = self._login() self.assertContains(response, self.LOCKED_MESSAGE) - @patch('redis.StrictRedis', mockredis.mock_strict_redis_client) + @patch('defender.decorators.redis_server', redis_client) def test_failure_limit_many(self): """Tests the login lock trying to login a lot of times more than failure limit @@ -101,34 +97,33 @@ class AccessAttemptTest(TestCase): response = self._login() self.assertContains(response, self.LOCKED_MESSAGE) - @patch('redis.StrictRedis', mockredis.mock_strict_redis_client) + @patch('defender.decorators.redis_server', redis_client) def test_valid_login(self): """Tests a valid login for a real username """ response = self._login(is_valid=True) self.assertNotContains(response, LOGIN_FORM_KEY, status_code=302) - @patch('redis.StrictRedis', mockredis.mock_strict_redis_client) + @patch('defender.decorators.redis_server', redis_client) def test_cooling_off(self): """Tests if the cooling time allows a user to login """ self.test_failure_limit_once() - # Wait for the cooling off period - time.sleep(COOLOFF_TIME.total_seconds()) - + time.sleep(COOLOFF_TIME) + # mock redis require that we expire on our own + redis_client.do_expire() # It should be possible to login again, make sure it is. self.test_valid_login() - @patch('redis.StrictRedis', mockredis.mock_strict_redis_client) + @patch('defender.decorators.redis_server', redis_client) def test_cooling_off_for_trusted_user(self): """Test the cooling time for a trusted user """ - # Try the cooling off time self.test_cooling_off() - @patch('redis.StrictRedis', mockredis.mock_strict_redis_client) + @patch('defender.decorators.redis_server', redis_client) def test_long_user_agent_valid(self): """Tests if can handle a long user agent """ @@ -136,7 +131,7 @@ class AccessAttemptTest(TestCase): response = self._login(is_valid=True, user_agent=long_user_agent) self.assertNotContains(response, LOGIN_FORM_KEY, status_code=302) - @patch('redis.StrictRedis', mockredis.mock_strict_redis_client) + @patch('defender.decorators.redis_server', redis_client) def test_long_user_agent_not_valid(self): """Tests if can handle a long user agent with failure """ @@ -146,7 +141,7 @@ class AccessAttemptTest(TestCase): self.assertContains(response, self.LOCKED_MESSAGE) - @patch('redis.StrictRedis', mockredis.mock_strict_redis_client) + @patch('defender.decorators.redis_server', redis_client) def test_reset_ip(self): """Tests if can reset an ip address """