From 3c984b9871157b3a75d345a1d299aa209a0a3b0a Mon Sep 17 00:00:00 2001
From: Matt Westcott <matt@west.co.tt>
Date: Thu, 5 Nov 2020 18:07:29 +0000
Subject: [PATCH] Avoid circular import between wagtail.admin.auth and custom
 user models (#6522)

Fixes #6518

If the models.py containing a custom user model directly or indirectly imports wagtail.admin.auth, this causes a circular dependency because wagtail.admin.auth attempts to import django.contrib.auth.views, which in turn depends on the custom user model. Fix this by moving the django.contrib.auth.views import inside reject_request.
---
 CHANGELOG.txt                      | 1 +
 docs/releases/2.11.1.rst           | 1 +
 wagtail/admin/auth.py              | 4 +++-
 wagtail/tests/customuser/models.py | 4 ++++
 4 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index c95e4ec104..2971c0b10e 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -11,6 +11,7 @@ Changelog
 ~~~~~~~~~~~~~~~~~~~
 
  * Fix: Ensure that cached `wagtail_site_root_paths` structures from older Wagtail versions are invalidated (Sævar Öfjörð Magnússon)
+ * Fix: Avoid circular import between wagtail.admin.auth and custom user models (Matt Westcott)
 
 
 2.11 LTS (02.11.2020)
diff --git a/docs/releases/2.11.1.rst b/docs/releases/2.11.1.rst
index 5f031e50e4..3276d75ade 100644
--- a/docs/releases/2.11.1.rst
+++ b/docs/releases/2.11.1.rst
@@ -14,3 +14,4 @@ Bug fixes
 ~~~~~~~~~
 
  * Ensure that cached ``wagtail_site_root_paths`` structures from older Wagtail versions are invalidated (Sævar Öfjörð Magnússon)
+ * Avoid circular import between wagtail.admin.auth and custom user models (Matt Westcott)
diff --git a/wagtail/admin/auth.py b/wagtail/admin/auth.py
index 0a3fe9df3c..ba4837b3ce 100644
--- a/wagtail/admin/auth.py
+++ b/wagtail/admin/auth.py
@@ -5,7 +5,6 @@ from functools import wraps
 import l18n
 
 from django.contrib.auth import get_user_model
-from django.contrib.auth.views import redirect_to_login as auth_redirect_to_login
 from django.core.exceptions import PermissionDenied
 from django.db.models import Q
 from django.shortcuts import redirect
@@ -145,6 +144,9 @@ def reject_request(request):
     if request.is_ajax():
         raise PermissionDenied
 
+    # import redirect_to_login here to avoid circular imports on model files that import
+    # wagtail.admin.auth, specifically where custom user models are involved
+    from django.contrib.auth.views import redirect_to_login as auth_redirect_to_login
     return auth_redirect_to_login(
         request.get_full_path(), login_url=reverse('wagtailadmin_login'))
 
diff --git a/wagtail/tests/customuser/models.py b/wagtail/tests/customuser/models.py
index 78869d30ac..c7a29ff392 100644
--- a/wagtail/tests/customuser/models.py
+++ b/wagtail/tests/customuser/models.py
@@ -1,6 +1,10 @@
 from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
 from django.db import models
 
+# make sure we can import wagtail.admin.auth here without triggering a circular import
+# (which is easily done because it's dealing with django.contrib.auth views which depend
+# on the user model)
+from wagtail.admin.auth import permission_denied  # noqa
 from wagtail.admin.edit_handlers import FieldPanel
 
 from .fields import ConvertedValueField