mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
enforce mfa on all frontend pages
This commit is contained in:
parent
527bc4381d
commit
eaf1a4baec
@ -1,12 +1,17 @@
|
||||
from django.shortcuts import HttpResponseRedirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.urls import reverse_lazy, Resolver404
|
||||
from django.db import connection
|
||||
from django.shortcuts import redirect
|
||||
from django.conf.urls import include, url
|
||||
import logging
|
||||
import time
|
||||
import operator
|
||||
|
||||
from rest_framework.authtoken.models import Token
|
||||
from allauth_2fa.middleware import BaseRequire2FAMiddleware
|
||||
|
||||
from InvenTree.urls import frontendpatterns
|
||||
|
||||
|
||||
logger = logging.getLogger("inventree")
|
||||
|
||||
@ -146,3 +151,16 @@ class QueryCountMiddleware(object):
|
||||
print(x[0], ':', x[1])
|
||||
|
||||
return response
|
||||
|
||||
|
||||
url_matcher = url('', include(frontendpatterns))
|
||||
|
||||
class Check2FAMiddleware(BaseRequire2FAMiddleware):
|
||||
def require_2fa(self, request):
|
||||
# Superusers are require to have 2FA.
|
||||
try:
|
||||
if url_matcher.resolve(request.path[1:]):
|
||||
return True
|
||||
except Resolver404:
|
||||
pass
|
||||
return False
|
||||
|
@ -304,7 +304,8 @@ MIDDLEWARE = CONFIG.get('middleware', [
|
||||
'allauth_2fa.middleware.AllauthTwoFactorMiddleware', # Flow control for allauth
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'InvenTree.middleware.AuthRequiredMiddleware'
|
||||
'InvenTree.middleware.AuthRequiredMiddleware',
|
||||
'InvenTree.middleware.Check2FAMiddleware', # Check if the user should be forced to use MFA
|
||||
])
|
||||
|
||||
# Error reporting middleware
|
||||
|
@ -37,7 +37,7 @@ from rest_framework.documentation import include_docs_urls
|
||||
|
||||
from .views import auth_request
|
||||
from .views import IndexView, SearchView, DatabaseStatsView
|
||||
from .views import SettingsView, EditUserView, SetPasswordView, CustomEmailView, CustomConnectionsView, CustomPasswordResetFromKeyView
|
||||
from .views import SettingsView, EditUserView, SetPasswordView, CustomEmailView, CustomConnectionsView, CustomPasswordResetFromKeyView, CustomTwoFactorAuthenticate
|
||||
from .views import CurrencyRefreshView
|
||||
from .views import AppearanceSelectView, SettingCategorySelectView
|
||||
from .views import DynamicJsView
|
||||
@ -122,15 +122,29 @@ translated_javascript_urls = [
|
||||
url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/translated/table_filters.js'), name='table_filters.js'),
|
||||
]
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^part/', include(part_urls)),
|
||||
url(r'^manufacturer-part/', include(manufacturer_part_urls)),
|
||||
url(r'^supplier-part/', include(supplier_part_urls)),
|
||||
|
||||
backendpatterns = [
|
||||
# "Dynamic" javascript files which are rendered using InvenTree templating.
|
||||
url(r'^js/dynamic/', include(dynamic_javascript_urls)),
|
||||
url(r'^js/i18n/', include(translated_javascript_urls)),
|
||||
|
||||
url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
url(r'^auth/?', auth_request),
|
||||
|
||||
url(r'^admin/error_log/', include('error_report.urls')),
|
||||
url(r'^admin/shell/', include('django_admin_shell.urls')),
|
||||
url(r'^admin/', admin.site.urls, name='inventree-admin'),
|
||||
|
||||
url(r'^api/', include(apipatterns)),
|
||||
url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
|
||||
|
||||
url(r'^markdownx/', include('markdownx.urls')),
|
||||
]
|
||||
|
||||
frontendpatterns = [
|
||||
url(r'^part/', include(part_urls)),
|
||||
url(r'^manufacturer-part/', include(manufacturer_part_urls)),
|
||||
url(r'^supplier-part/', include(supplier_part_urls)),
|
||||
|
||||
url(r'^common/', include(common_urls)),
|
||||
|
||||
url(r'^stock/', include(stock_urls)),
|
||||
@ -140,37 +154,30 @@ urlpatterns = [
|
||||
|
||||
url(r'^build/', include(build_urls)),
|
||||
|
||||
url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
|
||||
url(r'^settings/', include(settings_urls)),
|
||||
|
||||
url(r'^edit-user/', EditUserView.as_view(), name='edit-user'),
|
||||
url(r'^set-password/', SetPasswordView.as_view(), name='set-password'),
|
||||
|
||||
url(r'^admin/error_log/', include('error_report.urls')),
|
||||
url(r'^admin/shell/', include('django_admin_shell.urls')),
|
||||
url(r'^admin/', admin.site.urls, name='inventree-admin'),
|
||||
|
||||
url(r'^index/', IndexView.as_view(), name='index'),
|
||||
url(r'^search/', SearchView.as_view(), name='search'),
|
||||
url(r'^stats/', DatabaseStatsView.as_view(), name='stats'),
|
||||
|
||||
url(r'^auth/?', auth_request),
|
||||
|
||||
url(r'^api/', include(apipatterns)),
|
||||
url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
|
||||
|
||||
url(r'^markdownx/', include('markdownx.urls')),
|
||||
|
||||
# Single Sign On / allauth
|
||||
# overrides of urlpatterns
|
||||
url(r'^accounts/email/', CustomEmailView.as_view(), name='account_email'),
|
||||
url(r'^accounts/social/connections/', CustomConnectionsView.as_view(), name='socialaccount_connections'),
|
||||
url(r"^accounts/password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$", CustomPasswordResetFromKeyView.as_view(), name="account_reset_password_from_key"),
|
||||
url(r"^accounts/two-factor-authenticate/?$", CustomTwoFactorAuthenticate.as_view(), name="two-factor-authenticate"),
|
||||
url(r'^accounts/', include('allauth_2fa.urls')), # MFA support
|
||||
url(r'^accounts/', include('allauth.urls')), # included urlpatterns
|
||||
]
|
||||
|
||||
urlpatterns = [
|
||||
url('', include(frontendpatterns)),
|
||||
url('', include(backendpatterns)),
|
||||
]
|
||||
|
||||
# Server running in "DEBUG" mode?
|
||||
if settings.DEBUG:
|
||||
# Static file access
|
||||
|
@ -29,6 +29,7 @@ from allauth.socialaccount.forms import DisconnectForm
|
||||
from allauth.account.models import EmailAddress
|
||||
from allauth.account.views import EmailView, PasswordResetFromKeyView
|
||||
from allauth.socialaccount.views import ConnectionsView
|
||||
from allauth_2fa.views import TwoFactorAuthenticate
|
||||
|
||||
from common.settings import currency_code_default, currency_codes
|
||||
|
||||
@ -857,6 +858,14 @@ class CustomPasswordResetFromKeyView(PasswordResetFromKeyView):
|
||||
success_url = reverse_lazy("account_login")
|
||||
|
||||
|
||||
class CustomTwoFactorAuthenticate(TwoFactorAuthenticate):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if 'allauth_2fa_user_id' not in request.session and 'otp_token' not in request.POST:
|
||||
return redirect('account_login')
|
||||
if hasattr(request.user, 'id'):
|
||||
request.session['allauth_2fa_user_id'] = request.user.id
|
||||
return super(FormView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
class CurrencyRefreshView(RedirectView):
|
||||
"""
|
||||
POST endpoint to refresh / update exchange rates
|
||||
|
Loading…
Reference in New Issue
Block a user