From 0f807bcd4806776308dcd43faedd449992eb3a6d Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Mon, 15 Jul 2019 15:01:53 -0700 Subject: [PATCH] sso: Use new features of axes, log axes messages Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- plinth/__main__.py | 9 +++++---- plinth/axes_app_config.py | 2 +- plinth/modules/sso/views.py | 15 ++++++++++----- plinth/modules/users/urls.py | 3 +++ plinth/tests/data/django_test_settings.py | 9 +++++++++ plinth/utils.py | 11 +++++++++++ plinth/web_framework.py | 1 + 7 files changed, 40 insertions(+), 10 deletions(-) diff --git a/plinth/__main__.py b/plinth/__main__.py index 39392fcb5..ee99b2c66 100644 --- a/plinth/__main__.py +++ b/plinth/__main__.py @@ -21,12 +21,13 @@ import importlib import logging import sys -import axes - from . import (__version__, cfg, dbus, frontpage, log, menu, module_loader, - setup, web_framework, web_server) + setup, utils, web_framework, web_server) + +if utils.is_axes_old(): + import axes + axes.default_app_config = 'plinth.axes_app_config.AppConfig' -axes.default_app_config = "plinth.axes_app_config.AppConfig" precedence_commandline_arguments = ["server_dir", "develop"] logger = logging.getLogger(__name__) diff --git a/plinth/axes_app_config.py b/plinth/axes_app_config.py index 56602e0cb..cca9097fa 100644 --- a/plinth/axes_app_config.py +++ b/plinth/axes_app_config.py @@ -26,4 +26,4 @@ class AppConfig(apps.AppConfig): def ready(self): # Signals must be loaded for axes to get the login_failed signals - from axes import signals # isort:skip + from axes import signals # isort:skip pylint: disable=unused-import diff --git a/plinth/modules/sso/views.py b/plinth/modules/sso/views.py index 2ecbe135d..ef3c98aa0 100644 --- a/plinth/modules/sso/views.py +++ b/plinth/modules/sso/views.py @@ -28,7 +28,7 @@ from django.contrib.auth import REDIRECT_FIELD_NAME from django.contrib.auth.views import LoginView, LogoutView from django.http import HttpResponseRedirect -from plinth import actions, web_framework +from plinth import actions, utils, web_framework from .forms import AuthenticationForm @@ -69,6 +69,8 @@ class SSOLoginView(LoginView): return response + # XXX: Use axes middleware and authentication backend instead of + # axes_form_invalid when axes >= 5.0.0 becomes available in Debian stable. @axes_form_invalid def form_invalid(self, *args, **kwargs): return super(SSOLoginView, self).form_invalid(*args, **kwargs) @@ -89,10 +91,13 @@ class CaptchaLoginView(LoginView): return response # Successful authentication - ip_address = web_framework.get_ip_address_from_request(request) - axes.utils.reset(ip=ip_address) - logger.info('Login attempts reset for IP after successful login: %s', - ip_address) + if utils.is_axes_old(): + ip_address = web_framework.get_ip_address_from_request(request) + axes.utils.reset(ip=ip_address) + logger.info( + 'Login attempts reset for IP after successful login: %s', + ip_address) + return set_ticket_cookie(request.user, response) diff --git a/plinth/modules/users/urls.py b/plinth/modules/users/urls.py index 9aea81d69..aa86d69d4 100644 --- a/plinth/modules/users/urls.py +++ b/plinth/modules/users/urls.py @@ -40,6 +40,9 @@ urlpatterns = [ name='change_password'), # Authnz is handled by SSO + + # XXX: Use axes authentication backend and middleware instead of + # axes_dispatch after axes 5.x becomes available in Debian stable. url(r'^accounts/login/$', public(axes_dispatch(SSOLoginView.as_view())), name='login'), url(r'^accounts/logout/$', diff --git a/plinth/tests/data/django_test_settings.py b/plinth/tests/data/django_test_settings.py index 461766e7c..c0299fb8a 100644 --- a/plinth/tests/data/django_test_settings.py +++ b/plinth/tests/data/django_test_settings.py @@ -22,6 +22,14 @@ import os TEST_DATA_DIR = os.path.dirname(os.path.abspath(__file__)) +AXES_ENABLED = False + +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.dummy.DummyCache' + } +} + DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', @@ -30,6 +38,7 @@ DATABASES = { } INSTALLED_APPS = [ + 'axes', 'captcha', 'bootstrapform', 'django.contrib.auth', diff --git a/plinth/utils.py b/plinth/utils.py index 78fbb9ca3..c0821b60d 100644 --- a/plinth/utils.py +++ b/plinth/utils.py @@ -164,3 +164,14 @@ def gunzip(gzip_file, output_file): def is_non_empty_file(file_path): return os.path.isfile(file_path) and os.path.getsize(file_path) > 0 + + +def is_axes_old(): + """Return true if using django-axes version strictly less than 5.0.0. + + XXX: Remove this method and allow code that uses it after django-axes >= + 5.0.0 becomes available in Debian stable. + + """ + import axes + return LooseVersion(axes.get_version()) < LooseVersion('5.0') diff --git a/plinth/web_framework.py b/plinth/web_framework.py index 770e432ac..6110502e9 100644 --- a/plinth/web_framework.py +++ b/plinth/web_framework.py @@ -98,6 +98,7 @@ def init(): }, ], AXES_LOCKOUT_URL='locked/', + AXES_RESET_ON_SUCCESS=True, # Only used with axes >= 4.4.3 CACHES={ 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache'