Keep track of failed login attempts in Django-powered sites.

Related tags

Djangodjango-axes
Overview

django-axes

Jazzband GitHub PyPI release Supported Python versions Supported Django versions Documentation GitHub Actions Coverage

Axes is a Django plugin for keeping track of suspicious login attempts for your Django based website and implementing simple brute-force attack blocking.

The name is sort of a geeky pun, since it can be interpreted as:

  • access, as in monitoring access attempts, or
  • axes, as in tools you can use to hack (generally on wood).

Functionality

Axes records login attempts to your Django powered site and prevents attackers from attempting further logins to your site when they exceed the configured attempt limit.

Axes can track the attempts and persist them in the database indefinitely, or alternatively use a fast and DDoS resistant cache implementation.

Axes can be configured to monitor login attempts by IP address, username, user agent, or their combinations.

Axes supports cool off periods, IP address whitelisting and blacklisting, user account whitelisting, and other features for Django access management.

Documentation

For more information on installation and configuration see the documentation at:

https://django-axes.readthedocs.io/

Issues

If you have questions or have trouble using the app please file a bug report at:

https://github.com/jazzband/django-axes/issues

Contributions

All contributions are welcome!

It is best to separate proposed changes and PRs into small, distinct patches by type so that they can be merged faster into upstream and released quicker.

One way to organize contributions would be to separate PRs for e.g.

  • bugfixes,
  • new features,
  • code and design improvements,
  • documentation improvements, or
  • tooling and CI improvements.

Merging contributions requires passing the checks configured with the CI. This includes running tests and linters successfully on the currently officially supported Python and Django versions.

The test automation is run automatically with GitHub Actions, but you can run it locally with the tox command before pushing commits.

Please note that this is a Jazzband project. By contributing you agree to abide by the Contributor Code of Conduct and follow the guidelines.

