Coverage for paperless/urls.py: 100%

96 statements  

« 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 

18 

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 

71 

72admin.site.login = secure_admin_login(admin.site.login) 

73 

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) 

95 

96 

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] 

427 

428 

429websocket_urlpatterns = [ 

430 path("ws/status/", StatusConsumer.as_asgi()), 

431] 

432 

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")