send signals when blocking username or ip (#114)

This commit is contained in:
William Boman 2018-04-10 15:21:37 +02:00 committed by Ken Cochrane
parent 50e2962fd5
commit b546224372
4 changed files with 66 additions and 0 deletions

View file

@ -442,6 +442,26 @@ class BasicAuthenticationDefender(BasicAuthentication):
To make it works add `BasicAuthenticationDefender` to `DEFAULT_AUTHENTICATION_CLASSES` above all other authentication methods in your `settings.py`.
Django Signals
--------------------
`django-defender` will send signals when blocking a username or an IP address. To set up signal receiver functions:
```python
from django.dispatch import receiver
from defender import signals
@receiver(signals.username_block)
def username_blocked(username, **kwargs):
print("%s was blocked!" % username)
@receiver(signals.ip_block)
def ip_blocked(ip_address, **kwargs):
print("%s was blocked!" % ip_address)
```
Running Tests
=============

17
defender/signals.py Normal file
View file

@ -0,0 +1,17 @@
from django.dispatch import Signal
username_block = Signal(providing_args=['username'])
ip_block = Signal(providing_args=['ip_address'])
class BlockSignal:
"""
Providing a sender is mandatory when sending signals, hence
this empty sender class.
"""
pass
def send_username_block_signal(username):
username_block.send(sender=BlockSignal, username=username)
def send_ip_block_signal(ip_address):
ip_block.send(sender=BlockSignal, ip_address=ip_address)

View file

@ -23,6 +23,7 @@ except ImportError:
from . import utils
from . import config
from .signals import ip_block as ip_block_signal, username_block as username_block_signal
from .connection import parse_redis_url, get_redis_connection
from .decorators import watch_login
from .models import AccessAttempt
@ -875,6 +876,31 @@ class AccessAttemptTest(DefenderTestCase):
self.assertEqual(data_out, [])
class SignalTest(DefenderTestCase):
""" Test that signals are properly sent when blocking usernames and IPs.
"""
def test_should_send_signal_when_blocking_ip(self):
self.blocked_ip = None
def handler(sender, ip_address, **kwargs):
self.blocked_ip = ip_address
ip_block_signal.connect(handler)
utils.block_ip('8.8.8.8')
self.assertEqual(self.blocked_ip, '8.8.8.8')
def test_should_send_signal_when_blocking_username(self):
self.blocked_username = None
def handler(sender, username, **kwargs):
self.blocked_username = username
username_block_signal.connect(handler)
utils.block_username('richard_hendricks')
self.assertEqual(self.blocked_username, 'richard_hendricks')
class DefenderTestCaseTest(DefenderTestCase):
""" Make sure that we're cleaning the cache between tests """
key = 'test_key'

View file

@ -9,6 +9,7 @@ from django.core.exceptions import ValidationError
from .connection import get_redis_connection
from . import config
from .data import store_login_attempt
from .signals import send_username_block_signal, send_ip_block_signal
REDIS_SERVER = get_redis_connection()
@ -171,6 +172,7 @@ def block_ip(ip_address):
REDIS_SERVER.set(key, 'blocked', config.COOLOFF_TIME)
else:
REDIS_SERVER.set(key, 'blocked')
send_ip_block_signal(ip_address)
def block_username(username):
@ -186,6 +188,7 @@ def block_username(username):
REDIS_SERVER.set(key, 'blocked', config.COOLOFF_TIME)
else:
REDIS_SERVER.set(key, 'blocked')
send_username_block_signal(username)
def record_failed_attempt(ip_address, username):