From 481a1088ee27bb3af7d4e6122e12c2210c4a4195 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 1 Nov 2021 01:05:29 +0100 Subject: [PATCH] fix adapters to use OTP --- InvenTree/InvenTree/forms.py | 32 +++++++++++++++++++++++++++++++- InvenTree/InvenTree/settings.py | 3 +-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index 7a7668cf66..02b993d31b 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -4,12 +4,15 @@ Helper forms which subclass Django forms to provide additional functionality # -*- coding: utf-8 -*- from __future__ import unicode_literals +from urllib.parse import urlencode import logging from django.utils.translation import ugettext_lazy as _ from django import forms from django.contrib.auth.models import User, Group from django.conf import settings +from django.http import HttpResponseRedirect +from django.urls import reverse from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout, Field @@ -18,6 +21,9 @@ from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppende from allauth.account.forms import SignupForm, set_form_field_order from allauth.account.adapter import DefaultAccountAdapter from allauth.socialaccount.adapter import DefaultSocialAccountAdapter +from allauth.exceptions import ImmediateHttpResponse +from allauth_2fa.adapter import OTPAdapter +from allauth_2fa.utils import user_has_valid_totp_device from part.models import PartCategory from common.models import InvenTreeSetting @@ -278,7 +284,7 @@ class RegistratonMixin: return user -class CustomAccountAdapter(RegistratonMixin, DefaultAccountAdapter): +class CustomAccountAdapter(RegistratonMixin, OTPAdapter, DefaultAccountAdapter): """ Override of adapter to use dynamic settings """ @@ -297,3 +303,27 @@ class CustomSocialAccountAdapter(RegistratonMixin, DefaultSocialAccountAdapter): if InvenTreeSetting.get_setting('LOGIN_SIGNUP_SSO_AUTO', True): return super().is_auto_signup_allowed(request, sociallogin) return False + + # from OTPAdapter + def has_2fa_enabled(self, user): + """Returns True if the user has 2FA configured.""" + return user_has_valid_totp_device(user) + + def login(self, request, user): + # Require two-factor authentication if it has been configured. + if self.has_2fa_enabled(user): + # Cast to string for the case when this is not a JSON serializable + # object, e.g. a UUID. + request.session['allauth_2fa_user_id'] = str(user.id) + + redirect_url = reverse('two-factor-authenticate') + # Add GET parameters to the URL if they exist. + if request.GET: + redirect_url += u'?' + urlencode(request.GET) + + raise ImmediateHttpResponse( + response=HttpResponseRedirect(redirect_url) + ) + + # Otherwise defer to the original allauth adapter. + return super().login(request, user) diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index e740107c0e..6ee0c6e3a7 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -767,8 +767,7 @@ ACCOUNT_FORMS = { } SOCIALACCOUNT_ADAPTER = 'InvenTree.forms.CustomSocialAccountAdapter' -# ACCOUNT_ADAPTER = 'InvenTree.forms.CustomAccountAdapter' # TODO monkey-patch adapter -ACCOUNT_ADAPTER = 'allauth_2fa.adapter.OTPAdapter' +ACCOUNT_ADAPTER = 'InvenTree.forms.CustomAccountAdapter' # Markdownx configuration # Ref: https://neutronx.github.io/django-markdownx/customization/