mirror of
https://github.com/jazzband/django-defender.git
synced 2026-03-16 22:10:32 +00:00
Run black with Python 2.7 as target version to unify the code styling and make it more linter and style guide compliant
59 lines
2.2 KiB
Python
59 lines
2.2 KiB
Python
from . import utils
|
|
|
|
import functools
|
|
|
|
|
|
def watch_login(status_code=302, msg="", get_username=utils.get_username_from_request):
|
|
"""
|
|
Used to decorate the django.contrib.admin.site.login method or
|
|
any other function you want to protect by brute forcing.
|
|
To make it work on normal functions just pass the status code that should
|
|
indicate a failure and/or a string that will be checked within the
|
|
response body.
|
|
"""
|
|
|
|
def decorated_login(func):
|
|
@functools.wraps(func)
|
|
def wrapper(request, *args, **kwargs):
|
|
# if the request is currently under lockout, do not proceed to the
|
|
# login function, go directly to lockout url, do not pass go,
|
|
# do not collect messages about this login attempt
|
|
if utils.is_already_locked(request):
|
|
return utils.lockout_response(request)
|
|
|
|
# call the login function
|
|
response = func(request, *args, **kwargs)
|
|
|
|
if request.method == "POST":
|
|
# see if the login was successful
|
|
if status_code == 302: # standard Django login view
|
|
login_unsuccessful = (
|
|
response
|
|
and not response.has_header("location")
|
|
and response.status_code != status_code
|
|
)
|
|
else:
|
|
# If msg is not passed the last condition will be evaluated
|
|
# always to True so the first 2 will decide the result.
|
|
login_unsuccessful = (
|
|
response
|
|
and response.status_code == status_code
|
|
and msg in response.content.decode("utf-8")
|
|
)
|
|
|
|
# ideally make this background task, but to keep simple,
|
|
# keeping it inline for now.
|
|
utils.add_login_attempt_to_db(
|
|
request, not login_unsuccessful, get_username
|
|
)
|
|
|
|
if utils.check_request(request, login_unsuccessful, get_username):
|
|
return response
|
|
|
|
return utils.lockout_response(request)
|
|
|
|
return response
|
|
|
|
return wrapper
|
|
|
|
return decorated_login
|