We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Security] Open Redirect on Login page
### Description

The application currently has a security vulnerability known as an "Open Redirect" on its login page. This issue arises because the application fails to properly check and validate the URLs provided in the next parameter during the login process. As a result, attackers can exploit this by inserting an external URL into the next parameter. When a user logs in, instead of being redirected to an internal page, they are unwittingly sent to a potentially malicious external website. This vulnerability can be used for phishing attacks, where users are redirected to fake websites that steal their personal information, or for spreading malware. It's crucial to address this vulnerability to protect users from being redirected to unsafe and untrusted websites.

### Steps to reproduce

1. In the browser's address bar, modify the URL by adding a next parameter with a value pointing to an external website. For example, change it to /accounts/login/?next=//evil.com
2. Log in using valid credentials.
3. Observe that after a successful login, instead of being directed to an internal page of the application, you are redirected to the external website specified in the next parameter.

### Webserver logs

```bash
n/a
```


### Browser logs

_No response_

### Paperless-ngx version

v 2.5.2

### Host OS

Ubuntu 22.04.3 

### Installation method

Docker - official image

### Browser

_No response_

### Configuration changes

_No response_

### Other

_No response_

### Please confirm the following

- [X] I believe this issue is a bug that affects all users of Paperless-ngx, not something specific to my installation.
- [X] I have already searched for relevant existing issues and discussions before opening this report.
- [X] I have updated the title field above with a concise description.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/paperless/urls.py`
Content:
```
1 import os
2 
3 from django.conf import settings
4 from django.conf.urls import include
5 from django.contrib import admin
6 from django.contrib.auth.decorators import login_required
7 from django.urls import path
8 from django.urls import re_path
9 from django.utils.translation import gettext_lazy as _
10 from django.views.decorators.csrf import csrf_exempt
11 from django.views.decorators.csrf import ensure_csrf_cookie
12 from django.views.generic import RedirectView
13 from django.views.static import serve
14 from rest_framework.authtoken import views
15 from rest_framework.routers import DefaultRouter
16 
17 from documents.views import AcknowledgeTasksView
18 from documents.views import BulkDownloadView
19 from documents.views import BulkEditObjectsView
20 from documents.views import BulkEditView
21 from documents.views import CorrespondentViewSet
22 from documents.views import CustomFieldViewSet
23 from documents.views import DocumentTypeViewSet
24 from documents.views import IndexView
25 from documents.views import LogViewSet
26 from documents.views import PostDocumentView
27 from documents.views import RemoteVersionView
28 from documents.views import SavedViewViewSet
29 from documents.views import SearchAutoCompleteView
30 from documents.views import SelectionDataView
31 from documents.views import SharedLinkView
32 from documents.views import ShareLinkViewSet
33 from documents.views import StatisticsView
34 from documents.views import StoragePathViewSet
35 from documents.views import TagViewSet
36 from documents.views import TasksViewSet
37 from documents.views import UiSettingsView
38 from documents.views import UnifiedSearchViewSet
39 from documents.views import WorkflowActionViewSet
40 from documents.views import WorkflowTriggerViewSet
41 from documents.views import WorkflowViewSet
42 from paperless.consumers import StatusConsumer
43 from paperless.views import ApplicationConfigurationViewSet
44 from paperless.views import DisconnectSocialAccountView
45 from paperless.views import FaviconView
46 from paperless.views import GenerateAuthTokenView
47 from paperless.views import GroupViewSet
48 from paperless.views import ProfileView
49 from paperless.views import SocialAccountProvidersView
50 from paperless.views import UserViewSet
51 from paperless_mail.views import MailAccountTestView
52 from paperless_mail.views import MailAccountViewSet
53 from paperless_mail.views import MailRuleViewSet
54 
55 api_router = DefaultRouter()
56 api_router.register(r"correspondents", CorrespondentViewSet)
57 api_router.register(r"document_types", DocumentTypeViewSet)
58 api_router.register(r"documents", UnifiedSearchViewSet)
59 api_router.register(r"logs", LogViewSet, basename="logs")
60 api_router.register(r"tags", TagViewSet)
61 api_router.register(r"saved_views", SavedViewViewSet)
62 api_router.register(r"storage_paths", StoragePathViewSet)
63 api_router.register(r"tasks", TasksViewSet, basename="tasks")
64 api_router.register(r"users", UserViewSet, basename="users")
65 api_router.register(r"groups", GroupViewSet, basename="groups")
66 api_router.register(r"mail_accounts", MailAccountViewSet)
67 api_router.register(r"mail_rules", MailRuleViewSet)
68 api_router.register(r"share_links", ShareLinkViewSet)
69 api_router.register(r"workflow_triggers", WorkflowTriggerViewSet)
70 api_router.register(r"workflow_actions", WorkflowActionViewSet)
71 api_router.register(r"workflows", WorkflowViewSet)
72 api_router.register(r"custom_fields", CustomFieldViewSet)
73 api_router.register(r"config", ApplicationConfigurationViewSet)
74 
75 
76 urlpatterns = [
77     re_path(
78         r"^api/",
79         include(
80             [
81                 re_path(
82                     "^auth/",
83                     include(
84                         ("rest_framework.urls", "rest_framework"),
85                         namespace="rest_framework",
86                     ),
87                 ),
88                 re_path(
89                     "^search/autocomplete/",
90                     SearchAutoCompleteView.as_view(),
91                     name="autocomplete",
92                 ),
93                 re_path("^statistics/", StatisticsView.as_view(), name="statistics"),
94                 re_path(
95                     "^documents/post_document/",
96                     PostDocumentView.as_view(),
97                     name="post_document",
98                 ),
99                 re_path(
100                     "^documents/bulk_edit/",
101                     BulkEditView.as_view(),
102                     name="bulk_edit",
103                 ),
104                 re_path(
105                     "^documents/selection_data/",
106                     SelectionDataView.as_view(),
107                     name="selection_data",
108                 ),
109                 re_path(
110                     "^documents/bulk_download/",
111                     BulkDownloadView.as_view(),
112                     name="bulk_download",
113                 ),
114                 re_path(
115                     "^remote_version/",
116                     RemoteVersionView.as_view(),
117                     name="remoteversion",
118                 ),
119                 re_path("^ui_settings/", UiSettingsView.as_view(), name="ui_settings"),
120                 re_path(
121                     "^acknowledge_tasks/",
122                     AcknowledgeTasksView.as_view(),
123                     name="acknowledge_tasks",
124                 ),
125                 re_path(
126                     "^mail_accounts/test/",
127                     MailAccountTestView.as_view(),
128                     name="mail_accounts_test",
129                 ),
130                 path("token/", views.obtain_auth_token),
131                 re_path(
132                     "^bulk_edit_objects/",
133                     BulkEditObjectsView.as_view(),
134                     name="bulk_edit_objects",
135                 ),
136                 path("profile/generate_auth_token/", GenerateAuthTokenView.as_view()),
137                 path(
138                     "profile/disconnect_social_account/",
139                     DisconnectSocialAccountView.as_view(),
140                 ),
141                 path(
142                     "profile/social_account_providers/",
143                     SocialAccountProvidersView.as_view(),
144                 ),
145                 re_path(
146                     "^profile/",
147                     ProfileView.as_view(),
148                     name="profile_view",
149                 ),
150                 *api_router.urls,
151             ],
152         ),
153     ),
154     re_path(r"share/(?P<slug>\w+)/?$", SharedLinkView.as_view()),
155     re_path(r"^favicon.ico$", FaviconView.as_view(), name="favicon"),
156     re_path(r"admin/", admin.site.urls),
157     re_path(
158         r"^fetch/",
159         include(
160             [
161                 re_path(
162                     r"^doc/(?P<pk>\d+)$",
163                     RedirectView.as_view(
164                         url=settings.BASE_URL + "api/documents/%(pk)s/download/",
165                     ),
166                 ),
167                 re_path(
168                     r"^thumb/(?P<pk>\d+)$",
169                     RedirectView.as_view(
170                         url=settings.BASE_URL + "api/documents/%(pk)s/thumb/",
171                     ),
172                 ),
173                 re_path(
174                     r"^preview/(?P<pk>\d+)$",
175                     RedirectView.as_view(
176                         url=settings.BASE_URL + "api/documents/%(pk)s/preview/",
177                     ),
178                 ),
179             ],
180         ),
181     ),
182     re_path(
183         r"^push$",
184         csrf_exempt(
185             RedirectView.as_view(
186                 url=settings.BASE_URL + "api/documents/post_document/",
187             ),
188         ),
189     ),
190     # Frontend assets TODO: this is pretty bad, but it works.
191     path(
192         "assets/<path:path>",
193         RedirectView.as_view(
194             url=settings.STATIC_URL + "frontend/en-US/assets/%(path)s",
195         ),
196     ),
197     # App logo
198     re_path(
199         r"^logo(?P<path>.*)$",
200         serve,
201         kwargs={"document_root": os.path.join(settings.MEDIA_ROOT, "logo")},
202     ),
203     # TODO: with localization, this is even worse! :/
204     # login, logout
205     path("accounts/", include("allauth.urls")),
206     # Root of the Frontend
207     re_path(
208         r".*",
209         login_required(ensure_csrf_cookie(IndexView.as_view())),
210         name="base",
211     ),
212 ]
213 
214 
215 websocket_urlpatterns = [
216     path(settings.BASE_URL.lstrip("/") + "ws/status/", StatusConsumer.as_asgi()),
217 ]
218 
219 # Text in each page's <h1> (and above login form).
220 admin.site.site_header = "Paperless-ngx"
221 # Text at the end of each page's <title>.
222 admin.site.site_title = "Paperless-ngx"
223 # Text at the top of the admin index page.
224 admin.site.index_title = _("Paperless-ngx administration")
225
```

Path: `src/paperless/adapter.py`
Content:
```
1 from allauth.account.adapter import DefaultAccountAdapter
2 from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
3 from django.conf import settings
4 from django.urls import reverse
5 
6 
7 class CustomAccountAdapter(DefaultAccountAdapter):
8     def is_open_for_signup(self, request):
9         allow_signups = super().is_open_for_signup(request)
10         # Override with setting, otherwise default to super.
11         return getattr(settings, "ACCOUNT_ALLOW_SIGNUPS", allow_signups)
12 
13 
14 class CustomSocialAccountAdapter(DefaultSocialAccountAdapter):
15     def is_open_for_signup(self, request, sociallogin):
16         allow_signups = super().is_open_for_signup(request, sociallogin)
17         # Override with setting, otherwise default to super.
18         return getattr(settings, "SOCIALACCOUNT_ALLOW_SIGNUPS", allow_signups)
19 
20     def get_connect_redirect_url(self, request, socialaccount):
21         """
22         Returns the default URL to redirect to after successfully
23         connecting a social account.
24         """
25         url = reverse("base")
26         return url
27 
28     def populate_user(self, request, sociallogin, data):
29         # TODO: If default global permissions are implemented, should also be here
30         return super().populate_user(request, sociallogin, data)  # pragma: no cover
31
```
--- 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/src/paperless/adapter.py b/src/paperless/adapter.py
--- a/src/paperless/adapter.py
+++ b/src/paperless/adapter.py
@@ -1,4 +1,5 @@
 from allauth.account.adapter import DefaultAccountAdapter
+from allauth.core import context
 from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
 from django.conf import settings
 from django.urls import reverse
@@ -10,6 +11,21 @@
         # Override with setting, otherwise default to super.
         return getattr(settings, "ACCOUNT_ALLOW_SIGNUPS", allow_signups)
 
+    def is_safe_url(self, url):
+        # see https://github.com/paperless-ngx/paperless-ngx/issues/5780
+        from django.utils.http import url_has_allowed_host_and_scheme
+
+        # get_host already validates the given host, so no need to check it again
+        allowed_hosts = {context.request.get_host()} | set(settings.ALLOWED_HOSTS)
+
+        if "*" in allowed_hosts:
+            # dont allow wildcard to allow urls from any host
+            allowed_hosts.remove("*")
+            allowed_hosts.add(context.request.get_host())
+            return url_has_allowed_host_and_scheme(url, allowed_hosts=allowed_hosts)
+
+        return url_has_allowed_host_and_scheme(url, allowed_hosts=allowed_hosts)
+
 
 class CustomSocialAccountAdapter(DefaultSocialAccountAdapter):
     def is_open_for_signup(self, request, sociallogin):
diff --git a/src/paperless/urls.py b/src/paperless/urls.py
--- a/src/paperless/urls.py
+++ b/src/paperless/urls.py
@@ -193,6 +193,7 @@
         RedirectView.as_view(
             url=settings.STATIC_URL + "frontend/en-US/assets/%(path)s",
         ),
+        # TODO: with localization, this is even worse! :/
     ),
     # App logo
     re_path(
@@ -200,7 +201,6 @@
         serve,
         kwargs={"document_root": os.path.join(settings.MEDIA_ROOT, "logo")},
     ),
-    # TODO: with localization, this is even worse! :/
     # login, logout
     path("accounts/", include("allauth.urls")),
     # Root of the Frontend

{"golden_diff": "diff --git a/src/paperless/adapter.py b/src/paperless/adapter.py\n--- a/src/paperless/adapter.py\n+++ b/src/paperless/adapter.py\n@@ -1,4 +1,5 @@\n from allauth.account.adapter import DefaultAccountAdapter\n+from allauth.core import context\n from allauth.socialaccount.adapter import DefaultSocialAccountAdapter\n from django.conf import settings\n from django.urls import reverse\n@@ -10,6 +11,21 @@\n         # Override with setting, otherwise default to super.\n         return getattr(settings, \"ACCOUNT_ALLOW_SIGNUPS\", allow_signups)\n \n+    def is_safe_url(self, url):\n+        # see https://github.com/paperless-ngx/paperless-ngx/issues/5780\n+        from django.utils.http import url_has_allowed_host_and_scheme\n+\n+        # get_host already validates the given host, so no need to check it again\n+        allowed_hosts = {context.request.get_host()} | set(settings.ALLOWED_HOSTS)\n+\n+        if \"*\" in allowed_hosts:\n+            # dont allow wildcard to allow urls from any host\n+            allowed_hosts.remove(\"*\")\n+            allowed_hosts.add(context.request.get_host())\n+            return url_has_allowed_host_and_scheme(url, allowed_hosts=allowed_hosts)\n+\n+        return url_has_allowed_host_and_scheme(url, allowed_hosts=allowed_hosts)\n+\n \n class CustomSocialAccountAdapter(DefaultSocialAccountAdapter):\n     def is_open_for_signup(self, request, sociallogin):\ndiff --git a/src/paperless/urls.py b/src/paperless/urls.py\n--- a/src/paperless/urls.py\n+++ b/src/paperless/urls.py\n@@ -193,6 +193,7 @@\n         RedirectView.as_view(\n             url=settings.STATIC_URL + \"frontend/en-US/assets/%(path)s\",\n         ),\n+        # TODO: with localization, this is even worse! :/\n     ),\n     # App logo\n     re_path(\n@@ -200,7 +201,6 @@\n         serve,\n         kwargs={\"document_root\": os.path.join(settings.MEDIA_ROOT, \"logo\")},\n     ),\n-    # TODO: with localization, this is even worse! :/\n     # login, logout\n     path(\"accounts/\", include(\"allauth.urls\")),\n     # Root of the Frontend\n", "issue": "[Security] Open Redirect on Login page\n### Description\n\nThe application currently has a security vulnerability known as an \"Open Redirect\" on its login page. This issue arises because the application fails to properly check and validate the URLs provided in the next parameter during the login process. As a result, attackers can exploit this by inserting an external URL into the next parameter. When a user logs in, instead of being redirected to an internal page, they are unwittingly sent to a potentially malicious external website. This vulnerability can be used for phishing attacks, where users are redirected to fake websites that steal their personal information, or for spreading malware. It's crucial to address this vulnerability to protect users from being redirected to unsafe and untrusted websites.\n\n### Steps to reproduce\n\n1. In the browser's address bar, modify the URL by adding a next parameter with a value pointing to an external website. For example, change it to /accounts/login/?next=//evil.com\r\n2. Log in using valid credentials.\r\n3. Observe that after a successful login, instead of being directed to an internal page of the application, you are redirected to the external website specified in the next parameter.\n\n### Webserver logs\n\n```bash\nn/a\n```\n\n\n### Browser logs\n\n_No response_\n\n### Paperless-ngx version\n\nv 2.5.2\n\n### Host OS\n\nUbuntu 22.04.3 \n\n### Installation method\n\nDocker - official image\n\n### Browser\n\n_No response_\n\n### Configuration changes\n\n_No response_\n\n### Other\n\n_No response_\n\n### Please confirm the following\n\n- [X] I believe this issue is a bug that affects all users of Paperless-ngx, not something specific to my installation.\n- [X] I have already searched for relevant existing issues and discussions before opening this report.\n- [X] I have updated the title field above with a concise description.\n", "before_files": [{"content": "import os\n\nfrom django.conf import settings\nfrom django.conf.urls import include\nfrom django.contrib import admin\nfrom django.contrib.auth.decorators import login_required\nfrom django.urls import path\nfrom django.urls import re_path\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views.decorators.csrf import csrf_exempt\nfrom django.views.decorators.csrf import ensure_csrf_cookie\nfrom django.views.generic import RedirectView\nfrom django.views.static import serve\nfrom rest_framework.authtoken import views\nfrom rest_framework.routers import DefaultRouter\n\nfrom documents.views import AcknowledgeTasksView\nfrom documents.views import BulkDownloadView\nfrom documents.views import BulkEditObjectsView\nfrom documents.views import BulkEditView\nfrom documents.views import CorrespondentViewSet\nfrom documents.views import CustomFieldViewSet\nfrom documents.views import DocumentTypeViewSet\nfrom documents.views import IndexView\nfrom documents.views import LogViewSet\nfrom documents.views import PostDocumentView\nfrom documents.views import RemoteVersionView\nfrom documents.views import SavedViewViewSet\nfrom documents.views import SearchAutoCompleteView\nfrom documents.views import SelectionDataView\nfrom documents.views import SharedLinkView\nfrom documents.views import ShareLinkViewSet\nfrom documents.views import StatisticsView\nfrom documents.views import StoragePathViewSet\nfrom documents.views import TagViewSet\nfrom documents.views import TasksViewSet\nfrom documents.views import UiSettingsView\nfrom documents.views import UnifiedSearchViewSet\nfrom documents.views import WorkflowActionViewSet\nfrom documents.views import WorkflowTriggerViewSet\nfrom documents.views import WorkflowViewSet\nfrom paperless.consumers import StatusConsumer\nfrom paperless.views import ApplicationConfigurationViewSet\nfrom paperless.views import DisconnectSocialAccountView\nfrom paperless.views import FaviconView\nfrom paperless.views import GenerateAuthTokenView\nfrom paperless.views import GroupViewSet\nfrom paperless.views import ProfileView\nfrom paperless.views import SocialAccountProvidersView\nfrom paperless.views import UserViewSet\nfrom paperless_mail.views import MailAccountTestView\nfrom paperless_mail.views import MailAccountViewSet\nfrom paperless_mail.views import MailRuleViewSet\n\napi_router = DefaultRouter()\napi_router.register(r\"correspondents\", CorrespondentViewSet)\napi_router.register(r\"document_types\", DocumentTypeViewSet)\napi_router.register(r\"documents\", UnifiedSearchViewSet)\napi_router.register(r\"logs\", LogViewSet, basename=\"logs\")\napi_router.register(r\"tags\", TagViewSet)\napi_router.register(r\"saved_views\", SavedViewViewSet)\napi_router.register(r\"storage_paths\", StoragePathViewSet)\napi_router.register(r\"tasks\", TasksViewSet, basename=\"tasks\")\napi_router.register(r\"users\", UserViewSet, basename=\"users\")\napi_router.register(r\"groups\", GroupViewSet, basename=\"groups\")\napi_router.register(r\"mail_accounts\", MailAccountViewSet)\napi_router.register(r\"mail_rules\", MailRuleViewSet)\napi_router.register(r\"share_links\", ShareLinkViewSet)\napi_router.register(r\"workflow_triggers\", WorkflowTriggerViewSet)\napi_router.register(r\"workflow_actions\", WorkflowActionViewSet)\napi_router.register(r\"workflows\", WorkflowViewSet)\napi_router.register(r\"custom_fields\", CustomFieldViewSet)\napi_router.register(r\"config\", ApplicationConfigurationViewSet)\n\n\nurlpatterns = [\n    re_path(\n        r\"^api/\",\n        include(\n            [\n                re_path(\n                    \"^auth/\",\n                    include(\n                        (\"rest_framework.urls\", \"rest_framework\"),\n                        namespace=\"rest_framework\",\n                    ),\n                ),\n                re_path(\n                    \"^search/autocomplete/\",\n                    SearchAutoCompleteView.as_view(),\n                    name=\"autocomplete\",\n                ),\n                re_path(\"^statistics/\", StatisticsView.as_view(), name=\"statistics\"),\n                re_path(\n                    \"^documents/post_document/\",\n                    PostDocumentView.as_view(),\n                    name=\"post_document\",\n                ),\n                re_path(\n                    \"^documents/bulk_edit/\",\n                    BulkEditView.as_view(),\n                    name=\"bulk_edit\",\n                ),\n                re_path(\n                    \"^documents/selection_data/\",\n                    SelectionDataView.as_view(),\n                    name=\"selection_data\",\n                ),\n                re_path(\n                    \"^documents/bulk_download/\",\n                    BulkDownloadView.as_view(),\n                    name=\"bulk_download\",\n                ),\n                re_path(\n                    \"^remote_version/\",\n                    RemoteVersionView.as_view(),\n                    name=\"remoteversion\",\n                ),\n                re_path(\"^ui_settings/\", UiSettingsView.as_view(), name=\"ui_settings\"),\n                re_path(\n                    \"^acknowledge_tasks/\",\n                    AcknowledgeTasksView.as_view(),\n                    name=\"acknowledge_tasks\",\n                ),\n                re_path(\n                    \"^mail_accounts/test/\",\n                    MailAccountTestView.as_view(),\n                    name=\"mail_accounts_test\",\n                ),\n                path(\"token/\", views.obtain_auth_token),\n                re_path(\n                    \"^bulk_edit_objects/\",\n                    BulkEditObjectsView.as_view(),\n                    name=\"bulk_edit_objects\",\n                ),\n                path(\"profile/generate_auth_token/\", GenerateAuthTokenView.as_view()),\n                path(\n                    \"profile/disconnect_social_account/\",\n                    DisconnectSocialAccountView.as_view(),\n                ),\n                path(\n                    \"profile/social_account_providers/\",\n                    SocialAccountProvidersView.as_view(),\n                ),\n                re_path(\n                    \"^profile/\",\n                    ProfileView.as_view(),\n                    name=\"profile_view\",\n                ),\n                *api_router.urls,\n            ],\n        ),\n    ),\n    re_path(r\"share/(?P<slug>\\w+)/?$\", SharedLinkView.as_view()),\n    re_path(r\"^favicon.ico$\", FaviconView.as_view(), name=\"favicon\"),\n    re_path(r\"admin/\", admin.site.urls),\n    re_path(\n        r\"^fetch/\",\n        include(\n            [\n                re_path(\n                    r\"^doc/(?P<pk>\\d+)$\",\n                    RedirectView.as_view(\n                        url=settings.BASE_URL + \"api/documents/%(pk)s/download/\",\n                    ),\n                ),\n                re_path(\n                    r\"^thumb/(?P<pk>\\d+)$\",\n                    RedirectView.as_view(\n                        url=settings.BASE_URL + \"api/documents/%(pk)s/thumb/\",\n                    ),\n                ),\n                re_path(\n                    r\"^preview/(?P<pk>\\d+)$\",\n                    RedirectView.as_view(\n                        url=settings.BASE_URL + \"api/documents/%(pk)s/preview/\",\n                    ),\n                ),\n            ],\n        ),\n    ),\n    re_path(\n        r\"^push$\",\n        csrf_exempt(\n            RedirectView.as_view(\n                url=settings.BASE_URL + \"api/documents/post_document/\",\n            ),\n        ),\n    ),\n    # Frontend assets TODO: this is pretty bad, but it works.\n    path(\n        \"assets/<path:path>\",\n        RedirectView.as_view(\n            url=settings.STATIC_URL + \"frontend/en-US/assets/%(path)s\",\n        ),\n    ),\n    # App logo\n    re_path(\n        r\"^logo(?P<path>.*)$\",\n        serve,\n        kwargs={\"document_root\": os.path.join(settings.MEDIA_ROOT, \"logo\")},\n    ),\n    # TODO: with localization, this is even worse! :/\n    # login, logout\n    path(\"accounts/\", include(\"allauth.urls\")),\n    # Root of the Frontend\n    re_path(\n        r\".*\",\n        login_required(ensure_csrf_cookie(IndexView.as_view())),\n        name=\"base\",\n    ),\n]\n\n\nwebsocket_urlpatterns = [\n    path(settings.BASE_URL.lstrip(\"/\") + \"ws/status/\", StatusConsumer.as_asgi()),\n]\n\n# Text in each page's <h1> (and above login form).\nadmin.site.site_header = \"Paperless-ngx\"\n# Text at the end of each page's <title>.\nadmin.site.site_title = \"Paperless-ngx\"\n# Text at the top of the admin index page.\nadmin.site.index_title = _(\"Paperless-ngx administration\")\n", "path": "src/paperless/urls.py"}, {"content": "from allauth.account.adapter import DefaultAccountAdapter\nfrom allauth.socialaccount.adapter import DefaultSocialAccountAdapter\nfrom django.conf import settings\nfrom django.urls import reverse\n\n\nclass CustomAccountAdapter(DefaultAccountAdapter):\n    def is_open_for_signup(self, request):\n        allow_signups = super().is_open_for_signup(request)\n        # Override with setting, otherwise default to super.\n        return getattr(settings, \"ACCOUNT_ALLOW_SIGNUPS\", allow_signups)\n\n\nclass CustomSocialAccountAdapter(DefaultSocialAccountAdapter):\n    def is_open_for_signup(self, request, sociallogin):\n        allow_signups = super().is_open_for_signup(request, sociallogin)\n        # Override with setting, otherwise default to super.\n        return getattr(settings, \"SOCIALACCOUNT_ALLOW_SIGNUPS\", allow_signups)\n\n    def get_connect_redirect_url(self, request, socialaccount):\n        \"\"\"\n        Returns the default URL to redirect to after successfully\n        connecting a social account.\n        \"\"\"\n        url = reverse(\"base\")\n        return url\n\n    def populate_user(self, request, sociallogin, data):\n        # TODO: If default global permissions are implemented, should also be here\n        return super().populate_user(request, sociallogin, data)  # pragma: no cover\n", "path": "src/paperless/adapter.py"}], "after_files": [{"content": "import os\n\nfrom django.conf import settings\nfrom django.conf.urls import include\nfrom django.contrib import admin\nfrom django.contrib.auth.decorators import login_required\nfrom django.urls import path\nfrom django.urls import re_path\nfrom django.utils.translation import gettext_lazy as _\nfrom django.views.decorators.csrf import csrf_exempt\nfrom django.views.decorators.csrf import ensure_csrf_cookie\nfrom django.views.generic import RedirectView\nfrom django.views.static import serve\nfrom rest_framework.authtoken import views\nfrom rest_framework.routers import DefaultRouter\n\nfrom documents.views import AcknowledgeTasksView\nfrom documents.views import BulkDownloadView\nfrom documents.views import BulkEditObjectsView\nfrom documents.views import BulkEditView\nfrom documents.views import CorrespondentViewSet\nfrom documents.views import CustomFieldViewSet\nfrom documents.views import DocumentTypeViewSet\nfrom documents.views import IndexView\nfrom documents.views import LogViewSet\nfrom documents.views import PostDocumentView\nfrom documents.views import RemoteVersionView\nfrom documents.views import SavedViewViewSet\nfrom documents.views import SearchAutoCompleteView\nfrom documents.views import SelectionDataView\nfrom documents.views import SharedLinkView\nfrom documents.views import ShareLinkViewSet\nfrom documents.views import StatisticsView\nfrom documents.views import StoragePathViewSet\nfrom documents.views import TagViewSet\nfrom documents.views import TasksViewSet\nfrom documents.views import UiSettingsView\nfrom documents.views import UnifiedSearchViewSet\nfrom documents.views import WorkflowActionViewSet\nfrom documents.views import WorkflowTriggerViewSet\nfrom documents.views import WorkflowViewSet\nfrom paperless.consumers import StatusConsumer\nfrom paperless.views import ApplicationConfigurationViewSet\nfrom paperless.views import DisconnectSocialAccountView\nfrom paperless.views import FaviconView\nfrom paperless.views import GenerateAuthTokenView\nfrom paperless.views import GroupViewSet\nfrom paperless.views import ProfileView\nfrom paperless.views import SocialAccountProvidersView\nfrom paperless.views import UserViewSet\nfrom paperless_mail.views import MailAccountTestView\nfrom paperless_mail.views import MailAccountViewSet\nfrom paperless_mail.views import MailRuleViewSet\n\napi_router = DefaultRouter()\napi_router.register(r\"correspondents\", CorrespondentViewSet)\napi_router.register(r\"document_types\", DocumentTypeViewSet)\napi_router.register(r\"documents\", UnifiedSearchViewSet)\napi_router.register(r\"logs\", LogViewSet, basename=\"logs\")\napi_router.register(r\"tags\", TagViewSet)\napi_router.register(r\"saved_views\", SavedViewViewSet)\napi_router.register(r\"storage_paths\", StoragePathViewSet)\napi_router.register(r\"tasks\", TasksViewSet, basename=\"tasks\")\napi_router.register(r\"users\", UserViewSet, basename=\"users\")\napi_router.register(r\"groups\", GroupViewSet, basename=\"groups\")\napi_router.register(r\"mail_accounts\", MailAccountViewSet)\napi_router.register(r\"mail_rules\", MailRuleViewSet)\napi_router.register(r\"share_links\", ShareLinkViewSet)\napi_router.register(r\"workflow_triggers\", WorkflowTriggerViewSet)\napi_router.register(r\"workflow_actions\", WorkflowActionViewSet)\napi_router.register(r\"workflows\", WorkflowViewSet)\napi_router.register(r\"custom_fields\", CustomFieldViewSet)\napi_router.register(r\"config\", ApplicationConfigurationViewSet)\n\n\nurlpatterns = [\n    re_path(\n        r\"^api/\",\n        include(\n            [\n                re_path(\n                    \"^auth/\",\n                    include(\n                        (\"rest_framework.urls\", \"rest_framework\"),\n                        namespace=\"rest_framework\",\n                    ),\n                ),\n                re_path(\n                    \"^search/autocomplete/\",\n                    SearchAutoCompleteView.as_view(),\n                    name=\"autocomplete\",\n                ),\n                re_path(\"^statistics/\", StatisticsView.as_view(), name=\"statistics\"),\n                re_path(\n                    \"^documents/post_document/\",\n                    PostDocumentView.as_view(),\n                    name=\"post_document\",\n                ),\n                re_path(\n                    \"^documents/bulk_edit/\",\n                    BulkEditView.as_view(),\n                    name=\"bulk_edit\",\n                ),\n                re_path(\n                    \"^documents/selection_data/\",\n                    SelectionDataView.as_view(),\n                    name=\"selection_data\",\n                ),\n                re_path(\n                    \"^documents/bulk_download/\",\n                    BulkDownloadView.as_view(),\n                    name=\"bulk_download\",\n                ),\n                re_path(\n                    \"^remote_version/\",\n                    RemoteVersionView.as_view(),\n                    name=\"remoteversion\",\n                ),\n                re_path(\"^ui_settings/\", UiSettingsView.as_view(), name=\"ui_settings\"),\n                re_path(\n                    \"^acknowledge_tasks/\",\n                    AcknowledgeTasksView.as_view(),\n                    name=\"acknowledge_tasks\",\n                ),\n                re_path(\n                    \"^mail_accounts/test/\",\n                    MailAccountTestView.as_view(),\n                    name=\"mail_accounts_test\",\n                ),\n                path(\"token/\", views.obtain_auth_token),\n                re_path(\n                    \"^bulk_edit_objects/\",\n                    BulkEditObjectsView.as_view(),\n                    name=\"bulk_edit_objects\",\n                ),\n                path(\"profile/generate_auth_token/\", GenerateAuthTokenView.as_view()),\n                path(\n                    \"profile/disconnect_social_account/\",\n                    DisconnectSocialAccountView.as_view(),\n                ),\n                path(\n                    \"profile/social_account_providers/\",\n                    SocialAccountProvidersView.as_view(),\n                ),\n                re_path(\n                    \"^profile/\",\n                    ProfileView.as_view(),\n                    name=\"profile_view\",\n                ),\n                *api_router.urls,\n            ],\n        ),\n    ),\n    re_path(r\"share/(?P<slug>\\w+)/?$\", SharedLinkView.as_view()),\n    re_path(r\"^favicon.ico$\", FaviconView.as_view(), name=\"favicon\"),\n    re_path(r\"admin/\", admin.site.urls),\n    re_path(\n        r\"^fetch/\",\n        include(\n            [\n                re_path(\n                    r\"^doc/(?P<pk>\\d+)$\",\n                    RedirectView.as_view(\n                        url=settings.BASE_URL + \"api/documents/%(pk)s/download/\",\n                    ),\n                ),\n                re_path(\n                    r\"^thumb/(?P<pk>\\d+)$\",\n                    RedirectView.as_view(\n                        url=settings.BASE_URL + \"api/documents/%(pk)s/thumb/\",\n                    ),\n                ),\n                re_path(\n                    r\"^preview/(?P<pk>\\d+)$\",\n                    RedirectView.as_view(\n                        url=settings.BASE_URL + \"api/documents/%(pk)s/preview/\",\n                    ),\n                ),\n            ],\n        ),\n    ),\n    re_path(\n        r\"^push$\",\n        csrf_exempt(\n            RedirectView.as_view(\n                url=settings.BASE_URL + \"api/documents/post_document/\",\n            ),\n        ),\n    ),\n    # Frontend assets TODO: this is pretty bad, but it works.\n    path(\n        \"assets/<path:path>\",\n        RedirectView.as_view(\n            url=settings.STATIC_URL + \"frontend/en-US/assets/%(path)s\",\n        ),\n        # TODO: with localization, this is even worse! :/\n    ),\n    # App logo\n    re_path(\n        r\"^logo(?P<path>.*)$\",\n        serve,\n        kwargs={\"document_root\": os.path.join(settings.MEDIA_ROOT, \"logo\")},\n    ),\n    # login, logout\n    path(\"accounts/\", include(\"allauth.urls\")),\n    # Root of the Frontend\n    re_path(\n        r\".*\",\n        login_required(ensure_csrf_cookie(IndexView.as_view())),\n        name=\"base\",\n    ),\n]\n\n\nwebsocket_urlpatterns = [\n    path(settings.BASE_URL.lstrip(\"/\") + \"ws/status/\", StatusConsumer.as_asgi()),\n]\n\n# Text in each page's <h1> (and above login form).\nadmin.site.site_header = \"Paperless-ngx\"\n# Text at the end of each page's <title>.\nadmin.site.site_title = \"Paperless-ngx\"\n# Text at the top of the admin index page.\nadmin.site.index_title = _(\"Paperless-ngx administration\")\n", "path": "src/paperless/urls.py"}, {"content": "from allauth.account.adapter import DefaultAccountAdapter\nfrom allauth.core import context\nfrom allauth.socialaccount.adapter import DefaultSocialAccountAdapter\nfrom django.conf import settings\nfrom django.urls import reverse\n\n\nclass CustomAccountAdapter(DefaultAccountAdapter):\n    def is_open_for_signup(self, request):\n        allow_signups = super().is_open_for_signup(request)\n        # Override with setting, otherwise default to super.\n        return getattr(settings, \"ACCOUNT_ALLOW_SIGNUPS\", allow_signups)\n\n    def is_safe_url(self, url):\n        # see https://github.com/paperless-ngx/paperless-ngx/issues/5780\n        from django.utils.http import url_has_allowed_host_and_scheme\n\n        # get_host already validates the given host, so no need to check it again\n        allowed_hosts = {context.request.get_host()} | set(settings.ALLOWED_HOSTS)\n\n        if \"*\" in allowed_hosts:\n            # dont allow wildcard to allow urls from any host\n            allowed_hosts.remove(\"*\")\n            allowed_hosts.add(context.request.get_host())\n            return url_has_allowed_host_and_scheme(url, allowed_hosts=allowed_hosts)\n\n        return url_has_allowed_host_and_scheme(url, allowed_hosts=allowed_hosts)\n\n\nclass CustomSocialAccountAdapter(DefaultSocialAccountAdapter):\n    def is_open_for_signup(self, request, sociallogin):\n        allow_signups = super().is_open_for_signup(request, sociallogin)\n        # Override with setting, otherwise default to super.\n        return getattr(settings, \"SOCIALACCOUNT_ALLOW_SIGNUPS\", allow_signups)\n\n    def get_connect_redirect_url(self, request, socialaccount):\n        \"\"\"\n        Returns the default URL to redirect to after successfully\n        connecting a social account.\n        \"\"\"\n        url = reverse(\"base\")\n        return url\n\n    def populate_user(self, request, sociallogin, data):\n        # TODO: If default global permissions are implemented, should also be here\n        return super().populate_user(request, sociallogin, data)  # pragma: no cover\n", "path": "src/paperless/adapter.py"}]}