diff --git a/akarpov/templates/users/disable_2fa.html b/akarpov/templates/users/disable_2fa.html index 604678e..0a2de20 100644 --- a/akarpov/templates/users/disable_2fa.html +++ b/akarpov/templates/users/disable_2fa.html @@ -14,7 +14,7 @@
diff --git a/akarpov/users/middleware.py b/akarpov/users/middleware.py index 0b3258e..ae02bdd 100644 --- a/akarpov/users/middleware.py +++ b/akarpov/users/middleware.py @@ -1,6 +1,8 @@ +from cacheops import cached_as from django.shortcuts import redirect from django.urls import resolve from django.utils.deprecation import MiddlewareMixin +from django_otp.plugins.otp_totp.models import TOTPDevice from rest_framework.exceptions import AuthenticationFailed @@ -24,8 +26,20 @@ def __call__(self, request): otp_not_verified = not request.session.get("otp_verified", False) on_2fa_page = resolve(request.path_info).url_name == "enforce_otp_login" - # Enforce OTP token input, if user is authenticated but has not verified OTP, and is NOT on the 2FA page - if is_authenticated and otp_not_verified and not on_2fa_page: + # Caches the checker for has_otp_device + @cached_as( + TOTPDevice, timeout=15 * 60 + ) # consider appropriate time for your use case + def has_otp_device(user): + return TOTPDevice.objects.devices_for_user(user, confirmed=True).exists() + + # Enforce OTP token input, if user is authenticated, has OTP enabled but has not verified OTP + if ( + is_authenticated + and has_otp_device(request.user) + and otp_not_verified + and not on_2fa_page + ): request.session["next"] = request.get_full_path() return redirect("users:enforce_otp_login") diff --git a/config/settings/base.py b/config/settings/base.py index 7963a98..247b741 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -77,6 +77,7 @@ "files.*": {"ops": ("fetch", "get", "list"), "timeout": 60}, "auth.permission": {"ops": "all", "timeout": 60 * 15}, "music.*": {"ops": ("fetch", "get", "list"), "timeout": 60 * 15}, + "otp_totp.totpdevice": {"ops": "all", "timeout": 15 * 60}, } CACHEOPS_REDIS = env.str("REDIS_URL")