Coverage for paperless/urls.py: 100%
96 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 09:07 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 09:07 +0000
1from allauth.account import views as allauth_account_views
2from allauth.account.decorators import secure_admin_login
3from allauth.mfa.base import views as allauth_mfa_views
4from allauth.socialaccount import views as allauth_social_account_views
5from allauth.urls import build_provider_urlpatterns
6from django.conf import settings
7from django.conf.urls import include
8from django.contrib import admin
9from django.contrib.auth.decorators import login_required
10from django.urls import path
11from django.urls import re_path
12from django.utils.translation import gettext_lazy as _
13from django.views.decorators.csrf import ensure_csrf_cookie
14from django.views.generic import RedirectView
15from drf_spectacular.views import SpectacularAPIView
16from drf_spectacular.views import SpectacularSwaggerView
17from rest_framework.routers import DefaultRouter
19from documents.views import BulkDownloadView
20from documents.views import BulkEditObjectsView
21from documents.views import BulkEditView
22from documents.views import ChatStreamingView
23from documents.views import CorrespondentViewSet
24from documents.views import CustomFieldViewSet
25from documents.views import DeleteDocumentsView
26from documents.views import DocumentTypeViewSet
27from documents.views import EditPdfDocumentsView
28from documents.views import GlobalSearchView
29from documents.views import IndexView
30from documents.views import LogViewSet
31from documents.views import MergeDocumentsAsVersionsView
32from documents.views import MergeDocumentsView
33from documents.views import PostDocumentView
34from documents.views import RemoteVersionView
35from documents.views import RemovePasswordDocumentsView
36from documents.views import ReprocessDocumentsView
37from documents.views import RotateDocumentsView
38from documents.views import SavedViewViewSet
39from documents.views import SearchAutoCompleteView
40from documents.views import SelectionDataView
41from documents.views import SharedLinkView
42from documents.views import ShareLinkBundleViewSet
43from documents.views import ShareLinkViewSet
44from documents.views import StatisticsView
45from documents.views import StoragePathViewSet
46from documents.views import SystemStatusView
47from documents.views import TagViewSet
48from documents.views import TasksViewSet
49from documents.views import TrashView
50from documents.views import UiSettingsView
51from documents.views import UnifiedSearchViewSet
52from documents.views import WorkflowActionViewSet
53from documents.views import WorkflowTriggerViewSet
54from documents.views import WorkflowViewSet
55from documents.views import serve_logo
56from paperless.consumers import StatusConsumer
57from paperless.views import ApplicationConfigurationViewSet
58from paperless.views import DisconnectSocialAccountView
59from paperless.views import FaviconView
60from paperless.views import GenerateAuthTokenView
61from paperless.views import GroupViewSet
62from paperless.views import PaperlessObtainAuthTokenView
63from paperless.views import ProfileView
64from paperless.views import SocialAccountProvidersView
65from paperless.views import TOTPView
66from paperless.views import UserViewSet
67from paperless_mail.views import MailAccountViewSet
68from paperless_mail.views import MailRuleViewSet
69from paperless_mail.views import OauthCallbackView
70from paperless_mail.views import ProcessedMailViewSet
72admin.site.login = secure_admin_login(admin.site.login)
74api_router = DefaultRouter()
75api_router.register(r"correspondents", CorrespondentViewSet)
76api_router.register(r"document_types", DocumentTypeViewSet)
77api_router.register(r"documents", UnifiedSearchViewSet)
78api_router.register(r"logs", LogViewSet, basename="logs")
79api_router.register(r"tags", TagViewSet)
80api_router.register(r"saved_views", SavedViewViewSet)
81api_router.register(r"storage_paths", StoragePathViewSet)
82api_router.register(r"tasks", TasksViewSet, basename="tasks")
83api_router.register(r"users", UserViewSet, basename="users")
84api_router.register(r"groups", GroupViewSet, basename="groups")
85api_router.register(r"mail_accounts", MailAccountViewSet)
86api_router.register(r"mail_rules", MailRuleViewSet)
87api_router.register(r"share_link_bundles", ShareLinkBundleViewSet)
88api_router.register(r"share_links", ShareLinkViewSet)
89api_router.register(r"workflow_triggers", WorkflowTriggerViewSet)
90api_router.register(r"workflow_actions", WorkflowActionViewSet)
91api_router.register(r"workflows", WorkflowViewSet)
92api_router.register(r"custom_fields", CustomFieldViewSet)
93api_router.register(r"config", ApplicationConfigurationViewSet)
94api_router.register(r"processed_mail", ProcessedMailViewSet)
97urlpatterns = [
98 re_path(
99 r"^api/",
100 include(
101 [
102 re_path(
103 "^auth/",
104 include(
105 (
106 [
107 path(
108 "login/",
109 allauth_account_views.login,
110 name="login",
111 ),
112 path(
113 "logout/",
114 allauth_account_views.logout,
115 name="logout",
116 ),
117 ],
118 "rest_framework",
119 ),
120 namespace="rest_framework",
121 ),
122 ),
123 re_path(
124 "^search/",
125 include(
126 [
127 re_path(
128 "^$",
129 GlobalSearchView.as_view(),
130 name="global_search",
131 ),
132 re_path(
133 "^autocomplete/",
134 SearchAutoCompleteView.as_view(),
135 name="autocomplete",
136 ),
137 ],
138 ),
139 ),
140 re_path(
141 "^statistics/",
142 StatisticsView.as_view(),
143 name="statistics",
144 ),
145 re_path(
146 "^documents/",
147 include(
148 [
149 re_path(
150 "^post_document/",
151 PostDocumentView.as_view(),
152 name="post_document",
153 ),
154 re_path(
155 "^bulk_edit/",
156 BulkEditView.as_view(),
157 name="bulk_edit",
158 ),
159 re_path(
160 "^delete/",
161 DeleteDocumentsView.as_view(),
162 name="delete_documents",
163 ),
164 re_path(
165 "^reprocess/",
166 ReprocessDocumentsView.as_view(),
167 name="reprocess_documents",
168 ),
169 re_path(
170 "^rotate/",
171 RotateDocumentsView.as_view(),
172 name="rotate_documents",
173 ),
174 re_path(
175 "^merge/",
176 MergeDocumentsView.as_view(),
177 name="merge_documents",
178 ),
179 re_path(
180 "^merge_as_versions/",
181 MergeDocumentsAsVersionsView.as_view(),
182 name="merge_documents_as_versions",
183 ),
184 re_path(
185 "^edit_pdf/",
186 EditPdfDocumentsView.as_view(),
187 name="edit_pdf_documents",
188 ),
189 re_path(
190 "^remove_password/",
191 RemovePasswordDocumentsView.as_view(),
192 name="remove_password_documents",
193 ),
194 re_path(
195 "^bulk_download/",
196 BulkDownloadView.as_view(),
197 name="bulk_download",
198 ),
199 re_path(
200 "^selection_data/",
201 SelectionDataView.as_view(),
202 name="selection_data",
203 ),
204 re_path(
205 "^chat/",
206 ChatStreamingView.as_view(),
207 name="chat_streaming_view",
208 ),
209 ],
210 ),
211 ),
212 re_path(
213 "^bulk_edit_objects/",
214 BulkEditObjectsView.as_view(),
215 name="bulk_edit_objects",
216 ),
217 re_path(
218 "^remote_version/",
219 RemoteVersionView.as_view(),
220 name="remoteversion",
221 ),
222 re_path(
223 "^ui_settings/",
224 UiSettingsView.as_view(),
225 name="ui_settings",
226 ),
227 path(
228 "token/",
229 PaperlessObtainAuthTokenView.as_view(),
230 ),
231 re_path(
232 "^profile/",
233 include(
234 [
235 re_path(
236 "^$",
237 ProfileView.as_view(),
238 name="profile_view",
239 ),
240 path(
241 "generate_auth_token/",
242 GenerateAuthTokenView.as_view(),
243 ),
244 path(
245 "disconnect_social_account/",
246 DisconnectSocialAccountView.as_view(),
247 ),
248 path(
249 "social_account_providers/",
250 SocialAccountProvidersView.as_view(),
251 ),
252 path(
253 "totp/",
254 TOTPView.as_view(),
255 name="totp_view",
256 ),
257 ],
258 ),
259 ),
260 re_path(
261 "^status/",
262 SystemStatusView.as_view(),
263 name="system_status",
264 ),
265 re_path(
266 "^trash/",
267 TrashView.as_view(),
268 name="trash",
269 ),
270 re_path(
271 r"^oauth/callback/",
272 OauthCallbackView.as_view(),
273 name="oauth_callback",
274 ),
275 re_path(
276 "^schema/",
277 include(
278 [
279 re_path(
280 "^$",
281 SpectacularAPIView.as_view(),
282 name="schema",
283 ),
284 re_path(
285 "^view/",
286 SpectacularSwaggerView.as_view(),
287 name="swagger-ui",
288 ),
289 ],
290 ),
291 ),
292 re_path("^auth/headless/", include("allauth.headless.urls")),
293 re_path(
294 "^$", # Redirect to the API swagger view
295 RedirectView.as_view(url="schema/view/"),
296 ),
297 *api_router.urls,
298 ],
299 ),
300 ),
301 re_path(r"^share/(?P<slug>\w+)/?$", SharedLinkView.as_view()),
302 re_path(r"^favicon.ico$", FaviconView.as_view(), name="favicon"),
303 re_path(r"^admin/", admin.site.urls),
304 re_path(
305 r"^fetch/",
306 include(
307 [
308 re_path(
309 r"^doc/(?P<pk>\d+)$",
310 RedirectView.as_view(
311 url=settings.BASE_URL + "api/documents/%(pk)s/download/",
312 ),
313 ),
314 re_path(
315 r"^thumb/(?P<pk>\d+)$",
316 RedirectView.as_view(
317 url=settings.BASE_URL + "api/documents/%(pk)s/thumb/",
318 ),
319 ),
320 re_path(
321 r"^preview/(?P<pk>\d+)$",
322 RedirectView.as_view(
323 url=settings.BASE_URL + "api/documents/%(pk)s/preview/",
324 ),
325 ),
326 ],
327 ),
328 ),
329 # Frontend assets TODO: this is pretty bad, but it works.
330 path(
331 "assets/<path:path>",
332 RedirectView.as_view(
333 url=settings.STATIC_URL + "frontend/en-US/assets/%(path)s",
334 ),
335 # TODO: with localization, this is even worse! :/
336 ),
337 # App logo
338 re_path(r"^logo(?:/(?P<filename>.+))?/?$", serve_logo, name="app_logo"),
339 # allauth
340 path(
341 "accounts/",
342 include(
343 [
344 # see allauth/account/urls.py
345 # login, logout, signup, account_inactive
346 path("login/", allauth_account_views.login, name="account_login"),
347 path("logout/", allauth_account_views.logout, name="account_logout"),
348 path("signup/", allauth_account_views.signup, name="account_signup"),
349 path(
350 "account_inactive/",
351 allauth_account_views.account_inactive,
352 name="account_inactive",
353 ),
354 # password reset
355 path(
356 "password/",
357 include(
358 [
359 path(
360 "reset/",
361 allauth_account_views.password_reset,
362 name="account_reset_password",
363 ),
364 path(
365 "reset/done/",
366 allauth_account_views.password_reset_done,
367 name="account_reset_password_done",
368 ),
369 path(
370 "reset/key/done/",
371 allauth_account_views.password_reset_from_key_done,
372 name="account_reset_password_from_key_done",
373 ),
374 ],
375 ),
376 ),
377 re_path(
378 r"^confirm-email/(?P<key>[-:\w]+)/$",
379 allauth_account_views.ConfirmEmailView.as_view(),
380 name="account_confirm_email",
381 ),
382 re_path(
383 r"^password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$",
384 allauth_account_views.password_reset_from_key,
385 name="account_reset_password_from_key",
386 ),
387 # social account base urls, see allauth/socialaccount/urls.py
388 path(
389 "3rdparty/",
390 include(
391 [
392 path(
393 "login/cancelled/",
394 allauth_social_account_views.login_cancelled,
395 name="socialaccount_login_cancelled",
396 ),
397 path(
398 "login/error/",
399 allauth_social_account_views.login_error,
400 name="socialaccount_login_error",
401 ),
402 path(
403 "signup/",
404 allauth_social_account_views.signup,
405 name="socialaccount_signup",
406 ),
407 ],
408 ),
409 ),
410 *build_provider_urlpatterns(),
411 # mfa, see allauth/mfa/base/urls.py
412 path(
413 "2fa/authenticate/",
414 allauth_mfa_views.authenticate,
415 name="mfa_authenticate",
416 ),
417 ],
418 ),
419 ),
420 # Root of the Frontend
421 re_path(
422 r".*",
423 login_required(ensure_csrf_cookie(IndexView.as_view())),
424 name="base",
425 ),
426]
429websocket_urlpatterns = [
430 path("ws/status/", StatusConsumer.as_asgi()),
431]
433# Text in each page's <h1> (and above login form).
434admin.site.site_header = "Paperless-ngx"
435# Text at the end of each page's <title>.
436admin.site.site_title = "Paperless-ngx"
437# Text at the top of the admin index page.
438admin.site.index_title = _("Paperless-ngx administration")