Comments
  • Axes settings seems not loaded by django in production

    Axes settings seems not loaded by django in production

    Axes is in INSTALLED_APPS and AUTHENTICATION_BACKENDS. Version : 5.5.0

    When trying to run my CI and just test runner I got this :

    Here is the traceback : Traceback (most recent call last): File "manage.py", line 38, in execute_from_command_line(sys.argv) File "/usr/local/lib/python3.7/site-packages/django/core/management/init.py", line 381, in execute_from_command_line utility.execute() File "/usr/local/lib/python3.7/site-packages/django/core/management/init.py", line 357, in execute django.setup() File "/usr/local/lib/python3.7/site-packages/django/init.py", line 24, in setup apps.populate(settings.INSTALLED_APPS) File "/usr/local/lib/python3.7/site-packages/django/apps/registry.py", line 122, in populate app_config.ready() File "/var/www/jung/badoom/core/apps.py", line 20, in ready autodiscover_modules("signals") File "/usr/local/lib/python3.7/site-packages/django/utils/module_loading.py", line 47, in autodiscover_modules import_module('%s.%s' % (app_config.name, module_to_search)) File "/usr/local/lib/python3.7/importlib/init.py", line 127, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "", line 1006, in _gcd_import File "", line 983, in _find_and_load File "/usr/local/lib/python3.7/site-packages/ddtrace/internal/import_hooks.py", line 215, in wrapped_find_and_load_unlocked return exec_and_call_hooks(module_name, wrapped, args, kwargs) File "/usr/local/lib/python3.7/site-packages/ddtrace/internal/import_hooks.py", line 171, in exec_and_call_hooks return wrapped(*args, **kwargs) File "", line 967, in _find_and_load_unlocked File "", line 677, in _load_unlocked File "", line 728, in exec_module File "", line 219, in _call_with_frames_removed File "/usr/local/lib/python3.7/site-packages/axes/signals.py", line 15, in from axes.handlers.proxy import AxesProxyHandler File "", line 983, in _find_and_load File "/usr/local/lib/python3.7/site-packages/ddtrace/internal/import_hooks.py", line 215, in wrapped_find_and_load_unlocked return exec_and_call_hooks(module_name, wrapped, args, kwargs) File "/usr/local/lib/python3.7/site-packages/ddtrace/internal/import_hooks.py", line 171, in exec_and_call_hooks return wrapped(*args, **kwargs) File "/usr/local/lib/python3.7/site-packages/axes/handlers/proxy.py", line 16, in log = getLogger(settings.AXES_LOGGER) File "/usr/local/lib/python3.7/site-packages/django/conf/init.py", line 80, in getattr val = getattr(self._wrapped, name) AttributeError: 'Settings' object has no attribute 'AXES_LOGGER'

    I know we can skip Axes in test but I would prefer to fix this issue, any insight ?

    needs clarification 
    opened by jeremyrich 31
  • Potential security issues with `get_ip()` changes in v4

    Potential security issues with `get_ip()` changes in v4

    I'm a little concerned by the change to use ipware.ip.get_ip() in v4.

    1. There is no documentation to suggest that django-ipware may need to be configured.
    2. There is now no documentation on the potential attack vector if the proxy doesn't set X-Forwarded-For (or whatever the first header used in IPWARE_META_PRECEDENCE_ORDER is) explicitly, c.f. USE_X_FORWARDED_HOST
    3. ~~django-ipware says to use get_ip() if the server is not accessible on the Internet, see here.~~ (Although looking at the code the distinction between get_ip() and get_real_ip(), the latter doesn't count private IP addresses as "real". What they really mean here is use get_ip() if there are also clients that may connect from an internal private network otherwise use get_real_ip().)
    4. Previously django-axes allowed configuring the maximum number of proxies in case of spoofed entries. This is no longer possible. django-ipware provides get_trusted_ip() but it isn't particularly useful in it's current form.

    It would probably be wise to recommend setting IPWARE_META_PRECEDENCE_ORDER to ['HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR'] or at least indicate that this was the original behaviour. Checking all of these headers by default feels risky.

    Forgive me, but this feels rushed and ill thought through. It was working fine for me and issue #275 and pull request #280 fail to even give any evidence of a problem. Every comment in #275 is regarding AttributeError when looking up META on NoneType - django-ipware is still using request.META. This feels like a push to remove code in favour of a dependency for minor gain.

    documentation 
    opened by ngnpope 24
  • Axes 3.0.0. Fixes #215 #223 #233 #236

    Axes 3.0.0. Fixes #215 #223 #233 #236

    Hi everyone.

    I just did a bunch of changes to use the Django auth signals, so I suppose a lot of things may have changed.

    It is possible to be some broken tests but I already tested on a Django 1.11 project and works pretty fine.

    Please feel free to add comments or suggestions, and help me out fixing or improving tests. I won't have much time to work on them in the next couple weeks, but I would like this to be merged soon.

    any help is very much appreciated.

    opened by camilonova 23
  • Lockouts no longer functioning after upgrading from 5.0.18 to 5.0.19

    Lockouts no longer functioning after upgrading from 5.0.18 to 5.0.19

    (Hey everyone, thanks for making axes such a wonderful project! I know a lot of hard work was put into this!)

    I've been using django-axes for nearly a year (edit: since 4.5.x) without any problems, and recently upgraded from 5.0.18 to 5.0.19 and my unit tests now indicate that lockouts are no longer working.

    The lockouts are based on user login plus IP. We are using axes with django_rest_framework 3.8.2 and django_allauth 0.40.0.

    Some relevant settings:

    AUTHENTICATION_BACKENDS = (
        "axes.backends.AxesBackend",
        "django.contrib.auth.backends.ModelBackend",
        "allauth.account.auth_backends.AuthenticationBackend",
    }
    CACHES = {
        "default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"},
        "axes_cache": {"BACKEND": "django.core.cache.backends.dummy.DummyCache"},
    }
    AXES_CACHE = "axes_cache"
    AXES_LOCK_OUT_BY_COMBINATION_USER_AND_IP = True
    

    With axes 5.0.18, after two unsuccessful local attempts against the same login:

    [in]: from axes.models import AccessAttempt
    [in]: qs = AccessAttempt.objects.all()
    [in]: len(qs)
    [out]: 1
    
    [in]: attempt = qs.first()
    [in]: vars(attempt)
    [out]:
    {'_state': <django.db.models.base.ModelState at 0x7fd6214d5dd8>,
     'id': 68,
     'user_agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36',
     'ip_address': '127.0.0.1',
     'username': '[email protected]',
     'http_accept': 'application/json',
     'path_info': '/account/login/',
     'attempt_time': datetime.datetime(2019, 11, 28, 21, 22, 5, 592513, tzinfo=<UTC>),
     'get_data': '\n---------\n',
     'post_data': '[email protected]\n---------\[email protected]',
     'failures_since_start': 2}
    

    With 5.0.18 both attempts are correctly represented by the same model instance.

    After upgrading to axes 5.0.19, when I run the same test as above:

    [in]: qs = AccessAttempt.objects.all()
    [in]: len(qs)
    [out]: 2
    
    [in]: a_1 = qs.first()
    [in]: a_2 = qs.last()
    [in]: vars(a_1)
    [out]:
    {'_state': <django.db.models.base.ModelState at 0x7f20ebe4ae48>,
     'id': 69,
     'user_agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36',
     'ip_address': '127.0.0.1',
     'username': '[email protected]',
     'http_accept': 'application/json',
     'path_info': '/account/login/',
     'attempt_time': datetime.datetime(2019, 11, 28, 21, 27, 7, 300416, tzinfo=<UTC>),
     'get_data': '',
     'post_data': '[email protected]',
     'failures_since_start': 1}
    
    [in]: vars(a_2)
    [out]:
    {'_state': <django.db.models.base.ModelState at 0x7f20ebe4aa20>,
     'id': 70,
     'user_agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36',
     'ip_address': '127.0.0.1',
     'username': '[email protected]',
     'http_accept': 'application/json',
     'path_info': '/account/login/',
     'attempt_time': datetime.datetime(2019, 11, 28, 21, 27, 8, 883077, tzinfo=<UTC>),
     'get_data': '',
     'post_data': '[email protected]',
     'failures_since_start': 1}
    

    With 5.0.19, both attempts with the same login and IP are recorded to separate model instances and there is no lockout on subsequent attempts.

    Has anyone else experienced anything like this?

    documentation bug needs clarification 
    opened by whwkong 16
  • Bugfix #358 credentials in favor of request

    Bugfix #358 credentials in favor of request

    As previously mentioned in #358 the AXES_ONLY_USER_FAILURES setting only works if the login is performed using a Form request. If logging in using JSON, Axes can properly save the failed logins, but is unable to find an existing entry in the axes_attempts table or in cache due to relying on request.POST to find the username.

    I changed this to make use of the credentials or username fields wherever possible, added new tests for thsi behavior and updated the documentation.

    When available, credentials is passed along until it reaches the get_client_username in utils.py. If credentials is not available to be forwarded, but the parsed username from login is available otherwise, a dummy credentials dictionary is created with the settings.AXES_USERNAME_FORM_FIELD key and the username inside it. Only if none of these are availeble the old way to get the username directly from request,POST is attempted. This mainly affects the decorators for the Login forms, but there's neither a good way to access the username otherwise nor will these usually be manipulated to not send a form request for the login.

    Last but not least, I had to introduce a breaking change: The AXES_USERNAME_CALLABLE function now receives the credentials dictionary as additional parameter.

    I think this should also fix #376 as I've just replaced the manual logic for looking up the username from the request with callng get_client_username instead

    bug enhancement 
    opened by mastacheata 16
  • django-reversion compability

    django-reversion compability

    Hi guys,

    following thing: I'm using django-rest-framework and want to secure my backend with axes.

    When I use the default database table type "InnoDB" axes cannot save or update failed attempts in the tables. When I change the table type to "MyIsam", it works.

    I just updated to the latest version. Same as before. Super strange but I couldn't figure out why this happens.

    Best Ronny

    documentation known issue wont fix 
    opened by GitRon 15
  • Django test client compatibility

    Django test client compatibility

    Since version 5, when using the login and force_login methods of the django test client (django version 1.11), exceptions get thrown and tests fail.

    When using force_login() the django test client uses an instance of HttpRequest, but axes requires an AxesHttpRequest.

    from django.test import Client
    client = Client()
    client.force_login(user)
    
    Traceback (most recent call last):
      File "/vagrant/src/project/tests/tests_integration.py", line 87, in setUp
        client.force_login(user)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/django/test/client.py", line 645, in force_login
        self._login(user, backend)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/django/test/client.py", line 658, in _login
        login(request, user, backend)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/django/contrib/auth/__init__.py", line 161, in login
        user_logged_in.send(sender=user.__class__, request=request, user=user)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 193, in send
        for receiver in self._live_receivers(sender)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 193, in <listcomp>
        for receiver in self._live_receivers(sender)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/axes/signals.py", line 26, in handle_user_logged_in
        AxesProxyHandler.user_logged_in(*args, **kwargs)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/axes/handlers/proxy.py", line 52, in user_logged_in
        return cls.get_implementation().user_logged_in(sender, request, user, **kwargs)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/axes/handlers/database.py", line 141, in user_logged_in
        clean_expired_user_attempts(request.axes_attempt_time)
    AttributeError: 'HttpRequest' object has no attribute 'axes_attempt_time'
    

    When using login() the test client uses request=None to authenticate.

    from django.test import Client
    client = Client()
    client.login(user=user.email, password="SecurePassword123")
    
    Traceback (most recent call last):
      File "/vagrant/src/project/tests/tests_integration.py", line 89, in setUp
        client.login(user=user.email, password="SecurePassword123")
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/django/test/client.py", line 628, in login
        user = authenticate(**credentials)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/django/contrib/auth/__init__.py", line 70, in authenticate
        user = _authenticate_with_backend(backend, backend_path, request, credentials)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/django/contrib/auth/__init__.py", line 116, in _authenticate_with_backend
        return backend.authenticate(*args, **credentials)
      File "/home/vagrant/.local/share/virtualenvs/vagrant-gKDsaKU3/lib/python3.6/site-packages/axes/backends.py", line 33, in authenticate
        raise AxesBackendRequestParameterRequired('AxesBackend requires a request as an argument to authenticate')
    axes.exceptions.AxesBackendRequestParameterRequired: AxesBackend requires a request as an argument to authenticate
    
    documentation 
    opened by MWedl 15
  • Enable django-axes only for staff/admin site

    Enable django-axes only for staff/admin site

    I would like to only enable django-axes for staff accounts (preferably only admin site). According to the documentation this is currently not possible (I can't find anything about it). Is it true? Thanks!

    enhancement help wanted 
    opened by csdenboer 15
  • use an authentication backend to check if user is locked out.

    use an authentication backend to check if user is locked out.

    @camilonova First Draft for input.

    USAGE

    settings.py

    AUTHENTICATION_BACKENDS = [
        'axes.middleware.DjangoAxesAuthBackend',
        'django.contrib.auth.backends.ModelBackend',
    ]
    

    login view call example

    user = User.objects.get(email=form.cleaned_data['email'])
    response_context = {}
    user = authenticate(
        request=request,
        username=user.username,
        password=form.cleaned_data['password'],
        response_context=response_context
    )
    ...
    if 'error' not in context:
        # if don't have a more specific error, use a generic one.
        context['error'] = 'Incorrect Login Information'
    render(request, 'log_in.html', context)
    
    enhancement 
    opened by markddavidoff 14
  • Logging respects configuration settings

    Logging respects configuration settings

    This PR enhances external logging for the project in three ways:

    • Log messages contain the correct attributes of the request, when VERBOSE = False.
    • Log messages contain detailed information about the request when VERBOSE = True.
    • Adds a log message for successful login if DISABLE_SUCCESS_ACCESS_LOG = False.

    Accurate logging messages are dependent on the configuration. Settings that it looks at:

    • AXES_LOCK_OUT_BY_COMBINATION_USER_AND_IP
    • AXES_ONLY_USER_FAILURES
    • USE_USER_AGENT
    • VERBOSE

    Log messages were only accurate for the default setting, which exclusively blocks by IP address.

    Below is an example the before and after, for logs from a lockout based on IP username, where AXES_LOCK_OUT_BY_COMBINATION_USER_AND_IP = True.

    Before:

    [2017-04-25 20:20:26,474] [INFO] [axes.watch_login] AXES: BEGIN LOG
    [2017-04-25 20:20:26,474] [INFO] [axes.watch_login] AXES: Using django-axes 2.3.2
    [2017-04-25 20:20:32,361] [INFO] [axes.watch_login] AXES: Calling decorated function: LoginView
    [2017-04-25 20:20:32,473] [INFO] [axes.watch_login] AXES: New login failure by 10.2.3.1. Creating access record.
    [2017-04-25 20:20:33,841] [INFO] [axes.watch_login] AXES: Calling decorated function: LoginView
    [2017-04-25 20:20:34,000] [INFO] [axes.watch_login] AXES: Repeated login failure by 10.2.3.1. Updating access record. Count = 2
    [2017-04-25 20:20:35,149] [INFO] [axes.watch_login] AXES: Calling decorated function: LoginView
    [2017-04-25 20:20:35,290] [INFO] [axes.watch_login] AXES: Repeated login failure by 10.2.3.1. Updating access record. Count = 3
    [2017-04-25 20:20:35,292] [WARNING] [axes.watch_login] AXES: locked out 10.2.3.1 after repeated login attempts.
    

    After:

    [2017-04-25 20:18:27,057] [INFO] [axes.watch_login] AXES: BEGIN LOG
    [2017-04-25 20:18:27,058] [INFO] [axes.watch_login] AXES: Using django-axes 2.3.2
    [2017-04-25 20:18:27,058] [INFO] [axes.watch_login] AXES: blocking by combination of username and IP.
    [2017-04-25 20:18:35,321] [INFO] [axes.watch_login] AXES: Calling decorated function: LoginView
    [2017-04-25 20:18:35,445] [INFO] [axes.watch_login] AXES: New login failure by [email protected] from 10.2.3.1. Creating access record.
    [2017-04-25 20:18:36,570] [INFO] [axes.watch_login] AXES: Calling decorated function: LoginView
    [2017-04-25 20:18:36,701] [INFO] [axes.watch_login] AXES: Repeated login failure by [email protected] from 10.2.3.1. Updating access record. Count = 2 of 3
    [2017-04-25 20:18:37,630] [INFO] [axes.watch_login] AXES: Calling decorated function: LoginView
    [2017-04-25 20:18:37,763] [INFO] [axes.watch_login] AXES: Repeated login failure by [email protected] from 10.2.3.1. Updating access record. Count = 3 of 3
    [2017-04-25 20:18:37,765] [WARNING] [axes.watch_login] AXES: locked out [email protected] from 10.2.3.1 after repeated login attempts.
    

    If VERBOSE is set, then detailed information about the request that triggered the event is logged:

    • Username
    • IP Address
    • User agent
    • Requested path

    This is highly useful information when fed into an external SIEM or logging service, like ELK or Splunk, and used for correlation.

    [2017-04-25 21:50:08,638] [INFO] [axes.watch_login] AXES: BEGIN LOG
    [2017-04-25 21:50:08,638] [INFO] [axes.watch_login] AXES: Using django-axes 2.3.2
    [2017-04-25 21:50:08,638] [INFO] [axes.watch_login] AXES: blocking by combination of username and IP.
    [2017-04-25 21:50:31,896] [INFO] [axes.watch_login] AXES: Calling decorated function: LoginView
    [2017-04-25 21:50:32,016] [INFO] [axes.watch_login] AXES: New login failure by {user: '[email protected]', ip: '10.2.3.1', user-agent: 'Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1', path: '('/api/auth/login/',)'}. Creating access record.
    [2017-04-25 21:50:33,466] [INFO] [axes.watch_login] AXES: Calling decorated function: LoginView
    [2017-04-25 21:50:33,589] [INFO] [axes.watch_login] AXES: Repeated login failure by {user: '[email protected]', ip: '10.2.3.1', user-agent: 'Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1', path: '/api/auth/login/'}. Updating access record. Count = 2 of 3
    [2017-04-25 21:50:34,730] [INFO] [axes.watch_login] AXES: Calling decorated function: LoginView
    [2017-04-25 21:50:34,850] [INFO] [axes.watch_login] AXES: Repeated login failure by {user: '[email protected]', ip: '10.2.3.1', user-agent: 'Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1', path: '/api/auth/login/'}. Updating access record. Count = 3 of 3
    [2017-04-25 21:50:34,851] [WARNING] [axes.watch_login] AXES: locked out {user: '[email protected]', ip: '10.2.3.1', user-agent: 'Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1', path: '/api/auth/login/'} after repeated login attempts.
    

    Finally, capturing successful authentication events in external services may be desirable to track user sessions, detect when brute force has succeeded, or some other use case. When DISABLE_SUCCESS_ACCESS_LOG = False, a log message will be generated for successful authentication.

    [2017-04-25 22:38:34,545] [INFO] [axes.watch_login] AXES: New login failure by [email protected] from 10.2.3.1. Creating access record.
    [2017-04-25 22:38:36,995] [INFO] [axes.watch_login] AXES: Repeated login failure by [email protected] from 10.2.3.1. Updating access record. Count = 2 of 3
    [2017-04-25 22:38:40,477] [INFO] [axes.watch_login] AXES: Successful login by [email protected] from 10.2.3.1. Creating access record.
    
    opened by SafeEval 14
  • Possible bug in signals.py?

    Possible bug in signals.py?

    https://github.com/jazzband/django-axes/blob/master/axes/signals.py#L59

    Should the following:

            for attempt in attempts:
                failures = max(failures, attempt.failures_since_start)
    

    be modified to:

            for attempt in attempts:
                failures += attempt.failures_since_start
    

    Given that settings.AXES_ONLY_USER_FAILURES maybe return multiple attempts from the same user (different path or data). Wouldn't it make sense for all failed attempts to be summed together? 🤔 💭

    Thanks!

    bug needs clarification 
    opened by charleswhchan 13
  • Bump tox from 4.0.16 to 4.1.2

    Bump tox from 4.0.16 to 4.1.2

    Bumps tox from 4.0.16 to 4.1.2.

    Release notes

    Sourced from tox's releases.

    4.1.2

    What's Changed

    Full Changelog: https://github.com/tox-dev/tox/compare/4.1.1...4.1.2

    4.1.1

    What's Changed

    Full Changelog: https://github.com/tox-dev/tox/compare/4.1.0...4.1.1

    4.1.0

    What's Changed

    New Contributors

    Full Changelog: https://github.com/tox-dev/tox/compare/4.0.19...4.1.0

    4.0.18

    What's Changed

    Full Changelog: https://github.com/tox-dev/tox/compare/4.0.17...4.0.18

    4.0.17

    What's Changed

    New Contributors

    Full Changelog: https://github.com/tox-dev/tox/compare/4.0.16...4.0.17

    Changelog

    Sourced from tox's changelog.

    v4.1.2 (2022-12-30)

    Bugfixes - 4.1.2

    - Fix ``--skip-missing-interpreters`` behaviour - by :user:`q0w`. (:issue:`2649`)
    - Restore tox 3 behaviour of showing the output of pip freeze, however now only active when running inside a CI
      environment - by :user:`gaborbernat`. (:issue:`2685`)
    - Fix extracting extras from markers with many extras - by :user:`q0w`. (:issue:`2791`)
    

    v4.1.1 (2022-12-29)

    Bugfixes - 4.1.1

    • Fix logging error with emoji in git branch name. (:issue:2768)

    Improved Documentation - 4.1.1

    - Add faq entry about re-use of environments - by :user:`jugmac00`. (:issue:`2788`)
    

    v4.1.0 (2022-12-29)

    Features - 4.1.0

    - ``-f`` can be used multiple times and on hyphenated factors (e.g. ``-f py311-django -f py39``) - by :user:`sirosen`. (:issue:`2766`)
    

    Improved Documentation - 4.1.0 </code></pre> <ul> <li>Fix a grammatical typo in docs/user_guide.rst. (:issue:<code>2787</code>)</li> </ul> <h2>v4.0.19 (2022-12-28)</h2> <p>Bugfixes - 4.0.19</p> <pre><code>- Create temp_dir if not exists - by :user:q0w. (:issue:2770)

    v4.0.18 (2022-12-26)

    Bugfixes - 4.0.18 </code></pre> <ul> <li>Strip leading and trailing whitespace when parsing elements in requirement files - by :user:<code>gaborbernat</code>. (:issue:<code>2773</code>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary>

    <ul> <li><a href="https://github.com/tox-dev/tox/commit/6253d6220486e17c6132f613cc6218c87b084417"><code>6253d62</code></a> release 4.1.2</li> <li><a href="https://github.com/tox-dev/tox/commit/196b20de4c969a163d34692d8a5d646cad4717d6"><code>196b20d</code></a> Fix extracting extras from markers with many extras (<a href="https://github-redirect.dependabot.com/tox-dev/tox/issues/2792">#2792</a>)</li> <li><a href="https://github.com/tox-dev/tox/commit/a3d3ec042d38195392841a9112911c2bde3587d1"><code>a3d3ec0</code></a> Show installed packages after setup in CI envs (<a href="https://github-redirect.dependabot.com/tox-dev/tox/issues/2794">#2794</a>)</li> <li><a href="https://github.com/tox-dev/tox/commit/d8c4cb0ffa1999b5d6466e0099dab76f242b1ba8"><code>d8c4cb0</code></a> Fix --skip-missing-interpreters (<a href="https://github-redirect.dependabot.com/tox-dev/tox/issues/2793">#2793</a>)</li> <li><a href="https://github.com/tox-dev/tox/commit/1d739a2641bcb0545815afbabf8b3da9694ec0ff"><code>1d739a2</code></a> release 4.1.1</li> <li><a href="https://github.com/tox-dev/tox/commit/b49d11867ab6bd7219c5b2c50f610e7829395975"><code>b49d118</code></a> Fix logging error with emoji in git branch name. (<a href="https://github-redirect.dependabot.com/tox-dev/tox/issues/2790">#2790</a>)</li> <li><a href="https://github.com/tox-dev/tox/commit/c83819262b4b739899af8a0bd7b6f32442344e4a"><code>c838192</code></a> Add faq entry about re-use of environments (<a href="https://github-redirect.dependabot.com/tox-dev/tox/issues/2789">#2789</a>)</li> <li><a href="https://github.com/tox-dev/tox/commit/e0aed508607d34559610fbb0d2b4fd038da9c11b"><code>e0aed50</code></a> release 4.1.0</li> <li><a href="https://github.com/tox-dev/tox/commit/6cdd99cc3ce4fc73455374b40f2dd8a95ef101c5"><code>6cdd99c</code></a> Improved factor selection to allow multiple uses of <code>-f</code> for &quot;OR&quot; and to allo...</li> <li><a href="https://github.com/tox-dev/tox/commit/6f056cafcca6cee4b23a35fdfc2044647c99e8d7"><code>6f056ca</code></a> Update user_guide.rst (<a href="https://github-redirect.dependabot.com/tox-dev/tox/issues/2787">#2787</a>)</li> <li>Additional commits viewable in <a href="https://github.com/tox-dev/tox/compare/4.0.16...4.1.2">compare view</a></li> </ul> </details>

    <br />

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    python dependencies 
    opened by dependabot[bot] 0
  • Bump coverage from 7.0.0 to 7.0.1

    Bump coverage from 7.0.0 to 7.0.1

    Bumps coverage from 7.0.0 to 7.0.1.

    Changelog

    Sourced from coverage's changelog.

    Version 7.0.1 — 2022-12-23

    • When checking if a file mapping resolved to a file that exists, we weren't considering files in .whl files. This is now fixed, closing issue 1511_.

    • File pattern rules were too strict, forbidding plus signs and curly braces in directory and file names. This is now fixed, closing issue 1513_.

    • Unusual Unicode or control characters in source files could prevent reporting. This is now fixed, closing issue 1512_.

    • The PyPy wheel now installs on PyPy 3.7, 3.8, and 3.9, closing issue 1510_.

    .. _issue 1510: nedbat/coveragepy#1510 .. _issue 1511: nedbat/coveragepy#1511 .. _issue 1512: nedbat/coveragepy#1512 .. _issue 1513: nedbat/coveragepy#1513

    .. _changes_7-0-0:

    Commits
    • c5cda3a docs: releases take a little bit longer now
    • 9d4226e docs: latest sample HTML report
    • 8c77758 docs: prep for 7.0.1
    • da1b282 fix: also look into .whl files for source
    • d327a70 fix: more information when mapping rules aren't working right.
    • 35e249f fix: certain strange characters caused reporting to fail. #1512
    • 152cdc7 fix: don't forbid plus signs in file names. #1513
    • 31513b4 chore: make upgrade
    • 873b059 test: don't run tests on Windows PyPy-3.9
    • 5c5caa2 build: PyPy wheel now installs on 3.7, 3.8, and 3.9. #1510
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    python dependencies 
    opened by dependabot[bot] 0
  • Migration 007 relation

    Migration 007 relation "axes_accessattempt" does not exist

    Python version: 3.10.8 Django Version: 4.0.8 Django-axes version: 5.40.0

    Scenario: When upgrading from django-axes 5.39.0 to django-axes 5.40.0, with the django version of 4.0.8 remaining constant, we're encountering this exception below when trying to run all migrations in order on a fresh database. Reverting to django-axes 5.39.0 causes this error to disappear.

    I've previously searched for errors similar to this and found that this one might be tangentially related, but it also seems to predate the 5.40.0 version release, and may be specific to django 4.1, which is not the case here.

    Snippet of exception below:

    File "/.venv/lib/python3.10/site-packages/axes/migrations/0007_alter_accessattempt_unique_together.py", line 18, in deduplicate_attempts
        for attempt in duplicated_attempts:
      File "/.venv/lib/python3.10/site-packages/django/db/models/query.py", line 320, in __iter__
        self._fetch_all()
      File "/.venv/lib/python3.10/site-packages/django/db/models/query.py", line 1507, in _fetch_all
        self._result_cache = list(self._iterable_class(self))
      File "/.venv/lib/python3.10/site-packages/django/db/models/query.py", line 130, in __iter__
        for row in compiler.results_iter(
      File "/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1312, in results_iter
        results = self.execute_sql(
      File "/.venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1361, in execute_sql
        cursor.execute(sql, params)
      File "/.venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 67, in execute
        return self._execute_with_wrappers(
      File "/.venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
        return executor(sql, params, many, context)
      File "/.venv/lib/python3.10/site-packages/django_read_only/__init__.py", line 77, in blocker
        return execute(sql, params, many, context)
      File "/.venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 84, in _execute
        with self.db.wrap_database_errors:
      File "/.venv/lib/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
        raise dj_exc_value.with_traceback(traceback) from exc_value
      File "/.venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
        return self.cursor.execute(sql, params)
    django.db.utils.ProgrammingError: relation "axes_accessattempt" does not exist
    LINE 1: ...NT("axes_accessattempt"."id") AS "id__count" FROM "axes_acce...
    
    bug needs clarification 
    opened by js-truework 7
  • Unit Testing

    Unit Testing

    I get the error "AXES: New login failure by {username: "None", ip_address: "None", user_agent: "", path_info: ""}. Created new record in the database." when running unit test with Axes backend. The test runs successfully, but how can I fix the error?

       def test_admin(self):
             request = HttpRequest()
             authenticate(
                   request,
                  username=self.user.username,
                  password=self.user.password,
             )
    
        self.assertTrue(self.admin_user.is_authenticated)
        self.assertEqual(self.admin_user.username, "admin_1")
        self.assertTrue(self.admin_user.is_superuser)
        self.assertNotEqual(self.admin_user.is_staff, False)
    
    opened by edmundrotimi 0
  • Cannot use Token-based Authentication Backend unless AXES_ONLY_USER_FAILURES is set to True.

    Cannot use Token-based Authentication Backend unless AXES_ONLY_USER_FAILURES is set to True.

    I am running into a similar issue as #597 where I am using a Token Authentication Backend along side User-based authentication backends and I want to use Axes only for those User-based backends. I am running into an issue where my token based authentication will generate user_login_failed callbacks and as a result try and create AccessAttempt records with a username of "None" (a string).

    I can work around this by setting AXES_ONLY_USER_FAILURES to True, however I really would like to do IP-based blocking (maybe AXES_LOCK_OUT_BY_USER_OR_IP or even just IP-based lockouts instead.

    opened by Kraust 0
Releases(5.40.1)
Owner
Jazzband
We are all part of this
Jazzband
PostgreSQL with Docker + Portainer + pgAdmin + Django local

django-postgresql-docker Running PostgreSQL with Docker + Portainer + pgAdmin + Django local for development. This project was done with: Python 3.9.8

Regis Santos 4 Jun 12, 2022
This is a repository for a web application developed with Django, built with Crowdbotics

assignment_32558 This is a repository for a web application developed with Django, built with Crowdbotics Table of Contents Project Structure Features

Crowdbotics 1 Dec 29, 2021
React.JS - Django Application Template

OTS React.JS - DJango Web Application (UNTESTED) This repository servers as a template for creating React.JS - Django Web Applications. Note that the

Darryl See Wei Shen 5 Aug 19, 2022
A test microblog project created using Django 4.0

django-microblog This is a test microblog project created using Django 4.0. But don't worry this is a fully working project. There is no super-amazing

Ali Kasimoglu 8 Jan 14, 2022
PWA is a simple Django app to develope and deploy a Progressive Web Application.

PWA PWA is a simple Django app to develope and deploy a Progressive Web Application. Detailed documentation is in the "docs" directory. Quick start Ad

Nima 6 Dec 09, 2022
This website serves as an online database (hosted via SQLLite) for fictional businesses in the area to store contact information (name, email, phone number, etc.) for fictional customers.

Django-Online-Business-Database-Project this project is still in progress Overview of Website This website serves as an online database (hosted via SQ

1 Oct 30, 2021
Imparare Django ricreando un sito facsimile a quello Flask

SitoPBG-Django Imparare Django ricreando un sito facsimile a quello Flask Note di utilizzo Necessita la valorizzazione delle seguenti variabili di amb

Mario Nardi 1 Dec 08, 2021
Phoenix LiveView but for Django

Reactor, a LiveView library for Django Reactor enables you to do something similar to Phoenix framework LiveView using Django Channels. What's in the

Eddy Ernesto del Valle Pino 526 Jan 02, 2023
Automatic caching and invalidation for Django models through the ORM.

Cache Machine Cache Machine provides automatic caching and invalidation for Django models through the ORM. For full docs, see https://cache-machine.re

846 Nov 26, 2022
Python port of Google's libphonenumber

phonenumbers Python Library This is a Python port of Google's libphonenumber library It supports Python 2.5-2.7 and Python 3.x (in the same codebase,

David Drysdale 3.1k Jan 08, 2023
Vehicle registration using Python, Django and SQlite3

PythonCrud Cadastro de veículos utilizando Python, Django e SQlite3 Para acessar o deploy no Heroku:

Jorge Thiago 4 May 20, 2022
Py-instant-search-redis - Source code example for how to build an instant search with redis in python

py-instant-search-redis Source code example for how to build an instant search (

Giap Le 4 Feb 17, 2022
A simple demonstration of how a django-based website can be set up for local development with microk8s

Django with MicroK8s Start Building Your Project This project provides a Django web app running as a single node Kubernetes cluster in microk8s. It is

Noah Jacobson 19 Oct 22, 2022
django-tables2 - An app for creating HTML tables

django-tables2 - An app for creating HTML tables django-tables2 simplifies the task of turning sets of data into HTML tables. It has native support fo

Jan Pieter Waagmeester 1.6k Jan 03, 2023
Adding Firebase Cloud Messaging Service into a Django Project

Adding Firebase Cloud Messaging Service into a Django Project The aim of this repository is to provide a step-by-step guide and a basic project sample

Seyyed Ali Ayati 11 Jan 03, 2023
An API was build with Django to store and retrieve information about various musical instruments.

The project is meant to be a starting point, an experimentation or a basic example of a way to develop an API with Django. It is an exercise on using Django and various python technologies and design

Kostas Ziovas 2 Dec 25, 2021
User Authentication In Django/Ajax/Jquery

User Authentication In Django/Ajax/Jquery Demo: Authentication System Using Django/Ajax/Jquery Demo: Authentication System Using Django Overview The D

Suman Raj Khanal 10 Mar 26, 2022
pytest-django allows you to test your Django project/applications with the pytest testing tool.

pytest-django allows you to test your Django project/applications with the pytest testing tool.

pytest-dev 1.1k Dec 14, 2022
Duckiter will Automatically dockerize your Django projects.

Duckiter Duckiter will Automatically dockerize your Django projects. Requirements : - python version : python version 3.6 or upper version - OS :

soroush safari 23 Sep 16, 2021
Simple XML-RPC and JSON-RPC server for modern Django

django-modern-rpc Build an XML-RPC and/or JSON-RPC server as part of your Django project. Major Django and Python versions are supported Main features

Antoine Lorence 82 Dec 04, 2022