We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Login screen should redirect somewhere appropriate if visited while already logged in
Rather confusing, visiting the login screen while already logged in presents the user with a login form again. It should redirect them to the dashboard, I'd suggest.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `runtests.py`
Content:
```
1 #!/usr/bin/env python
2 import sys
3 import os
4 import shutil
5 
6 from django.conf import settings, global_settings
7 from django.core.management import execute_from_command_line
8 
9 WAGTAIL_ROOT = os.path.dirname(__file__)
10 STATIC_ROOT = os.path.join(WAGTAIL_ROOT, 'test-static')
11 MEDIA_ROOT = os.path.join(WAGTAIL_ROOT, 'test-media')
12 
13 if not settings.configured:
14 
15     try:
16         import elasticutils
17         has_elasticsearch = True
18     except ImportError:
19         has_elasticsearch = False
20 
21     WAGTAILSEARCH_BACKENDS = {
22         'default': {
23             'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch',
24         }
25     }
26     if has_elasticsearch:
27         WAGTAILSEARCH_BACKENDS['elasticsearch'] = {
28             'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',
29             'TIMEOUT': 10,
30             'max_retries': 1,
31         }
32 
33     settings.configure(
34         DATABASES={
35             'default': {
36                 'ENGINE': os.environ.get('DATABASE_ENGINE', 'django.db.backends.postgresql_psycopg2'),
37                 'NAME': 'wagtaildemo',
38                 'USER': os.environ.get('DATABASE_USER', 'postgres'),
39             }
40         },
41         ROOT_URLCONF='wagtail.tests.urls',
42         STATIC_URL='/static/',
43         STATIC_ROOT=STATIC_ROOT,
44         MEDIA_ROOT=MEDIA_ROOT,
45         USE_TZ=True,
46         STATICFILES_FINDERS=(
47             'django.contrib.staticfiles.finders.AppDirectoriesFinder',
48             'compressor.finders.CompressorFinder',
49         ),
50         TEMPLATE_CONTEXT_PROCESSORS=global_settings.TEMPLATE_CONTEXT_PROCESSORS + (
51             'django.core.context_processors.request',
52         ),
53         MIDDLEWARE_CLASSES=(
54             'django.middleware.common.CommonMiddleware',
55             'django.contrib.sessions.middleware.SessionMiddleware',
56             'django.middleware.csrf.CsrfViewMiddleware',
57             'django.contrib.auth.middleware.AuthenticationMiddleware',
58             'django.contrib.messages.middleware.MessageMiddleware',
59             'django.middleware.clickjacking.XFrameOptionsMiddleware',
60 
61             'wagtail.wagtailcore.middleware.SiteMiddleware',
62 
63             'wagtail.wagtailredirects.middleware.RedirectMiddleware',
64         ),
65         INSTALLED_APPS=[
66             'django.contrib.contenttypes',
67             'django.contrib.sessions',
68             'django.contrib.auth',
69             'django.contrib.messages',
70             'django.contrib.staticfiles',
71             'django.contrib.admin',
72 
73             'taggit',
74             'south',
75             'compressor',
76 
77             'wagtail.wagtailcore',
78             'wagtail.wagtailadmin',
79             'wagtail.wagtaildocs',
80             'wagtail.wagtailsnippets',
81             'wagtail.wagtailusers',
82             'wagtail.wagtailimages',
83             'wagtail.wagtailembeds',
84             'wagtail.wagtailsearch',
85             'wagtail.wagtailredirects',
86             'wagtail.wagtailforms',
87             'wagtail.tests',
88         ],
89 
90         # Using DatabaseCache to make sure that the cache is cleared between tests.
91         # This prevents false-positives in some wagtail core tests where we are
92         # changing the 'wagtail_root_paths' key which may cause future tests to fail.
93         CACHES = {
94             'default': {
95                 'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
96                 'LOCATION': 'cache',
97             }
98         },
99         PASSWORD_HASHERS=(
100             'django.contrib.auth.hashers.MD5PasswordHasher',  # don't use the intentionally slow default password hasher
101         ),
102         COMPRESS_ENABLED=False,  # disable compression so that we can run tests on the content of the compress tag
103         WAGTAILSEARCH_BACKENDS=WAGTAILSEARCH_BACKENDS,
104         WAGTAIL_SITE_NAME='Test Site',
105         LOGIN_REDIRECT_URL='wagtailadmin_home',
106     )
107 
108 
109 def runtests():
110     argv = sys.argv[:1] + ['test'] + sys.argv[1:]
111     try:
112         execute_from_command_line(argv)
113     finally:
114         shutil.rmtree(STATIC_ROOT, ignore_errors=True)
115         shutil.rmtree(MEDIA_ROOT, ignore_errors=True)
116 
117 
118 if __name__ == '__main__':
119     runtests()
120
```

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
7 from django.utils.translation import ugettext as _ 
8 
9 @permission_required('wagtailadmin.access_admin')
10 def account(request):
11     return render(request, 'wagtailadmin/account/account.html', {
12         'show_change_password': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True) and request.user.has_usable_password(),
13     })
14 
15 
16 @permission_required('wagtailadmin.access_admin')
17 def change_password(request):
18     can_change_password = request.user.has_usable_password()
19 
20     if can_change_password:
21         if request.POST:
22             form = SetPasswordForm(request.user, request.POST)
23 
24             if form.is_valid():
25                 form.save()
26 
27                 messages.success(request, _("Your password has been changed successfully!"))
28                 return redirect('wagtailadmin_account')
29         else:
30             form = SetPasswordForm(request.user)
31     else:
32         form = None
33 
34     return render(request, 'wagtailadmin/account/change_password.html', {
35         'form': form,
36         'can_change_password': can_change_password,
37     })
38 
39 
40 def logout(request):
41     response = auth_logout(request, next_page = 'wagtailadmin_login')
42 
43     # By default, logging out will generate a fresh sessionid cookie. We want to use the
44     # absence of sessionid as an indication that front-end pages are being viewed by a
45     # non-logged-in user and are therefore cacheable, so we forcibly delete the cookie here.
46     response.delete_cookie(settings.SESSION_COOKIE_NAME,
47         domain=settings.SESSION_COOKIE_DOMAIN,
48         path=settings.SESSION_COOKIE_PATH)
49 
50     # HACK: pretend that the session hasn't been modified, so that SessionMiddleware
51     # won't override the above and write a new cookie.
52     request.session.modified = False
53 
54     return response
55
```

Path: `wagtail/wagtailadmin/urls.py`
Content:
```
1 from django.conf.urls import url
2 from django.conf import settings
3 
4 from wagtail.wagtailadmin.forms import LoginForm, PasswordResetForm
5 from wagtail.wagtailadmin.views import account, chooser, home, pages, tags, userbar
6 from wagtail.wagtailadmin import hooks
7 
8 urlpatterns = [
9     url(
10         r'^login/$', 'django.contrib.auth.views.login', {
11             'template_name': 'wagtailadmin/login.html',
12             'authentication_form': LoginForm,
13             'extra_context': {'show_password_reset': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True)},
14         }, name='wagtailadmin_login'
15     ),
16 
17     # Password reset
18     url(
19         r'^password_reset/$', 'django.contrib.auth.views.password_reset', {
20             'template_name': 'wagtailadmin/account/password_reset/form.html',
21             'email_template_name': 'wagtailadmin/account/password_reset/email.txt',
22             'subject_template_name': 'wagtailadmin/account/password_reset/email_subject.txt',
23             'password_reset_form': PasswordResetForm,
24         }, name='password_reset'
25     ),
26     url(
27         r'^password_reset/done/$', 'django.contrib.auth.views.password_reset_done', {
28             'template_name': 'wagtailadmin/account/password_reset/done.html'
29         }, name='password_reset_done'
30     ),
31     url(
32         r'^password_reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
33         'django.contrib.auth.views.password_reset_confirm',
34         {'template_name': 'wagtailadmin/account/password_reset/confirm.html'},
35         name='password_reset_confirm',
36     ),
37     url(
38         r'^password_reset/complete/$', 'django.contrib.auth.views.password_reset_complete',
39         {'template_name': 'wagtailadmin/account/password_reset/complete.html'},
40         name='password_reset_complete'
41     ),
42 ]
43 
44 urlpatterns += [
45     url(r'^$', home.home, name='wagtailadmin_home'),
46 
47     url(r'^failwhale/$', home.error_test, name='wagtailadmin_error_test'),
48 
49     url(r'^pages/$', pages.index, name='wagtailadmin_explore_root'),
50     url(r'^pages/(\d+)/$', pages.index, name='wagtailadmin_explore'),
51 
52     url(r'^pages/new/(\w+)/(\w+)/(\d+)/$', pages.create, name='wagtailadmin_pages_create'),
53     url(r'^pages/new/(\w+)/(\w+)/(\d+)/preview/$', pages.preview_on_create, name='wagtailadmin_pages_preview_on_create'),
54     url(r'^pages/usage/(\w+)/(\w+)/$', pages.content_type_use, name='wagtailadmin_pages_type_use'),
55 
56     url(r'^pages/(\d+)/edit/$', pages.edit, name='wagtailadmin_pages_edit'),
57     url(r'^pages/(\d+)/edit/preview/$', pages.preview_on_edit, name='wagtailadmin_pages_preview_on_edit'),
58 
59     url(r'^pages/preview_placeholder/$', pages.preview_placeholder, name='wagtailadmin_pages_preview_placeholder'),
60 
61     url(r'^pages/(\d+)/view_draft/$', pages.view_draft, name='wagtailadmin_pages_view_draft'),
62     url(r'^pages/(\d+)/add_subpage/$', pages.add_subpage, name='wagtailadmin_pages_add_subpage'),
63     url(r'^pages/(\d+)/delete/$', pages.delete, name='wagtailadmin_pages_delete'),
64     url(r'^pages/(\d+)/unpublish/$', pages.unpublish, name='wagtailadmin_pages_unpublish'),
65 
66     url(r'^pages/search/$', pages.search, name='wagtailadmin_pages_search'),
67 
68     url(r'^pages/(\d+)/move/$', pages.move_choose_destination, name='wagtailadmin_pages_move'),
69     url(r'^pages/(\d+)/move/(\d+)/$', pages.move_choose_destination, name='wagtailadmin_pages_move_choose_destination'),
70     url(r'^pages/(\d+)/move/(\d+)/confirm/$', pages.move_confirm, name='wagtailadmin_pages_move_confirm'),
71     url(r'^pages/(\d+)/set_position/$', pages.set_page_position, name='wagtailadmin_pages_set_page_position'),
72 
73     url(r'^pages/moderation/(\d+)/approve/$', pages.approve_moderation, name='wagtailadmin_pages_approve_moderation'),
74     url(r'^pages/moderation/(\d+)/reject/$', pages.reject_moderation, name='wagtailadmin_pages_reject_moderation'),
75     url(r'^pages/moderation/(\d+)/preview/$', pages.preview_for_moderation, name='wagtailadmin_pages_preview_for_moderation'),
76 
77     url(r'^choose-page/$', chooser.browse, name='wagtailadmin_choose_page'),
78     url(r'^choose-page/(\d+)/$', chooser.browse, name='wagtailadmin_choose_page_child'),
79     url(r'^choose-external-link/$', chooser.external_link, name='wagtailadmin_choose_page_external_link'),
80     url(r'^choose-email-link/$', chooser.email_link, name='wagtailadmin_choose_page_email_link'),
81 
82     url(r'^tag-autocomplete/$', tags.autocomplete, name='wagtailadmin_tag_autocomplete'),
83 
84     url(r'^account/$', account.account, name='wagtailadmin_account'),
85     url(r'^account/change_password/$', account.change_password, name='wagtailadmin_account_change_password'),
86     url(r'^logout/$', account.logout, name='wagtailadmin_logout'),
87 
88     url(r'^userbar/(\d+)/$', userbar.for_frontend, name='wagtailadmin_userbar_frontend'),
89     url(r'^userbar/moderation/(\d+)/$', userbar.for_moderation, name='wagtailadmin_userbar_moderation'),
90 ]
91 
92 
93 # Import additional urlpatterns from any apps that define a register_admin_urls hook
94 for fn in hooks.get_hooks('register_admin_urls'):
95     urls = fn()
96     if urls:
97         urlpatterns += urls
98
```
--- 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/runtests.py b/runtests.py
--- a/runtests.py
+++ b/runtests.py
@@ -103,6 +103,7 @@
         WAGTAILSEARCH_BACKENDS=WAGTAILSEARCH_BACKENDS,
         WAGTAIL_SITE_NAME='Test Site',
         LOGIN_REDIRECT_URL='wagtailadmin_home',
+        LOGIN_URL='wagtailadmin_login',
     )
 
 
diff --git a/wagtail/wagtailadmin/urls.py b/wagtail/wagtailadmin/urls.py
--- a/wagtail/wagtailadmin/urls.py
+++ b/wagtail/wagtailadmin/urls.py
@@ -5,15 +5,8 @@
 from wagtail.wagtailadmin.views import account, chooser, home, pages, tags, userbar
 from wagtail.wagtailadmin import hooks
 
-urlpatterns = [
-    url(
-        r'^login/$', 'django.contrib.auth.views.login', {
-            'template_name': 'wagtailadmin/login.html',
-            'authentication_form': LoginForm,
-            'extra_context': {'show_password_reset': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True)},
-        }, name='wagtailadmin_login'
-    ),
 
+urlpatterns = [
     # Password reset
     url(
         r'^password_reset/$', 'django.contrib.auth.views.password_reset', {
@@ -81,6 +74,7 @@
 
     url(r'^tag-autocomplete/$', tags.autocomplete, name='wagtailadmin_tag_autocomplete'),
 
+    url(r'^login/$', account.login, name='wagtailadmin_login'),
     url(r'^account/$', account.account, name='wagtailadmin_account'),
     url(r'^account/change_password/$', account.change_password, name='wagtailadmin_account_change_password'),
     url(r'^logout/$', account.logout, name='wagtailadmin_logout'),
@@ -90,6 +84,13 @@
 ]
 
 
+# This is here to make sure that 'django.contrib.auth.views.login' is reversed correctly
+# It must be placed after 'wagtailadmin_login' to prevent this from being used
+urlpatterns += [
+    url(r'^login/$', 'django.contrib.auth.views.login'),
+]
+
+
 # Import additional urlpatterns from any apps that define a register_admin_urls hook
 for fn in hooks.get_hooks('register_admin_urls'):
     urls = fn()
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
@@ -3,8 +3,13 @@
 from django.contrib import messages
 from django.contrib.auth.forms import SetPasswordForm
 from django.contrib.auth.decorators import permission_required
-from django.contrib.auth.views import logout as auth_logout
+from django.contrib.auth.views import logout as auth_logout, login as auth_login
 from django.utils.translation import ugettext as _ 
+from django.views.decorators.debug import sensitive_post_parameters
+from django.views.decorators.cache import never_cache
+
+from wagtail.wagtailadmin import forms
+
 
 @permission_required('wagtailadmin.access_admin')
 def account(request):
@@ -37,6 +42,21 @@
     })
 
 
+@sensitive_post_parameters()
+@never_cache
+def login(request):
+    if request.user.is_authenticated():
+        return redirect('wagtailadmin_home')
+    else:
+        return auth_login(request,
+            template_name='wagtailadmin/login.html',
+            authentication_form=forms.LoginForm,
+            extra_context={
+                'show_password_reset': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True),
+            },
+        )
+
+
 def logout(request):
     response = auth_logout(request, next_page = 'wagtailadmin_login')

{"golden_diff": "diff --git a/runtests.py b/runtests.py\n--- a/runtests.py\n+++ b/runtests.py\n@@ -103,6 +103,7 @@\n         WAGTAILSEARCH_BACKENDS=WAGTAILSEARCH_BACKENDS,\n         WAGTAIL_SITE_NAME='Test Site',\n         LOGIN_REDIRECT_URL='wagtailadmin_home',\n+        LOGIN_URL='wagtailadmin_login',\n     )\n \n \ndiff --git a/wagtail/wagtailadmin/urls.py b/wagtail/wagtailadmin/urls.py\n--- a/wagtail/wagtailadmin/urls.py\n+++ b/wagtail/wagtailadmin/urls.py\n@@ -5,15 +5,8 @@\n from wagtail.wagtailadmin.views import account, chooser, home, pages, tags, userbar\n from wagtail.wagtailadmin import hooks\n \n-urlpatterns = [\n-    url(\n-        r'^login/$', 'django.contrib.auth.views.login', {\n-            'template_name': 'wagtailadmin/login.html',\n-            'authentication_form': LoginForm,\n-            'extra_context': {'show_password_reset': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True)},\n-        }, name='wagtailadmin_login'\n-    ),\n \n+urlpatterns = [\n     # Password reset\n     url(\n         r'^password_reset/$', 'django.contrib.auth.views.password_reset', {\n@@ -81,6 +74,7 @@\n \n     url(r'^tag-autocomplete/$', tags.autocomplete, name='wagtailadmin_tag_autocomplete'),\n \n+    url(r'^login/$', account.login, name='wagtailadmin_login'),\n     url(r'^account/$', account.account, name='wagtailadmin_account'),\n     url(r'^account/change_password/$', account.change_password, name='wagtailadmin_account_change_password'),\n     url(r'^logout/$', account.logout, name='wagtailadmin_logout'),\n@@ -90,6 +84,13 @@\n ]\n \n \n+# This is here to make sure that 'django.contrib.auth.views.login' is reversed correctly\n+# It must be placed after 'wagtailadmin_login' to prevent this from being used\n+urlpatterns += [\n+    url(r'^login/$', 'django.contrib.auth.views.login'),\n+]\n+\n+\n # Import additional urlpatterns from any apps that define a register_admin_urls hook\n for fn in hooks.get_hooks('register_admin_urls'):\n     urls = fn()\ndiff --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@@ -3,8 +3,13 @@\n from django.contrib import messages\n from django.contrib.auth.forms import SetPasswordForm\n from django.contrib.auth.decorators import permission_required\n-from django.contrib.auth.views import logout as auth_logout\n+from django.contrib.auth.views import logout as auth_logout, login as auth_login\n from django.utils.translation import ugettext as _ \n+from django.views.decorators.debug import sensitive_post_parameters\n+from django.views.decorators.cache import never_cache\n+\n+from wagtail.wagtailadmin import forms\n+\n \n @permission_required('wagtailadmin.access_admin')\n def account(request):\n@@ -37,6 +42,21 @@\n     })\n \n \n+@sensitive_post_parameters()\n+@never_cache\n+def 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+\n def logout(request):\n     response = auth_logout(request, next_page = 'wagtailadmin_login')\n", "issue": "Login screen should redirect somewhere appropriate if visited while already logged in\nRather confusing, visiting the login screen while already logged in presents the user with a login form again. It should redirect them to the dashboard, I'd suggest.\n\n", "before_files": [{"content": "#!/usr/bin/env python\nimport sys\nimport os\nimport shutil\n\nfrom django.conf import settings, global_settings\nfrom django.core.management import execute_from_command_line\n\nWAGTAIL_ROOT = os.path.dirname(__file__)\nSTATIC_ROOT = os.path.join(WAGTAIL_ROOT, 'test-static')\nMEDIA_ROOT = os.path.join(WAGTAIL_ROOT, 'test-media')\n\nif not settings.configured:\n\n    try:\n        import elasticutils\n        has_elasticsearch = True\n    except ImportError:\n        has_elasticsearch = False\n\n    WAGTAILSEARCH_BACKENDS = {\n        'default': {\n            'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch',\n        }\n    }\n    if has_elasticsearch:\n        WAGTAILSEARCH_BACKENDS['elasticsearch'] = {\n            'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',\n            'TIMEOUT': 10,\n            'max_retries': 1,\n        }\n\n    settings.configure(\n        DATABASES={\n            'default': {\n                'ENGINE': os.environ.get('DATABASE_ENGINE', 'django.db.backends.postgresql_psycopg2'),\n                'NAME': 'wagtaildemo',\n                'USER': os.environ.get('DATABASE_USER', 'postgres'),\n            }\n        },\n        ROOT_URLCONF='wagtail.tests.urls',\n        STATIC_URL='/static/',\n        STATIC_ROOT=STATIC_ROOT,\n        MEDIA_ROOT=MEDIA_ROOT,\n        USE_TZ=True,\n        STATICFILES_FINDERS=(\n            'django.contrib.staticfiles.finders.AppDirectoriesFinder',\n            'compressor.finders.CompressorFinder',\n        ),\n        TEMPLATE_CONTEXT_PROCESSORS=global_settings.TEMPLATE_CONTEXT_PROCESSORS + (\n            'django.core.context_processors.request',\n        ),\n        MIDDLEWARE_CLASSES=(\n            'django.middleware.common.CommonMiddleware',\n            'django.contrib.sessions.middleware.SessionMiddleware',\n            'django.middleware.csrf.CsrfViewMiddleware',\n            'django.contrib.auth.middleware.AuthenticationMiddleware',\n            'django.contrib.messages.middleware.MessageMiddleware',\n            'django.middleware.clickjacking.XFrameOptionsMiddleware',\n\n            'wagtail.wagtailcore.middleware.SiteMiddleware',\n\n            'wagtail.wagtailredirects.middleware.RedirectMiddleware',\n        ),\n        INSTALLED_APPS=[\n            'django.contrib.contenttypes',\n            'django.contrib.sessions',\n            'django.contrib.auth',\n            'django.contrib.messages',\n            'django.contrib.staticfiles',\n            'django.contrib.admin',\n\n            'taggit',\n            'south',\n            'compressor',\n\n            'wagtail.wagtailcore',\n            'wagtail.wagtailadmin',\n            'wagtail.wagtaildocs',\n            'wagtail.wagtailsnippets',\n            'wagtail.wagtailusers',\n            'wagtail.wagtailimages',\n            'wagtail.wagtailembeds',\n            'wagtail.wagtailsearch',\n            'wagtail.wagtailredirects',\n            'wagtail.wagtailforms',\n            'wagtail.tests',\n        ],\n\n        # Using DatabaseCache to make sure that the cache is cleared between tests.\n        # This prevents false-positives in some wagtail core tests where we are\n        # changing the 'wagtail_root_paths' key which may cause future tests to fail.\n        CACHES = {\n            'default': {\n                'BACKEND': 'django.core.cache.backends.db.DatabaseCache',\n                'LOCATION': 'cache',\n            }\n        },\n        PASSWORD_HASHERS=(\n            'django.contrib.auth.hashers.MD5PasswordHasher',  # don't use the intentionally slow default password hasher\n        ),\n        COMPRESS_ENABLED=False,  # disable compression so that we can run tests on the content of the compress tag\n        WAGTAILSEARCH_BACKENDS=WAGTAILSEARCH_BACKENDS,\n        WAGTAIL_SITE_NAME='Test Site',\n        LOGIN_REDIRECT_URL='wagtailadmin_home',\n    )\n\n\ndef runtests():\n    argv = sys.argv[:1] + ['test'] + sys.argv[1:]\n    try:\n        execute_from_command_line(argv)\n    finally:\n        shutil.rmtree(STATIC_ROOT, ignore_errors=True)\n        shutil.rmtree(MEDIA_ROOT, ignore_errors=True)\n\n\nif __name__ == '__main__':\n    runtests()\n", "path": "runtests.py"}, {"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\nfrom django.utils.translation import ugettext as _ \n\n@permission_required('wagtailadmin.access_admin')\ndef account(request):\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    })\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\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"}, {"content": "from django.conf.urls import url\nfrom django.conf import settings\n\nfrom wagtail.wagtailadmin.forms import LoginForm, PasswordResetForm\nfrom wagtail.wagtailadmin.views import account, chooser, home, pages, tags, userbar\nfrom wagtail.wagtailadmin import hooks\n\nurlpatterns = [\n    url(\n        r'^login/$', 'django.contrib.auth.views.login', {\n            'template_name': 'wagtailadmin/login.html',\n            'authentication_form': LoginForm,\n            'extra_context': {'show_password_reset': getattr(settings, 'WAGTAIL_PASSWORD_MANAGEMENT_ENABLED', True)},\n        }, name='wagtailadmin_login'\n    ),\n\n    # Password reset\n    url(\n        r'^password_reset/$', 'django.contrib.auth.views.password_reset', {\n            'template_name': 'wagtailadmin/account/password_reset/form.html',\n            'email_template_name': 'wagtailadmin/account/password_reset/email.txt',\n            'subject_template_name': 'wagtailadmin/account/password_reset/email_subject.txt',\n            'password_reset_form': PasswordResetForm,\n        }, name='password_reset'\n    ),\n    url(\n        r'^password_reset/done/$', 'django.contrib.auth.views.password_reset_done', {\n            'template_name': 'wagtailadmin/account/password_reset/done.html'\n        }, name='password_reset_done'\n    ),\n    url(\n        r'^password_reset/confirm/(?P<uidb64>[0-9A-Za-z_\\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',\n        'django.contrib.auth.views.password_reset_confirm',\n        {'template_name': 'wagtailadmin/account/password_reset/confirm.html'},\n        name='password_reset_confirm',\n    ),\n    url(\n        r'^password_reset/complete/$', 'django.contrib.auth.views.password_reset_complete',\n        {'template_name': 'wagtailadmin/account/password_reset/complete.html'},\n        name='password_reset_complete'\n    ),\n]\n\nurlpatterns += [\n    url(r'^$', home.home, name='wagtailadmin_home'),\n\n    url(r'^failwhale/$', home.error_test, name='wagtailadmin_error_test'),\n\n    url(r'^pages/$', pages.index, name='wagtailadmin_explore_root'),\n    url(r'^pages/(\\d+)/$', pages.index, name='wagtailadmin_explore'),\n\n    url(r'^pages/new/(\\w+)/(\\w+)/(\\d+)/$', pages.create, name='wagtailadmin_pages_create'),\n    url(r'^pages/new/(\\w+)/(\\w+)/(\\d+)/preview/$', pages.preview_on_create, name='wagtailadmin_pages_preview_on_create'),\n    url(r'^pages/usage/(\\w+)/(\\w+)/$', pages.content_type_use, name='wagtailadmin_pages_type_use'),\n\n    url(r'^pages/(\\d+)/edit/$', pages.edit, name='wagtailadmin_pages_edit'),\n    url(r'^pages/(\\d+)/edit/preview/$', pages.preview_on_edit, name='wagtailadmin_pages_preview_on_edit'),\n\n    url(r'^pages/preview_placeholder/$', pages.preview_placeholder, name='wagtailadmin_pages_preview_placeholder'),\n\n    url(r'^pages/(\\d+)/view_draft/$', pages.view_draft, name='wagtailadmin_pages_view_draft'),\n    url(r'^pages/(\\d+)/add_subpage/$', pages.add_subpage, name='wagtailadmin_pages_add_subpage'),\n    url(r'^pages/(\\d+)/delete/$', pages.delete, name='wagtailadmin_pages_delete'),\n    url(r'^pages/(\\d+)/unpublish/$', pages.unpublish, name='wagtailadmin_pages_unpublish'),\n\n    url(r'^pages/search/$', pages.search, name='wagtailadmin_pages_search'),\n\n    url(r'^pages/(\\d+)/move/$', pages.move_choose_destination, name='wagtailadmin_pages_move'),\n    url(r'^pages/(\\d+)/move/(\\d+)/$', pages.move_choose_destination, name='wagtailadmin_pages_move_choose_destination'),\n    url(r'^pages/(\\d+)/move/(\\d+)/confirm/$', pages.move_confirm, name='wagtailadmin_pages_move_confirm'),\n    url(r'^pages/(\\d+)/set_position/$', pages.set_page_position, name='wagtailadmin_pages_set_page_position'),\n\n    url(r'^pages/moderation/(\\d+)/approve/$', pages.approve_moderation, name='wagtailadmin_pages_approve_moderation'),\n    url(r'^pages/moderation/(\\d+)/reject/$', pages.reject_moderation, name='wagtailadmin_pages_reject_moderation'),\n    url(r'^pages/moderation/(\\d+)/preview/$', pages.preview_for_moderation, name='wagtailadmin_pages_preview_for_moderation'),\n\n    url(r'^choose-page/$', chooser.browse, name='wagtailadmin_choose_page'),\n    url(r'^choose-page/(\\d+)/$', chooser.browse, name='wagtailadmin_choose_page_child'),\n    url(r'^choose-external-link/$', chooser.external_link, name='wagtailadmin_choose_page_external_link'),\n    url(r'^choose-email-link/$', chooser.email_link, name='wagtailadmin_choose_page_email_link'),\n\n    url(r'^tag-autocomplete/$', tags.autocomplete, name='wagtailadmin_tag_autocomplete'),\n\n    url(r'^account/$', account.account, name='wagtailadmin_account'),\n    url(r'^account/change_password/$', account.change_password, name='wagtailadmin_account_change_password'),\n    url(r'^logout/$', account.logout, name='wagtailadmin_logout'),\n\n    url(r'^userbar/(\\d+)/$', userbar.for_frontend, name='wagtailadmin_userbar_frontend'),\n    url(r'^userbar/moderation/(\\d+)/$', userbar.for_moderation, name='wagtailadmin_userbar_moderation'),\n]\n\n\n# Import additional urlpatterns from any apps that define a register_admin_urls hook\nfor fn in hooks.get_hooks('register_admin_urls'):\n    urls = fn()\n    if urls:\n        urlpatterns += urls\n", "path": "wagtail/wagtailadmin/urls.py"}], "after_files": [{"content": "#!/usr/bin/env python\nimport sys\nimport os\nimport shutil\n\nfrom django.conf import settings, global_settings\nfrom django.core.management import execute_from_command_line\n\nWAGTAIL_ROOT = os.path.dirname(__file__)\nSTATIC_ROOT = os.path.join(WAGTAIL_ROOT, 'test-static')\nMEDIA_ROOT = os.path.join(WAGTAIL_ROOT, 'test-media')\n\nif not settings.configured:\n\n    try:\n        import elasticutils\n        has_elasticsearch = True\n    except ImportError:\n        has_elasticsearch = False\n\n    WAGTAILSEARCH_BACKENDS = {\n        'default': {\n            'BACKEND': 'wagtail.wagtailsearch.backends.db.DBSearch',\n        }\n    }\n    if has_elasticsearch:\n        WAGTAILSEARCH_BACKENDS['elasticsearch'] = {\n            'BACKEND': 'wagtail.wagtailsearch.backends.elasticsearch.ElasticSearch',\n            'TIMEOUT': 10,\n            'max_retries': 1,\n        }\n\n    settings.configure(\n        DATABASES={\n            'default': {\n                'ENGINE': os.environ.get('DATABASE_ENGINE', 'django.db.backends.postgresql_psycopg2'),\n                'NAME': 'wagtaildemo',\n                'USER': os.environ.get('DATABASE_USER', 'postgres'),\n            }\n        },\n        ROOT_URLCONF='wagtail.tests.urls',\n        STATIC_URL='/static/',\n        STATIC_ROOT=STATIC_ROOT,\n        MEDIA_ROOT=MEDIA_ROOT,\n        USE_TZ=True,\n        STATICFILES_FINDERS=(\n            'django.contrib.staticfiles.finders.AppDirectoriesFinder',\n            'compressor.finders.CompressorFinder',\n        ),\n        TEMPLATE_CONTEXT_PROCESSORS=global_settings.TEMPLATE_CONTEXT_PROCESSORS + (\n            'django.core.context_processors.request',\n        ),\n        MIDDLEWARE_CLASSES=(\n            'django.middleware.common.CommonMiddleware',\n            'django.contrib.sessions.middleware.SessionMiddleware',\n            'django.middleware.csrf.CsrfViewMiddleware',\n            'django.contrib.auth.middleware.AuthenticationMiddleware',\n            'django.contrib.messages.middleware.MessageMiddleware',\n            'django.middleware.clickjacking.XFrameOptionsMiddleware',\n\n            'wagtail.wagtailcore.middleware.SiteMiddleware',\n\n            'wagtail.wagtailredirects.middleware.RedirectMiddleware',\n        ),\n        INSTALLED_APPS=[\n            'django.contrib.contenttypes',\n            'django.contrib.sessions',\n            'django.contrib.auth',\n            'django.contrib.messages',\n            'django.contrib.staticfiles',\n            'django.contrib.admin',\n\n            'taggit',\n            'south',\n            'compressor',\n\n            'wagtail.wagtailcore',\n            'wagtail.wagtailadmin',\n            'wagtail.wagtaildocs',\n            'wagtail.wagtailsnippets',\n            'wagtail.wagtailusers',\n            'wagtail.wagtailimages',\n            'wagtail.wagtailembeds',\n            'wagtail.wagtailsearch',\n            'wagtail.wagtailredirects',\n            'wagtail.wagtailforms',\n            'wagtail.tests',\n        ],\n\n        # Using DatabaseCache to make sure that the cache is cleared between tests.\n        # This prevents false-positives in some wagtail core tests where we are\n        # changing the 'wagtail_root_paths' key which may cause future tests to fail.\n        CACHES = {\n            'default': {\n                'BACKEND': 'django.core.cache.backends.db.DatabaseCache',\n                'LOCATION': 'cache',\n            }\n        },\n        PASSWORD_HASHERS=(\n            'django.contrib.auth.hashers.MD5PasswordHasher',  # don't use the intentionally slow default password hasher\n        ),\n        COMPRESS_ENABLED=False,  # disable compression so that we can run tests on the content of the compress tag\n        WAGTAILSEARCH_BACKENDS=WAGTAILSEARCH_BACKENDS,\n        WAGTAIL_SITE_NAME='Test Site',\n        LOGIN_REDIRECT_URL='wagtailadmin_home',\n        LOGIN_URL='wagtailadmin_login',\n    )\n\n\ndef runtests():\n    argv = sys.argv[:1] + ['test'] + sys.argv[1:]\n    try:\n        execute_from_command_line(argv)\n    finally:\n        shutil.rmtree(STATIC_ROOT, ignore_errors=True)\n        shutil.rmtree(MEDIA_ROOT, ignore_errors=True)\n\n\nif __name__ == '__main__':\n    runtests()\n", "path": "runtests.py"}, {"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\n\n\n@permission_required('wagtailadmin.access_admin')\ndef account(request):\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    })\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@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"}, {"content": "from django.conf.urls import url\nfrom django.conf import settings\n\nfrom wagtail.wagtailadmin.forms import LoginForm, PasswordResetForm\nfrom wagtail.wagtailadmin.views import account, chooser, home, pages, tags, userbar\nfrom wagtail.wagtailadmin import hooks\n\n\nurlpatterns = [\n    # Password reset\n    url(\n        r'^password_reset/$', 'django.contrib.auth.views.password_reset', {\n            'template_name': 'wagtailadmin/account/password_reset/form.html',\n            'email_template_name': 'wagtailadmin/account/password_reset/email.txt',\n            'subject_template_name': 'wagtailadmin/account/password_reset/email_subject.txt',\n            'password_reset_form': PasswordResetForm,\n        }, name='password_reset'\n    ),\n    url(\n        r'^password_reset/done/$', 'django.contrib.auth.views.password_reset_done', {\n            'template_name': 'wagtailadmin/account/password_reset/done.html'\n        }, name='password_reset_done'\n    ),\n    url(\n        r'^password_reset/confirm/(?P<uidb64>[0-9A-Za-z_\\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',\n        'django.contrib.auth.views.password_reset_confirm',\n        {'template_name': 'wagtailadmin/account/password_reset/confirm.html'},\n        name='password_reset_confirm',\n    ),\n    url(\n        r'^password_reset/complete/$', 'django.contrib.auth.views.password_reset_complete',\n        {'template_name': 'wagtailadmin/account/password_reset/complete.html'},\n        name='password_reset_complete'\n    ),\n]\n\nurlpatterns += [\n    url(r'^$', home.home, name='wagtailadmin_home'),\n\n    url(r'^failwhale/$', home.error_test, name='wagtailadmin_error_test'),\n\n    url(r'^pages/$', pages.index, name='wagtailadmin_explore_root'),\n    url(r'^pages/(\\d+)/$', pages.index, name='wagtailadmin_explore'),\n\n    url(r'^pages/new/(\\w+)/(\\w+)/(\\d+)/$', pages.create, name='wagtailadmin_pages_create'),\n    url(r'^pages/new/(\\w+)/(\\w+)/(\\d+)/preview/$', pages.preview_on_create, name='wagtailadmin_pages_preview_on_create'),\n    url(r'^pages/usage/(\\w+)/(\\w+)/$', pages.content_type_use, name='wagtailadmin_pages_type_use'),\n\n    url(r'^pages/(\\d+)/edit/$', pages.edit, name='wagtailadmin_pages_edit'),\n    url(r'^pages/(\\d+)/edit/preview/$', pages.preview_on_edit, name='wagtailadmin_pages_preview_on_edit'),\n\n    url(r'^pages/preview_placeholder/$', pages.preview_placeholder, name='wagtailadmin_pages_preview_placeholder'),\n\n    url(r'^pages/(\\d+)/view_draft/$', pages.view_draft, name='wagtailadmin_pages_view_draft'),\n    url(r'^pages/(\\d+)/add_subpage/$', pages.add_subpage, name='wagtailadmin_pages_add_subpage'),\n    url(r'^pages/(\\d+)/delete/$', pages.delete, name='wagtailadmin_pages_delete'),\n    url(r'^pages/(\\d+)/unpublish/$', pages.unpublish, name='wagtailadmin_pages_unpublish'),\n\n    url(r'^pages/search/$', pages.search, name='wagtailadmin_pages_search'),\n\n    url(r'^pages/(\\d+)/move/$', pages.move_choose_destination, name='wagtailadmin_pages_move'),\n    url(r'^pages/(\\d+)/move/(\\d+)/$', pages.move_choose_destination, name='wagtailadmin_pages_move_choose_destination'),\n    url(r'^pages/(\\d+)/move/(\\d+)/confirm/$', pages.move_confirm, name='wagtailadmin_pages_move_confirm'),\n    url(r'^pages/(\\d+)/set_position/$', pages.set_page_position, name='wagtailadmin_pages_set_page_position'),\n\n    url(r'^pages/moderation/(\\d+)/approve/$', pages.approve_moderation, name='wagtailadmin_pages_approve_moderation'),\n    url(r'^pages/moderation/(\\d+)/reject/$', pages.reject_moderation, name='wagtailadmin_pages_reject_moderation'),\n    url(r'^pages/moderation/(\\d+)/preview/$', pages.preview_for_moderation, name='wagtailadmin_pages_preview_for_moderation'),\n\n    url(r'^choose-page/$', chooser.browse, name='wagtailadmin_choose_page'),\n    url(r'^choose-page/(\\d+)/$', chooser.browse, name='wagtailadmin_choose_page_child'),\n    url(r'^choose-external-link/$', chooser.external_link, name='wagtailadmin_choose_page_external_link'),\n    url(r'^choose-email-link/$', chooser.email_link, name='wagtailadmin_choose_page_email_link'),\n\n    url(r'^tag-autocomplete/$', tags.autocomplete, name='wagtailadmin_tag_autocomplete'),\n\n    url(r'^login/$', account.login, name='wagtailadmin_login'),\n    url(r'^account/$', account.account, name='wagtailadmin_account'),\n    url(r'^account/change_password/$', account.change_password, name='wagtailadmin_account_change_password'),\n    url(r'^logout/$', account.logout, name='wagtailadmin_logout'),\n\n    url(r'^userbar/(\\d+)/$', userbar.for_frontend, name='wagtailadmin_userbar_frontend'),\n    url(r'^userbar/moderation/(\\d+)/$', userbar.for_moderation, name='wagtailadmin_userbar_moderation'),\n]\n\n\n# This is here to make sure that 'django.contrib.auth.views.login' is reversed correctly\n# It must be placed after 'wagtailadmin_login' to prevent this from being used\nurlpatterns += [\n    url(r'^login/$', 'django.contrib.auth.views.login'),\n]\n\n\n# Import additional urlpatterns from any apps that define a register_admin_urls hook\nfor fn in hooks.get_hooks('register_admin_urls'):\n    urls = fn()\n    if urls:\n        urlpatterns += urls\n", "path": "wagtail/wagtailadmin/urls.py"}]}