Repository: jazzband/django-axes (python)

Issue:
`force_login` not working in tests
Hey,

I've tried following the documentation and setting `AXES_ENABLED = False` in the test settings, but that did not work. I also tried removing 'axes' from INSTALLED_APPS in my test settings, but that also did not work?

I was able to get the test to work by using `client.login` and passing in a mock request, but it would be nicer if I could get it to work by just setting `AXES_ENABLED`.

My test:
``` python
@override_settings(AXES_ENABLED=False)
def test_gives_non_cas_admin_403_on_cas_admin_url(client, django_user_model):
    user = django_user_model.objects.create()

    client.force_login(user)
    response = client.get(reverse('create_user'))

    assert response.status_code == 403
```
The test is failing because it redirect back to the login view since the `force_login` is not working

Pull request description:
Remove unused backend methods
# What does this PR do?

`AxesStandaloneBackend` was inheriting a default implementation of `get_user()` from `BaseBackend`. Django's `force_login()` uses the first authentication backend that has a `get_user()` method for authorization (since django/django#7634), which fails because `AxesStandaloneBackend` will always be first but can't authorize.

The existing tests didn't notice this, because they never try to do a request after `force_login()`.

By removing the `BaseBackend` parent class, `AxesStandaloneBackend` doesn't have a `get_user()` method anymore, and will be skipped by `force_login()`. Since `AxesStandaloneBackend` never authorizes a user, nothing will ever try to call the inexisting `get_user()`.

This is the same solution [django-rules](https://github.com/dfunckt/django-rules) uses.

Fixes #998.

## Before submitting
- [ ] This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
- [ ] Did you make sure to update the documentation with your changes?
- [x] Did you write any new necessary tests?


Patch:
diff --git a/axes/backends.py b/axes/backends.py
index 6cec9b5..2cec578 100644
--- a/axes/backends.py
+++ b/axes/backends.py
@@ -1,6 +1,6 @@
 from typing import Optional
 from django.conf import settings
-from django.contrib.auth.backends import BaseBackend, ModelBackend
+from django.contrib.auth.backends import ModelBackend
 from django.http import HttpRequest
 
 from axes.exceptions import (
@@ -11,7 +11,7 @@ from axes.handlers.proxy import AxesProxyHandler
 from axes.helpers import get_credentials, get_lockout_message, toggleable
 
 
-class AxesStandaloneBackend(BaseBackend):
+class AxesStandaloneBackend:
     """
     Authentication backend class that forbids login attempts for locked out users.
 
diff --git a/requirements.txt b/requirements.txt
index 814edbf..b5fae12 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,4 +2,4 @@
 -r requirements-qa.txt
 -r requirements-test.txt
 sphinx_rtd_theme==1.2.2
-tox==4.6.2
+tox==4.6.3


Test patch:
diff --git a/tests/test_login.py b/tests/test_login.py
index 1caf0ad..80b602f 100644
--- a/tests/test_login.py
+++ b/tests/test_login.py
@@ -28,7 +28,7 @@ class DjangoLoginTestCase(TestCase):
         self.username = "john.doe"
         self.password = "hunter2"
 
-        self.user = get_user_model().objects.create(username=self.username)
+        self.user = get_user_model().objects.create(username=self.username, is_staff=True)
         self.user.set_password(self.password)
         self.user.save()
         self.user.backend = "django.contrib.auth.backends.ModelBackend"
@@ -47,13 +47,19 @@ class DjangoContribAuthLoginTestCase(DjangoLoginTestCase):
 class DjangoTestClientLoginTestCase(DjangoLoginTestCase):
     def test_client_login(self):
         self.client.login(username=self.username, password=self.password)
+        response = self.client.get(reverse("admin:index"))
+        self.assertEqual(response.status_code, 200)
 
     def test_client_logout(self):
         self.client.login(username=self.username, password=self.password)
         self.client.logout()
+        response = self.client.get(reverse("admin:index"))
+        self.assertEqual(response.status_code, 302)
 
     def test_client_force_login(self):
         self.client.force_login(self.user)
+        response = self.client.get(reverse("admin:index"))
+        self.assertEqual(response.status_code, 200)
 
 
 class DatabaseLoginTestCase(AxesTestCase):
@@ -283,7 +289,7 @@ class DatabaseLoginTestCase(AxesTestCase):
         # Test he is locked by user_agent:
         response = self._login("username2", self.VALID_PASSWORD, ip_addr=self.IP_2, user_agent="test-browser")
         self.assertEqual(response.status_code, self.BLOCKED)
-       
+
         # Test he is allowed to login with different username, ip and user_agent
         response = self._login("username2", self.VALID_PASSWORD, ip_addr=self.IP_2, user_agent="test-browser2")
         self.assertEqual(response.status_code, self.ATTEMPT_NOT_BLOCKED)
@@ -308,7 +314,7 @@ class DatabaseLoginTestCase(AxesTestCase):
         # Test he is allowed to login with different user_agent:
         response = self._login("username", self.VALID_PASSWORD, ip_addr=self.IP_1, user_agent="test-browser2")
         self.assertEqual(response.status_code, self.ATTEMPT_NOT_BLOCKED)
-       
+
         # Test he is allowed to login with different username, ip and user_agent
         response = self._login("username2", self.VALID_PASSWORD, ip_addr=self.IP_2, user_agent="test-browser2")
         self.assertEqual(response.status_code, self.ATTEMPT_NOT_BLOCKED)