from django.conf import settings from django.contrib.auth import REDIRECT_FIELD_NAME from django.contrib.auth.views import redirect_to_login from django.http import HttpResponseRedirect from django.shortcuts import resolve_url from django.urls import reverse from django.utils.http import url_has_allowed_host_and_scheme # renamed Dj^3.* from two_factor.admin import AdminSiteOTPRequired, AdminSiteOTPRequiredMixin # https://stackoverflow.com/questions/48600737/django-two-factor-auth-cant-access-admin-site class AdminSiteOTPRequiredMixinRedirectSetup(AdminSiteOTPRequired): """ Fixes the current implementation of django-two-factor-auth = 1.15.3 when admin page is patched for 2fa (circular redirect - super user created with manage.py and cannot log in because he does not have a device configured). The class redirects to the setup page. After that, you can log in as usual. """ def login(self, request, extra_context=None): redirect_to = request.POST.get( REDIRECT_FIELD_NAME, request.GET.get(REDIRECT_FIELD_NAME) ) # For users not yet verified the AdminSiteOTPRequired.has_permission # will fail. So use the standard admin has_permission check: # (is_active and is_staff) and then check for verification. # Go to index if they pass, otherwise make them setup OTP device. if request.method == "GET" and super( AdminSiteOTPRequiredMixin, self ).has_permission(request): # Already logged-in and verified by OTP if request.user.is_verified(): # User has permission index_path = reverse("admin:index", current_app=self.name) else: # User has permission but no OTP set: index_path = reverse("two_factor:setup", current_app=self.name) return HttpResponseRedirect(index_path) if not redirect_to or not url_has_allowed_host_and_scheme( url=redirect_to, allowed_hosts=[request.get_host()] ): redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL) return redirect_to_login(redirect_to)