mirror of
https://github.com/jazzband/django-defender.git
synced 2026-03-16 22:10:32 +00:00
another different approach
This commit is contained in:
parent
be523281ab
commit
7121db4b0f
3 changed files with 17 additions and 43 deletions
|
|
@ -58,4 +58,4 @@ def get_approx_account_lockouts_from_login_attempts(ip_address=None, username=No
|
|||
# TODO: Maybe we should throw an exception here instead of returning 0?
|
||||
return 0
|
||||
|
||||
return min(AccessAttempt.objects.filter(q).count() // failure_limit, len(config.LOCKOUT_COOLOFF_TIMES) - 1)
|
||||
return AccessAttempt.objects.filter(q).count() // failure_limit
|
||||
|
|
@ -11,6 +11,7 @@ from django.test.client import RequestFactory
|
|||
from redis.client import Redis
|
||||
from django.urls import reverse
|
||||
|
||||
from . import data
|
||||
from . import utils
|
||||
from . import config
|
||||
from .signals import (
|
||||
|
|
@ -436,7 +437,7 @@ class AccessAttemptTest(DefenderTestCase):
|
|||
self.assertTemplateUsed(response, "defender/lockout.html")
|
||||
|
||||
@patch("defender.config.COOLOFF_TIME", 0)
|
||||
@patch("defender.config.LOCKOUT_COOLOFF_TIMES", 0)
|
||||
@patch("defender.config.LOCKOUT_COOLOFF_TIMES", [0])
|
||||
def test_failed_login_no_cooloff(self):
|
||||
""" failed login no cooloff """
|
||||
for i in range(0, config.FAILURE_LIMIT):
|
||||
|
|
@ -958,62 +959,35 @@ class AccessAttemptTest(DefenderTestCase):
|
|||
|
||||
@patch("defender.config.LOCKOUT_COOLOFF_TIMES", [3, 6])
|
||||
def test_lockout_cooloff_correctly_scales_with_ip_when_set(self):
|
||||
|
||||
self.test_ip_failure_limit()
|
||||
time.sleep(config.LOCKOUT_COOLOFF_TIMES[0])
|
||||
self.assertEqual(data.get_approx_account_lockouts_from_login_attempts(ip_address="127.0.0.1"), 1)
|
||||
if config.MOCK_REDIS:
|
||||
# mock redis require that we expire on our own
|
||||
get_redis_connection().do_expire() # pragma: no cover
|
||||
self.assertFalse(utils.is_source_ip_already_locked("127.0.0.1"))
|
||||
self.test_ip_failure_limit()
|
||||
time.sleep(config.LOCKOUT_COOLOFF_TIMES[0])
|
||||
self.assertTrue(utils.is_source_ip_already_locked("127.0.0.1"))
|
||||
utils.reset_failed_attempts(ip_address="127.0.0.1")
|
||||
self.test_ip_failure_limit()
|
||||
self.assertEqual(data.get_approx_account_lockouts_from_login_attempts(ip_address="127.0.0.1"), 2)
|
||||
if config.MOCK_REDIS:
|
||||
# mock redis require that we expire on our own
|
||||
get_redis_connection().do_expire() # pragma: no cover
|
||||
time.sleep(config.LOCKOUT_COOLOFF_TIMES[1])
|
||||
self.test_valid_login()
|
||||
|
||||
@patch("defender.config.LOCKOUT_COOLOFF_TIMES", [3, 6])
|
||||
def test_lockout_cooloff_correctly_scales_with_username_when_set(self):
|
||||
self.test_username_failure_limit()
|
||||
time.sleep(config.LOCKOUT_COOLOFF_TIMES[0])
|
||||
self.assertEqual(data.get_approx_account_lockouts_from_login_attempts(username=VALID_USERNAME), 1)
|
||||
if config.MOCK_REDIS:
|
||||
# mock redis require that we expire on our own
|
||||
get_redis_connection().do_expire() # pragma: no cover
|
||||
self.assertFalse(utils.is_user_already_locked(VALID_USERNAME))
|
||||
self.test_username_failure_limit()
|
||||
time.sleep(config.LOCKOUT_COOLOFF_TIMES[0])
|
||||
self.assertTrue(utils.is_user_already_locked(VALID_USERNAME))
|
||||
utils.reset_failed_attempts(username=VALID_USERNAME)
|
||||
|
||||
@patch("defender.config.LOCKOUT_COOLOFF_TIMES", [3, 6])
|
||||
def test_lockout_correctly_releases_after_scaling_with_ip(self):
|
||||
self.test_ip_failure_limit()
|
||||
time.sleep(config.LOCKOUT_COOLOFF_TIMES[0])
|
||||
if config.MOCK_REDIS:
|
||||
# mock redis require that we expire on our own
|
||||
get_redis_connection().do_expire() # pragma: no cover
|
||||
self.assertFalse(utils.is_source_ip_already_locked("127.0.0.1"))
|
||||
self.test_ip_failure_limit()
|
||||
time.sleep(config.LOCKOUT_COOLOFF_TIMES[1])
|
||||
if config.MOCK_REDIS:
|
||||
# mock redis require that we expire on our own
|
||||
get_redis_connection().do_expire() # pragma: no cover
|
||||
self.assertFalse(utils.is_source_ip_already_locked("127.0.0.1"))
|
||||
utils.reset_failed_attempts(ip_address="127.0.0.1")
|
||||
|
||||
@patch("defender.config.LOCKOUT_COOLOFF_TIMES", [3, 6])
|
||||
def test_lockout_correctly_releases_after_scaling_with_username(self):
|
||||
self.test_username_failure_limit()
|
||||
time.sleep(config.LOCKOUT_COOLOFF_TIMES[0])
|
||||
self.assertEqual(data.get_approx_account_lockouts_from_login_attempts(username=VALID_USERNAME), 2)
|
||||
if config.MOCK_REDIS:
|
||||
# mock redis require that we expire on our own
|
||||
get_redis_connection().do_expire() # pragma: no cover
|
||||
self.assertFalse(utils.is_user_already_locked(VALID_USERNAME))
|
||||
self.test_username_failure_limit()
|
||||
time.sleep(config.LOCKOUT_COOLOFF_TIMES[1])
|
||||
if config.MOCK_REDIS:
|
||||
# mock redis require that we expire on our own
|
||||
get_redis_connection().do_expire() # pragma: no cover
|
||||
self.assertFalse(utils.is_user_already_locked(VALID_USERNAME))
|
||||
utils.reset_failed_attempts(username=VALID_USERNAME)
|
||||
self.test_valid_login()
|
||||
|
||||
|
||||
class SignalTest(DefenderTestCase):
|
||||
|
|
|
|||
|
|
@ -206,10 +206,10 @@ def get_user_attempts(request, get_username=get_username_from_request, username=
|
|||
return max(ip_count, username_count)
|
||||
|
||||
def get_lockout_cooloff_time(ip_address=None, username=None):
|
||||
index = min(
|
||||
index = max(0, min(
|
||||
len(config.LOCKOUT_COOLOFF_TIMES) - 1,
|
||||
get_approx_account_lockouts_from_login_attempts(ip_address, username)
|
||||
)
|
||||
get_approx_account_lockouts_from_login_attempts(ip_address, username) - 1
|
||||
))
|
||||
return config.LOCKOUT_COOLOFF_TIMES[index]
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue