fixed unit tests

This commit is contained in:
Ken Cochrane 2014-12-31 12:19:06 -05:00
parent 6786499ba1
commit 2ee602b9dd
4 changed files with 29 additions and 35 deletions

View file

@ -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

View file

@ -29,5 +29,4 @@ class AccessAttempt(models.Model):
)
class Meta:
abstract = True
ordering = ['-attempt_time']

View file

@ -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

View file

@ -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 = '<form action="/admin/login/" method="post" \
id="login-form">'
LOGIN_FORM_KEY = '<form action="/admin/" method="post" id="login-form">'
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
"""