diff --git a/plinth/__main__.py b/plinth/__main__.py index 3be807a30..51b5f9db1 100644 --- a/plinth/__main__.py +++ b/plinth/__main__.py @@ -242,6 +242,7 @@ def configure_django(): 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ], + AXES_LOCKOUT_URL='locked', CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}, CAPTCHA_FONT_PATH=['/usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf'], diff --git a/plinth/modules/sso/views.py b/plinth/modules/sso/views.py index c9615c289..c1146526f 100644 --- a/plinth/modules/sso/views.py +++ b/plinth/modules/sso/views.py @@ -30,6 +30,10 @@ from django.contrib.auth import REDIRECT_FIELD_NAME from django.contrib.auth.decorators import login_required from django.contrib.auth.views import LoginView, LogoutView +from django.shortcuts import render_to_response + +from axes.utils import reset + PRIVATE_KEY_FILE_NAME = 'privkey.pem' SSO_COOKIE_NAME = 'auth_pubtkt' KEYS_DIRECTORY = '/etc/apache2/auth-pubtkt-keys' @@ -58,22 +62,37 @@ class SSOLoginView(LoginView): def dispatch(self, request, *args, **kwargs): response = super(SSOLoginView, self).dispatch(request, *args, **kwargs) + if request.user.is_authenticated: + return set_ticket_cookie(request.user, response) + else: + return response + + +class CaptchaLoginView(LoginView): + redirect_authenticated_user = True + template_name = 'login.html' + form_class = AuthenticationForm + + def dispatch(self, request, *args, **kwargs): + response = super(CaptchaLoginView, self).dispatch( + request, *args, **kwargs) if request.POST: if request.user.is_authenticated: + ip = get_ip_address_from_request(request) + reset() # TODO reset(ip=ip) return set_ticket_cookie(request.user, response) - else: # Redirect user to captcha page - redirect = '' if request.path.rstrip('/').endswith('captcha') else 'captcha' - return HttpResponseRedirect(redirect) + else: + return response return response -class CaptchaLoginView(SSOLoginView): - form_class = AuthenticationForm +def get_ip_address_from_request(request): + # TODO Not sure if this is the right way to get the client ip + return request.META['HTTP_X_FORWARDED_FOR'] class SSOLogoutView(LogoutView): """View to log out of Plinth and remove the auth_pubtkt cookie""" - template_name = 'index.html' def dispatch(self, request, *args, **kwargs): diff --git a/plinth/modules/users/urls.py b/plinth/modules/users/urls.py index 9b150ebb8..b51cc10be 100644 --- a/plinth/modules/users/urls.py +++ b/plinth/modules/users/urls.py @@ -23,7 +23,7 @@ from django.urls import reverse_lazy from stronghold.decorators import public from plinth.utils import non_admin_view -from plinth.modules.sso.views import SSOLoginView, SSOLogoutView, CaptchaLoginView +from plinth.modules.sso.views import SSOLoginView, SSOLogoutView from . import views from axes.decorators import watch_login @@ -49,9 +49,6 @@ urlpatterns = [ non_admin_view(SSOLogoutView.as_view()), {'next_page': reverse_lazy('index')}, name='logout'), - url(r'^accounts/login/captcha/$', - public(CaptchaLoginView.as_view()), - name='captcha-login'), url(r'^users/firstboot/$', public(views.FirstBootView.as_view()), name='firstboot'), diff --git a/plinth/urls.py b/plinth/urls.py index 7566f7e19..e9b76dcde 100644 --- a/plinth/urls.py +++ b/plinth/urls.py @@ -18,9 +18,10 @@ Django URLconf file containing all urls """ from captcha import views as cviews -from django.conf.urls import url, include +from django.conf.urls import url from django.views.generic import TemplateView +from plinth.modules.sso.views import CaptchaLoginView from stronghold.decorators import public from . import views @@ -43,4 +44,5 @@ urlpatterns = [ kwargs={'scale': 2}), url(r'audio/(?P\w+)/$', public(cviews.captcha_audio), name='captcha-audio'), url(r'refresh/$', public(cviews.captcha_refresh), name='captcha-refresh'), + url(r'locked/$', public(CaptchaLoginView.as_view()), name='locked_out'), ] diff --git a/plinth/utils.py b/plinth/utils.py index 8c14755c1..e0a6856db 100644 --- a/plinth/utils.py +++ b/plinth/utils.py @@ -57,7 +57,7 @@ def non_admin_view(func): def is_user_admin(request, cached=False): """Return whether user is an administrator.""" - if not request.user.is_authenticated(): + if not request.user.is_authenticated: return False if 'cache_user_is_admin' in request.session and cached: