mirror of
https://github.com/jazzband/django-defender.git
synced 2026-03-16 22:10:32 +00:00
Taking redis client from django.core.cache (#82)
* new setting that point to an already configured redis client * taking redis client from django cache setting * adding informative exception * dropping django 1.6 support * dropping django 1.7 support * adding tests * removing old coverage stuff + pep8 fixes * ups, wrong package * supporting multiple backends * adding documentation * dropping python 2.6 support
This commit is contained in:
parent
a59cbca0f6
commit
d2b712eade
7 changed files with 47 additions and 34 deletions
18
.travis.yml
18
.travis.yml
|
|
@ -1,15 +1,12 @@
|
|||
language: python
|
||||
|
||||
python:
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
|
||||
env:
|
||||
- DJANGO=1.6
|
||||
- DJANGO=1.7
|
||||
- DJANGO=1.8
|
||||
- DJANGO=1.9
|
||||
- DJANGO=1.10
|
||||
|
|
@ -22,6 +19,7 @@ install:
|
|||
- pip install -q django~=$DJANGO.0
|
||||
- pip install coveralls
|
||||
- pip install mockredispy
|
||||
- pip install django-redis-cache
|
||||
- pip install 'celery<4'
|
||||
- python setup.py develop
|
||||
|
||||
|
|
@ -31,26 +29,12 @@ script:
|
|||
|
||||
matrix:
|
||||
exclude:
|
||||
- python: "2.6"
|
||||
env: DJANGO=1.7
|
||||
- python: "2.6"
|
||||
env: DJANGO=1.8
|
||||
- python: "2.6"
|
||||
env: DJANGO=1.9
|
||||
- python: "2.6"
|
||||
env: DJANGO=1.10
|
||||
- python: "2.6"
|
||||
env: DJANGO=1.11
|
||||
- python: "3.3"
|
||||
env: DJANGO=1.9
|
||||
- python: "3.3"
|
||||
env: DJANGO=1.10
|
||||
- python: "3.3"
|
||||
env: DJANGO=1.11
|
||||
- python: "3.5"
|
||||
env: DJANGO=1.6
|
||||
- python: "3.5"
|
||||
env: DJANGO=1.7
|
||||
|
||||
after_success:
|
||||
- coveralls --verbose
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ to improve the login.
|
|||
requirements
|
||||
============
|
||||
|
||||
- django: 1.6.x, 1.7.x, 1.8.x, 1.9.x, 1.10.x, 1.11.x
|
||||
- django: 1.8.x, 1.9.x, 1.10.x, 1.11.x
|
||||
- redis
|
||||
- python: 2.6.x, 2.7.x, 3.3.x, 3.4.x, 3.5.x, 3.6.x, PyPy
|
||||
|
||||
|
|
@ -332,6 +332,8 @@ locked out.
|
|||
* ``DEFENDER_REDIS_URL``: String: the redis url for defender.
|
||||
[Default: ``redis://localhost:6379/0``]
|
||||
(Example with password: ``redis://:mypassword@localhost:6379/0``)
|
||||
* ``DEFENDER_REDIS_NAME``: String: the name of your cache client on the CACHES django setting. If set, ``DEFENDER_REDIS_URL`` will be ignored.
|
||||
[Default: ``None``]
|
||||
* ``DEFENDER_STORE_ACCESS_ATTEMPTS``: Boolean: If you want to store the login
|
||||
attempt to the database, set to True. If False, it is not saved
|
||||
[Default: ``True``]
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ def get_setting(variable, default=None):
|
|||
# redis server host
|
||||
DEFENDER_REDIS_URL = get_setting('DEFENDER_REDIS_URL')
|
||||
|
||||
# reuse declared cache from django settings
|
||||
DEFENDER_REDIS_NAME = get_setting('DEFENDER_REDIS_NAME')
|
||||
|
||||
MOCK_REDIS = get_setting('DEFENDER_MOCK_REDIS', False)
|
||||
|
||||
# see if the user has overridden the failure limit
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from django.core.cache import caches
|
||||
from django.core.cache.backends.base import InvalidCacheBackendError
|
||||
import mockredis
|
||||
import redis
|
||||
try:
|
||||
|
|
@ -12,12 +14,25 @@ urlparse.uses_netloc.append("redis")
|
|||
|
||||
|
||||
MOCKED_REDIS = mockredis.mock_strict_redis_client()
|
||||
INVALID_CACHE_ERROR_MSG = 'The cache {} was not found on the django cache settings.'
|
||||
|
||||
|
||||
def get_redis_connection():
|
||||
""" Get the redis connection if not using mock """
|
||||
if config.MOCK_REDIS: # pragma: no cover
|
||||
return MOCKED_REDIS # pragma: no cover
|
||||
elif config.DEFENDER_REDIS_NAME: # pragma: no cover
|
||||
try:
|
||||
cache = caches[config.DEFENDER_REDIS_NAME]
|
||||
except InvalidCacheBackendError:
|
||||
raise KeyError(INVALID_CACHE_ERROR_MSG.format(config.DEFENDER_REDIS_NAME))
|
||||
# every redis backend implement it own way to get the low level client
|
||||
try:
|
||||
# redis_cache.RedisCache case (django-redis-cache package)
|
||||
return cache.get_master_client()
|
||||
except AttributeError:
|
||||
# django_redis.cache.RedisCache case (django-redis package)
|
||||
return cache._client
|
||||
else: # pragma: no cover
|
||||
redis_config = parse_redis_url(config.DEFENDER_REDIS_URL)
|
||||
return redis.StrictRedis(
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ from django import get_version
|
|||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.contrib.sessions.backends.db import SessionStore
|
||||
from django.core.urlresolvers import NoReverseMatch
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpRequest
|
||||
from django.test.client import RequestFactory
|
||||
from redis.client import Redis
|
||||
|
||||
from . import utils
|
||||
from . import config
|
||||
|
|
@ -20,14 +20,8 @@ from .connection import parse_redis_url, get_redis_connection
|
|||
from .models import AccessAttempt
|
||||
from .test import DefenderTestCase, DefenderTransactionTestCase
|
||||
|
||||
# Django >= 1.7 compatibility
|
||||
try:
|
||||
LOGIN_FORM_KEY = '<form action="/admin/login/" method="post"'
|
||||
' id="login-form">'
|
||||
ADMIN_LOGIN_URL = reverse('admin:login')
|
||||
except NoReverseMatch:
|
||||
ADMIN_LOGIN_URL = reverse('admin:index')
|
||||
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
||||
LOGIN_FORM_KEY = '<form action="/admin/login/" method="post" id="login-form">'
|
||||
ADMIN_LOGIN_URL = reverse('admin:login')
|
||||
|
||||
DJANGO_VERSION = StrictVersion(get_version())
|
||||
|
||||
|
|
@ -46,7 +40,7 @@ class AccessAttemptTest(DefenderTestCase):
|
|||
""" Returns a random str """
|
||||
chars = string.ascii_uppercase + string.digits
|
||||
|
||||
return ''.join(random.choice(chars) for x in range(20))
|
||||
return ''.join(random.choice(chars) for _ in range(20))
|
||||
|
||||
def _login(self, username=None, password=None, user_agent='test-browser',
|
||||
remote_addr='127.0.0.1'):
|
||||
|
|
@ -193,7 +187,7 @@ class AccessAttemptTest(DefenderTestCase):
|
|||
""" Test an user with blocked ip cannot login with another username
|
||||
"""
|
||||
for i in range(0, config.FAILURE_LIMIT + 1):
|
||||
response = self._login(username=VALID_USERNAME)
|
||||
self._login(username=VALID_USERNAME)
|
||||
|
||||
# try to login with a different user
|
||||
response = self._login(username='myuser')
|
||||
|
|
@ -205,7 +199,7 @@ class AccessAttemptTest(DefenderTestCase):
|
|||
"""
|
||||
for i in range(0, config.FAILURE_LIMIT + 1):
|
||||
ip = '74.125.239.{0}.'.format(i)
|
||||
response = self._login(username=VALID_USERNAME, remote_addr=ip)
|
||||
self._login(username=VALID_USERNAME, remote_addr=ip)
|
||||
|
||||
# try to login with a different ip
|
||||
response = self._login(username=VALID_USERNAME, remote_addr='8.8.8.8')
|
||||
|
|
@ -457,6 +451,16 @@ class AccessAttemptTest(DefenderTestCase):
|
|||
self.assertEqual(conf.get('PASSWORD'), None)
|
||||
self.assertEqual(conf.get('PORT'), 1234)
|
||||
|
||||
@patch('defender.config.DEFENDER_REDIS_NAME', 'default')
|
||||
def test_get_redis_connection_django_conf(self):
|
||||
redis_client = get_redis_connection()
|
||||
self.assertIsInstance(redis_client, Redis)
|
||||
|
||||
@patch('defender.config.DEFENDER_REDIS_NAME', 'bad-key')
|
||||
def test_get_redis_connection_django_conf_wrong_key(self):
|
||||
error_msg = 'The cache bad-key was not found on the django cache settings.'
|
||||
self.assertRaisesMessage(KeyError, error_msg, get_redis_connection)
|
||||
|
||||
def test_get_ip_address_from_request(self):
|
||||
req = HttpRequest()
|
||||
req.META['REMOTE_ADDR'] = '1.2.3.4'
|
||||
|
|
@ -589,8 +593,7 @@ class AccessAttemptTest(DefenderTestCase):
|
|||
response = self._login()
|
||||
self.assertContains(response, self.LOCKED_MESSAGE)
|
||||
|
||||
self.assertEqual(AccessAttempt.objects.count(),
|
||||
config.FAILURE_LIMIT + 1)
|
||||
self.assertEqual(AccessAttempt.objects.count(), config.FAILURE_LIMIT + 1)
|
||||
self.assertIsNotNone(str(AccessAttempt.objects.all()[0]))
|
||||
|
||||
@patch('defender.config.LOCKOUT_BY_IP_USERNAME', True)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@ DATABASES = {
|
|||
}
|
||||
}
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
'BACKEND': 'redis_cache.RedisCache',
|
||||
'LOCATION': 'localhost:6379',
|
||||
}
|
||||
}
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
|
|
|
|||
4
setup.py
4
setup.py
|
|
@ -69,7 +69,7 @@ setup(name='django-defender',
|
|||
include_package_data=True,
|
||||
packages=get_packages('defender'),
|
||||
package_data=get_package_data('defender'),
|
||||
install_requires=['Django>=1.6,<=1.10', 'redis>=2.10.3,<3.0',
|
||||
install_requires=['Django>=1.8,<=1.10', 'redis>=2.10.3,<3.0',
|
||||
'hiredis>=0.2.0,<1.0', 'mockredispy>=2.9.0.11,<3.0'],
|
||||
tests_require=['mock', 'mockredispy', 'coverage', 'celery'],
|
||||
tests_require=['mock', 'mockredispy', 'coverage', 'celery', 'django-redis-cache'],
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue