We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug - Redirect loop
There seems to be a bug of redirection loop when a user (created without any admin/editor roles) attempts to log in. I was trying out the demo and apparently the admin interface does not cater for users without any roles.

It would be nice to know if there is a workaround this issue. Thanks!


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `wagtail/wagtailadmin/views/account.py`
Content:
```
1 from django.conf import settings
2 from django.shortcuts import render, redirect
3 from django.contrib import messages
4 from django.contrib.auth.forms import SetPasswordForm
5 from django.contrib.auth.decorators import permission_required
6 from django.contrib.auth.views import logout as auth_logout, login as auth_login
7 from django.utils.translation import ugettext as _ 
8 from django.views.decorators.debug import sensitive_post_parameters
9 from django.views.decorators.cache import never_cache
10 
11 from wagtail.wagtailadmin import forms
12 from wagtail.wagtailusers.forms import NotificationPreferencesForm
13 from wagtail.wagtailusers.models import UserProfile
14 from wagtail.wagtailcore.models import UserPagePermissionsProxy
15 
16 
17 @permission_required('wagtailadmin.access_admin')
18 def account(request):
19     user_perms = UserPagePermissionsProxy(request.user)
20     show_notification_preferences = user_perms.can_edit_pages() or user_perms.can_publish_pages()
21 
22     return render(request, 'wagtailadmin/account/account.html', {
23         'show_change_password': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True) and request.user.has_usable_password(),
24         'show_notification_preferences': show_notification_preferences
25     })
26 
27 
28 @permission_required('wagtailadmin.access_admin')
29 def change_password(request):
30     can_change_password = request.user.has_usable_password()
31 
32     if can_change_password:
33         if request.POST:
34             form = SetPasswordForm(request.user, request.POST)
35 
36             if form.is_valid():
37                 form.save()
38 
39                 messages.success(request, _("Your password has been changed successfully!"))
40                 return redirect('wagtailadmin_account')
41         else:
42             form = SetPasswordForm(request.user)
43     else:
44         form = None
45 
46     return render(request, 'wagtailadmin/account/change_password.html', {
47         'form': form,
48         'can_change_password': can_change_password,
49     })
50 
51 
52 @permission_required('wagtailadmin.access_admin')
53 def notification_preferences(request):
54 
55     if request.POST:
56         form = NotificationPreferencesForm(request.POST, instance=UserProfile.get_for_user(request.user))
57 
58         if form.is_valid():
59             form.save()
60             messages.success(request, _("Your preferences have been updated successfully!"))
61             return redirect('wagtailadmin_account')
62     else:
63         form = NotificationPreferencesForm(instance=UserProfile.get_for_user(request.user))
64 
65     # quick-and-dirty catch-all in case the form has been rendered with no
66     # fields, as the user has no customisable permissions
67     if not form.fields:
68         return redirect('wagtailadmin_account')
69 
70     return render(request, 'wagtailadmin/account/notification_preferences.html', {
71         'form': form,
72     })
73 
74 
75 @sensitive_post_parameters()
76 @never_cache
77 def login(request):
78     if request.user.is_authenticated():
79         return redirect('wagtailadmin_home')
80     else:
81         return auth_login(request,
82             template_name='wagtailadmin/login.html',
83             authentication_form=forms.LoginForm,
84             extra_context={
85                 'show_password_reset': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True),
86             },
87         )
88 
89 
90 def logout(request):
91     response = auth_logout(request, next_page = 'wagtailadmin_login')
92 
93     # By default, logging out will generate a fresh sessionid cookie. We want to use the
94     # absence of sessionid as an indication that front-end pages are being viewed by a
95     # non-logged-in user and are therefore cacheable, so we forcibly delete the cookie here.
96     response.delete_cookie(settings.SESSION_COOKIE_NAME,
97         domain=settings.SESSION_COOKIE_DOMAIN,
98         path=settings.SESSION_COOKIE_PATH)
99 
100     # HACK: pretend that the session hasn't been modified, so that SessionMiddleware
101     # won't override the above and write a new cookie.
102     request.session.modified = False
103 
104     return response
105
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/wagtail/wagtailadmin/views/account.py b/wagtail/wagtailadmin/views/account.py
--- a/wagtail/wagtailadmin/views/account.py
+++ b/wagtail/wagtailadmin/views/account.py
@@ -75,7 +75,7 @@
 @sensitive_post_parameters()
 @never_cache
 def login(request):
-    if request.user.is_authenticated():
+    if request.user.is_authenticated() and request.user.has_perm('wagtailadmin.access_admin'):
         return redirect('wagtailadmin_home')
     else:
         return auth_login(request,

{"golden_diff": "diff --git a/wagtail/wagtailadmin/views/account.py b/wagtail/wagtailadmin/views/account.py\n--- a/wagtail/wagtailadmin/views/account.py\n+++ b/wagtail/wagtailadmin/views/account.py\n@@ -75,7 +75,7 @@\n @sensitive_post_parameters()\n @never_cache\n def login(request):\n-    if request.user.is_authenticated():\n+    if request.user.is_authenticated() and request.user.has_perm('wagtailadmin.access_admin'):\n         return redirect('wagtailadmin_home')\n     else:\n         return auth_login(request,\n", "issue": "Bug - Redirect loop\nThere seems to be a bug of redirection loop when a user (created without any admin/editor roles) attempts to log in. I was trying out the demo and apparently the admin interface does not cater for users without any roles.\n\nIt would be nice to know if there is a workaround this issue. Thanks!\n\n", "before_files": [{"content": "from django.conf import settings\nfrom django.shortcuts import render, redirect\nfrom django.contrib import messages\nfrom django.contrib.auth.forms import SetPasswordForm\nfrom django.contrib.auth.decorators import permission_required\nfrom django.contrib.auth.views import logout as auth_logout, login as auth_login\nfrom django.utils.translation import ugettext as _ \nfrom django.views.decorators.debug import sensitive_post_parameters\nfrom django.views.decorators.cache import never_cache\n\nfrom wagtail.wagtailadmin import forms\nfrom wagtail.wagtailusers.forms import NotificationPreferencesForm\nfrom wagtail.wagtailusers.models import UserProfile\nfrom wagtail.wagtailcore.models import UserPagePermissionsProxy\n\n\n@permission_required('wagtailadmin.access_admin')\ndef account(request):\n    user_perms = UserPagePermissionsProxy(request.user)\n    show_notification_preferences = user_perms.can_edit_pages() or user_perms.can_publish_pages()\n\n    return render(request, 'wagtailadmin/account/account.html', {\n        'show_change_password': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True) and request.user.has_usable_password(),\n        'show_notification_preferences': show_notification_preferences\n    })\n\n\n@permission_required('wagtailadmin.access_admin')\ndef change_password(request):\n    can_change_password = request.user.has_usable_password()\n\n    if can_change_password:\n        if request.POST:\n            form = SetPasswordForm(request.user, request.POST)\n\n            if form.is_valid():\n                form.save()\n\n                messages.success(request, _(\"Your password has been changed successfully!\"))\n                return redirect('wagtailadmin_account')\n        else:\n            form = SetPasswordForm(request.user)\n    else:\n        form = None\n\n    return render(request, 'wagtailadmin/account/change_password.html', {\n        'form': form,\n        'can_change_password': can_change_password,\n    })\n\n\n@permission_required('wagtailadmin.access_admin')\ndef notification_preferences(request):\n\n    if request.POST:\n        form = NotificationPreferencesForm(request.POST, instance=UserProfile.get_for_user(request.user))\n\n        if form.is_valid():\n            form.save()\n            messages.success(request, _(\"Your preferences have been updated successfully!\"))\n            return redirect('wagtailadmin_account')\n    else:\n        form = NotificationPreferencesForm(instance=UserProfile.get_for_user(request.user))\n\n    # quick-and-dirty catch-all in case the form has been rendered with no\n    # fields, as the user has no customisable permissions\n    if not form.fields:\n        return redirect('wagtailadmin_account')\n\n    return render(request, 'wagtailadmin/account/notification_preferences.html', {\n        'form': form,\n    })\n\n\n@sensitive_post_parameters()\n@never_cache\ndef login(request):\n    if request.user.is_authenticated():\n        return redirect('wagtailadmin_home')\n    else:\n        return auth_login(request,\n            template_name='wagtailadmin/login.html',\n            authentication_form=forms.LoginForm,\n            extra_context={\n                'show_password_reset': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True),\n            },\n        )\n\n\ndef logout(request):\n    response = auth_logout(request, next_page = 'wagtailadmin_login')\n\n    # By default, logging out will generate a fresh sessionid cookie. We want to use the\n    # absence of sessionid as an indication that front-end pages are being viewed by a\n    # non-logged-in user and are therefore cacheable, so we forcibly delete the cookie here.\n    response.delete_cookie(settings.SESSION_COOKIE_NAME,\n        domain=settings.SESSION_COOKIE_DOMAIN,\n        path=settings.SESSION_COOKIE_PATH)\n\n    # HACK: pretend that the session hasn't been modified, so that SessionMiddleware\n    # won't override the above and write a new cookie.\n    request.session.modified = False\n\n    return response\n", "path": "wagtail/wagtailadmin/views/account.py"}], "after_files": [{"content": "from django.conf import settings\nfrom django.shortcuts import render, redirect\nfrom django.contrib import messages\nfrom django.contrib.auth.forms import SetPasswordForm\nfrom django.contrib.auth.decorators import permission_required\nfrom django.contrib.auth.views import logout as auth_logout, login as auth_login\nfrom django.utils.translation import ugettext as _ \nfrom django.views.decorators.debug import sensitive_post_parameters\nfrom django.views.decorators.cache import never_cache\n\nfrom wagtail.wagtailadmin import forms\nfrom wagtail.wagtailusers.forms import NotificationPreferencesForm\nfrom wagtail.wagtailusers.models import UserProfile\nfrom wagtail.wagtailcore.models import UserPagePermissionsProxy\n\n\n@permission_required('wagtailadmin.access_admin')\ndef account(request):\n    user_perms = UserPagePermissionsProxy(request.user)\n    show_notification_preferences = user_perms.can_edit_pages() or user_perms.can_publish_pages()\n\n    return render(request, 'wagtailadmin/account/account.html', {\n        'show_change_password': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True) and request.user.has_usable_password(),\n        'show_notification_preferences': show_notification_preferences\n    })\n\n\n@permission_required('wagtailadmin.access_admin')\ndef change_password(request):\n    can_change_password = request.user.has_usable_password()\n\n    if can_change_password:\n        if request.POST:\n            form = SetPasswordForm(request.user, request.POST)\n\n            if form.is_valid():\n                form.save()\n\n                messages.success(request, _(\"Your password has been changed successfully!\"))\n                return redirect('wagtailadmin_account')\n        else:\n            form = SetPasswordForm(request.user)\n    else:\n        form = None\n\n    return render(request, 'wagtailadmin/account/change_password.html', {\n        'form': form,\n        'can_change_password': can_change_password,\n    })\n\n\n@permission_required('wagtailadmin.access_admin')\ndef notification_preferences(request):\n\n    if request.POST:\n        form = NotificationPreferencesForm(request.POST, instance=UserProfile.get_for_user(request.user))\n\n        if form.is_valid():\n            form.save()\n            messages.success(request, _(\"Your preferences have been updated successfully!\"))\n            return redirect('wagtailadmin_account')\n    else:\n        form = NotificationPreferencesForm(instance=UserProfile.get_for_user(request.user))\n\n    # quick-and-dirty catch-all in case the form has been rendered with no\n    # fields, as the user has no customisable permissions\n    if not form.fields:\n        return redirect('wagtailadmin_account')\n\n    return render(request, 'wagtailadmin/account/notification_preferences.html', {\n        'form': form,\n    })\n\n\n@sensitive_post_parameters()\n@never_cache\ndef login(request):\n    if request.user.is_authenticated() and request.user.has_perm('wagtailadmin.access_admin'):\n        return redirect('wagtailadmin_home')\n    else:\n        return auth_login(request,\n            template_name='wagtailadmin/login.html',\n            authentication_form=forms.LoginForm,\n            extra_context={\n                'show_password_reset': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True),\n            },\n        )\n\n\ndef logout(request):\n    response = auth_logout(request, next_page = 'wagtailadmin_login')\n\n    # By default, logging out will generate a fresh sessionid cookie. We want to use the\n    # absence of sessionid as an indication that front-end pages are being viewed by a\n    # non-logged-in user and are therefore cacheable, so we forcibly delete the cookie here.\n    response.delete_cookie(settings.SESSION_COOKIE_NAME,\n        domain=settings.SESSION_COOKIE_DOMAIN,\n        path=settings.SESSION_COOKIE_PATH)\n\n    # HACK: pretend that the session hasn't been modified, so that SessionMiddleware\n    # won't override the above and write a new cookie.\n    request.session.modified = False\n\n    return response\n", "path": "wagtail/wagtailadmin/views/account.py"}]}