Refactor is_user_lockable

Signed-off-by: Aleksi Häkli <aleksi.hakli@iki.fi>
This commit is contained in:
Aleksi Häkli 2019-02-13 00:55:53 +02:00
parent c3e471a211
commit 911de8f347
No known key found for this signature in database
GPG key ID: 3E7146964D726BBE
2 changed files with 40 additions and 23 deletions

View file

@ -1,5 +1,6 @@
from datetime import timedelta
from hashlib import md5
from logging import getLogger
from django.contrib.auth import get_user_model
from django.utils import timezone
@ -8,6 +9,8 @@ from axes.conf import settings
from axes.models import AccessAttempt
from axes.utils import get_axes_cache, get_client_ip, get_client_username
log = getLogger(settings.AXES_LOGGER)
def _query_user_attempts(request, credentials=None):
"""
@ -151,32 +154,25 @@ def ip_in_blacklist(ip):
def is_user_lockable(request, credentials=None):
"""
Check if the user has a profile with nolockout attribute set.
If so, then return the value to see if this user is special and does not get their account locked out.
"""
if request.method != 'POST':
return True
username_field = getattr(get_user_model(), 'USERNAME_FIELD', 'username')
username_value = get_client_username(request, credentials)
kwargs = {
username_field: username_value
}
UserModel = get_user_model()
# Special users with nolockout attribute set should never be locked out
try:
field = getattr(get_user_model(), 'USERNAME_FIELD', 'username')
kwargs = {
field: get_client_username(request, credentials)
}
user = get_user_model().objects.get(**kwargs)
user = UserModel.objects.get(**kwargs)
return not user.nolockout
except (UserModel.DoesNotExist, AttributeError):
pass
if hasattr(user, 'nolockout'):
# need to invert since we need to return
# false for users that can't be blocked
return not user.nolockout
except get_user_model().DoesNotExist:
# not a valid user
return True
# Default behavior for a user to be lockable
# Default case is that users can be locked out
return True

View file

@ -5,14 +5,14 @@ import string
import time
from unittest.mock import patch
from django.contrib.auth import authenticate
from django.contrib.auth import authenticate, get_user_model
from django.contrib.auth.models import User
from django.http import HttpRequest
from django.test import TestCase, override_settings
from django.test.client import RequestFactory
from django.urls import reverse
from axes.attempts import get_cache_key
from axes.attempts import get_cache_key, is_user_lockable
from axes.conf import settings
from axes.models import AccessAttempt, AccessLog
from axes.signals import user_locked_out
@ -496,3 +496,24 @@ class AccessAttemptTest(TestCase):
# But we should find one now
response = self._login()
self.assertContains(response, self.LOCKED_MESSAGE, status_code=403)
@patch('axes.attempts.log')
def test_is_user_lockable(self, log):
request = HttpRequest()
request.method = 'POST'
UserModel = get_user_model()
UserModel.objects.create(username='jane.doe')
with self.subTest('User is marked as nolockout.'):
with patch.object(UserModel, 'nolockout', True, create=True):
lockable = is_user_lockable(request, {'username': 'jane.doe'})
self.assertFalse(lockable)
with self.subTest('User exists but attemptee can be locked out.'):
lockable = is_user_lockable(request, {'username': 'jane.doe'})
self.assertTrue(lockable)
with self.subTest('User does not exist and attemptee can be locked out.'):
lockable = is_user_lockable(request, {'username': 'john.doe'})
self.assertTrue(lockable)