mirror of
https://github.com/jazzband/django-axes.git
synced 2026-03-16 22:30:23 +00:00
Deprecate old signature for AXES_USERNAME_CALLABLE and update documentation
Signed-off-by: Aleksi Häkli <aleksi.hakli@iki.fi>
This commit is contained in:
parent
715dedc069
commit
fcef40748a
6 changed files with 38 additions and 48 deletions
|
|
@ -26,6 +26,9 @@ Changes
|
|||
- Drop support for Python 2.7 and Python 3.4.
|
||||
[aleksihakli]
|
||||
|
||||
- Drop old single-argument signature format for ``AXES_USERNAME_CALLABLE``.
|
||||
[aleksihakli]
|
||||
|
||||
|
||||
4.5.4 (2019-01-15)
|
||||
------------------
|
||||
|
|
|
|||
|
|
@ -172,22 +172,9 @@ class UtilsTest(TestCase):
|
|||
|
||||
self.assertEqual(expected_in_credentials, actual)
|
||||
|
||||
def sample_customize_username(request):
|
||||
def sample_customize_username(request, credentials):
|
||||
return 'prefixed-' + request.POST.get('username')
|
||||
|
||||
@override_settings(AXES_USERNAME_FORM_FIELD='username')
|
||||
@override_settings(AXES_USERNAME_CALLABLE=sample_customize_username)
|
||||
def test_custom_get_client_username(self):
|
||||
provided = 'test-username'
|
||||
expected = 'prefixed-' + provided
|
||||
|
||||
request = HttpRequest()
|
||||
request.POST['username'] = provided
|
||||
|
||||
actual = get_client_username(request)
|
||||
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
@override_settings(AXES_USERNAME_FORM_FIELD='username')
|
||||
@override_settings(AXES_USERNAME_CALLABLE=sample_customize_username)
|
||||
def test_custom_get_client_username_from_request(self):
|
||||
|
|
@ -223,18 +210,30 @@ class UtilsTest(TestCase):
|
|||
|
||||
self.assertEqual(expected_in_credentials, actual)
|
||||
|
||||
def sample_get_client_username_too_few_arguments():
|
||||
def sample_get_client_username(request, credentials):
|
||||
return 'example'
|
||||
|
||||
@override_settings(AXES_USERNAME_CALLABLE=sample_get_client_username)
|
||||
def test_get_client_username(self):
|
||||
self.assertEqual('example', get_client_username(HttpRequest(), {}))
|
||||
|
||||
@override_settings(AXES_USERNAME_CALLABLE=sample_get_client_username)
|
||||
def test_get_client_username_too_many_arguments(self):
|
||||
with self.assertRaises(TypeError):
|
||||
actual = get_client_username(HttpRequest(), {}, None)
|
||||
|
||||
def sample_get_client_username_too_few_arguments(request):
|
||||
pass
|
||||
|
||||
@override_settings(AXES_USERNAME_CALLABLE=sample_get_client_username_too_few_arguments)
|
||||
def test_get_client_username_too_few_arguments_invalid_callable(self):
|
||||
def test_get_client_username_invalid_callable_too_few_arguments(self):
|
||||
with self.assertRaises(TypeError):
|
||||
actual = get_client_username(HttpRequest(), {})
|
||||
|
||||
def sample_get_client_username_too_many_arguments(one, two, three):
|
||||
def sample_get_client_username_too_many_arguments(request, credentials, extra_argument):
|
||||
pass
|
||||
|
||||
@override_settings(AXES_USERNAME_CALLABLE=sample_get_client_username_too_many_arguments)
|
||||
def test_get_client_username_too_many_arguments_invalid_callable(self):
|
||||
def test_get_client_username_invalid_callable_too_many_arguments(self):
|
||||
with self.assertRaises(TypeError):
|
||||
actual = get_client_username(HttpRequest(), {})
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from datetime import timedelta
|
||||
from inspect import getargspec
|
||||
from logging import getLogger
|
||||
from socket import error, inet_pton, AF_INET6
|
||||
|
||||
|
|
@ -76,30 +75,17 @@ def get_client_username(request, credentials=None):
|
|||
|
||||
The order of preference for fetching the username is as follows:
|
||||
|
||||
1. If configured, use `AXES_USERNAME_CALLABLE`, and supply either `request` or `request, credentials` as arguments
|
||||
depending on the function argument count (multiple signatures are supported for backwards compatibility)
|
||||
2. If given, use `credentials` and fetch username from `AXES_USERNAME_FORM_FIELD` (defaults to `username`)
|
||||
3. Use request.POST and fetch username from `AXES_USERNAME_FORM_FIELD` (defaults to `username`)
|
||||
1. If configured, use ``AXES_USERNAME_CALLABLE``, and supply ``request, credentials`` as arguments
|
||||
2. If given, use ``credentials`` and fetch username from ``AXES_USERNAME_FORM_FIELD`` (defaults to ``username``)
|
||||
3. Use request.POST and fetch username from ``AXES_USERNAME_FORM_FIELD`` (defaults to ``username``)
|
||||
|
||||
:param request: incoming Django `HttpRequest` or similar object from authentication backend or other source
|
||||
:param credentials: incoming credentials `dict` or similar object from authentication backend or other source
|
||||
:param request: incoming Django ``HttpRequest`` or similar object from authentication backend or other source
|
||||
:param credentials: incoming credentials ``dict`` or similar object from authentication backend or other source
|
||||
"""
|
||||
|
||||
if settings.AXES_USERNAME_CALLABLE:
|
||||
num_args = len(
|
||||
getargspec(settings.AXES_USERNAME_CALLABLE).args # pylint: disable=deprecated-method
|
||||
)
|
||||
|
||||
if num_args == 2:
|
||||
logger.debug('Using AXES_USERNAME_CALLABLE for username with two arguments: request, credentials')
|
||||
return settings.AXES_USERNAME_CALLABLE(request, credentials)
|
||||
|
||||
if num_args == 1:
|
||||
logger.debug('Using AXES_USERNAME_CALLABLE for username with one argument: request')
|
||||
return settings.AXES_USERNAME_CALLABLE(request)
|
||||
|
||||
logger.error('Using AXES_USERNAME_CALLABLE for username failed: wrong number of arguments %s', num_args)
|
||||
raise TypeError('Wrong number of arguments in function call to AXES_USERNAME_CALLABLE', num_args)
|
||||
logger.debug('Using AXES_USERNAME_CALLABLE to get username')
|
||||
return settings.AXES_USERNAME_CALLABLE(request, credentials)
|
||||
|
||||
if credentials:
|
||||
logger.debug('Using `credentials` to get username with key AXES_USERNAME_FORM_FIELD')
|
||||
|
|
|
|||
|
|
@ -145,8 +145,8 @@ Use the ``python manage.py check`` command to verify the correct configuration i
|
|||
development and production environments. It is probably best to use this step as part
|
||||
of your regular CI workflows to verify that your project is not misconfigured.
|
||||
|
||||
django-axes uses the checks to verify your cache configuration to see that your caches
|
||||
should be functional with the configuration axes. Many people have different configurations
|
||||
Axes uses the checks to verify your cache configuration to see that your caches
|
||||
should be functional with the configuration of Axes. Many people have different configurations
|
||||
for their development and production environments.
|
||||
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ add an extra cache to ``CACHES`` with a name of your choice::
|
|||
}
|
||||
}
|
||||
|
||||
The next step is to tell axes to use this cache through adding ``AXES_CACHE``
|
||||
The next step is to tell Axes to use this cache through adding ``AXES_CACHE``
|
||||
to your ``settings.py`` file::
|
||||
|
||||
AXES_CACHE = 'axes_cache'
|
||||
|
|
@ -221,7 +221,7 @@ Customizing Axes
|
|||
You have a couple options available to you to customize ``django-axes`` a bit.
|
||||
These should be defined in your ``settings.py`` file.
|
||||
|
||||
* ``AXES_CACHE``: The name of the cache for axes to use.
|
||||
* ``AXES_CACHE``: The name of the cache for Axes to use.
|
||||
Default: ``'default'``
|
||||
* ``AXES_FAILURE_LIMIT``: The number of login attempts allowed before a
|
||||
record is created for the failed logins. Default: ``3``
|
||||
|
|
@ -235,7 +235,7 @@ These should be defined in your ``settings.py`` file.
|
|||
old failed login attempts will be forgotten. Can be set to a python
|
||||
timedelta object or an integer. If an integer, will be interpreted as a
|
||||
number of hours. Default: ``None``
|
||||
* ``AXES_LOGGER``: If set, specifies a logging mechanism for axes to use.
|
||||
* ``AXES_LOGGER``: If set, specifies a logging mechanism for Axes to use.
|
||||
Default: ``'axes.watch_login'``
|
||||
* ``AXES_LOCKOUT_TEMPLATE``: If set, specifies a template to render when a
|
||||
user is locked out. Template receives cooloff_time and failure_limit as
|
||||
|
|
@ -247,11 +247,11 @@ These should be defined in your ``settings.py`` file.
|
|||
Default: ``True``
|
||||
* ``AXES_USERNAME_FORM_FIELD``: the name of the form field that contains your
|
||||
users usernames. Default: ``username``
|
||||
* ``AXES_USERNAME_CALLABLE``: A callable function that takes either one or two arguments:
|
||||
``AXES_USERNAME_CALLABLE(request)`` or ``AXES_USERNAME_CALLABLE(request, credentials)``.
|
||||
* ``AXES_USERNAME_CALLABLE``: A callable function that takes two arguments:
|
||||
``AXES_USERNAME_CALLABLE(request, credentials)``.
|
||||
The ``request`` is a HttpRequest like object and the ``credentials`` is a dictionary like object.
|
||||
``credentials`` are the ones that were passed to Django ``authenticate()`` in the login flow.
|
||||
If no function is supplied, axes fetches the username from the ``credentials`` or ``request.POST``
|
||||
If no function is supplied, Axes fetches the username from the ``credentials`` or ``request.POST``
|
||||
dictionaries based on ``AXES_USERNAME_FORM_FIELD``. Default: ``None``
|
||||
* ``AXES_PASSWORD_FORM_FIELD``: the name of the form or credentials field that contains your
|
||||
users password. Default: ``password``
|
||||
|
|
|
|||
|
|
@ -33,3 +33,5 @@ API endpoints or names for compatibility reasons.
|
|||
``axes.exceptions.AxesSignalPermissionDenied`` on lockouts.
|
||||
- ``AxesMiddleware`` was added to return lockout responses.
|
||||
The middleware handles ``axes.exception.AxesSignalPermissionDenied``.
|
||||
- ``AXES_USERNAME_CALLABLE`` is now always called with two arguments,
|
||||
``request`` and ``credentials`` instead of ``request``.
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ Once ``axes`` is in your ``INSTALLED_APPS`` in your project settings file, you c
|
|||
login and logout of your application via the ``django.contrib.auth`` views.
|
||||
The attempts will be logged and visible in the "Access Attempts" section in admin.
|
||||
|
||||
By default, django-axes will lock out repeated access attempts from the same IP address.
|
||||
By default, Axes will lock out repeated access attempts from the same IP address.
|
||||
You can allow this IP to attempt again by deleting relevant ``AccessAttempt`` records.
|
||||
|
||||
Records can be deleted, for example, by using the Django admin application.
|
||||
|
|
|
|||
Loading…
Reference in a new issue