From 37f8a775165e9d0ccaa1618045e3bc7cc083cb89 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Sun, 24 Nov 2024 12:06:31 -0800 Subject: [PATCH] Chore: cleanup urls, use actions for some views (#8346) --- src/documents/views.py | 23 +++---- src/paperless/urls.py | 118 +++++++++++++++++++----------------- src/paperless_mail/views.py | 33 +++++----- 3 files changed, 91 insertions(+), 83 deletions(-) diff --git a/src/documents/views.py b/src/documents/views.py index 332d5f64a..35fa8eafc 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -1546,6 +1546,12 @@ class StoragePathViewSet(ModelViewSet, PermissionsAwareDocumentCountMixin): filterset_class = StoragePathFilterSet ordering_fields = ("name", "path", "matching_algorithm", "match", "document_count") + def get_permissions(self): + if self.action == "test": + # Test action does not require object level permissions + self.permission_classes = (IsAuthenticated,) + return super().get_permissions() + def destroy(self, request, *args, **kwargs): """ When a storage path is deleted, see if documents @@ -1562,17 +1568,12 @@ class StoragePathViewSet(ModelViewSet, PermissionsAwareDocumentCountMixin): return response - -class StoragePathTestView(GenericAPIView): - """ - Test storage path against a document - """ - - permission_classes = [IsAuthenticated] - serializer_class = StoragePathTestSerializer - - def post(self, request, *args, **kwargs): - serializer = self.get_serializer(data=request.data) + @action(methods=["post"], detail=False) + def test(self, request): + """ + Test storage path against a document + """ + serializer = StoragePathTestSerializer(data=request.data) serializer.is_valid(raise_exception=True) document = serializer.validated_data.get("document") diff --git a/src/paperless/urls.py b/src/paperless/urls.py index 5b7327b8d..c528c5e2a 100644 --- a/src/paperless/urls.py +++ b/src/paperless/urls.py @@ -11,7 +11,6 @@ from django.contrib.auth.decorators import login_required from django.urls import path from django.urls import re_path from django.utils.translation import gettext_lazy as _ -from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import ensure_csrf_cookie from django.views.generic import RedirectView from django.views.static import serve @@ -35,7 +34,6 @@ from documents.views import SelectionDataView from documents.views import SharedLinkView from documents.views import ShareLinkViewSet from documents.views import StatisticsView -from documents.views import StoragePathTestView from documents.views import StoragePathViewSet from documents.views import SystemStatusView from documents.views import TagViewSet @@ -56,7 +54,6 @@ from paperless.views import ProfileView from paperless.views import SocialAccountProvidersView from paperless.views import TOTPView from paperless.views import UserViewSet -from paperless_mail.views import MailAccountTestView from paperless_mail.views import MailAccountViewSet from paperless_mail.views import MailRuleViewSet from paperless_mail.views import OauthCallbackView @@ -94,58 +91,83 @@ urlpatterns = [ namespace="rest_framework", ), ), - re_path( - "^search/autocomplete/", - SearchAutoCompleteView.as_view(), - name="autocomplete", - ), re_path( "^search/", - GlobalSearchView.as_view(), - name="global_search", - ), - re_path("^statistics/", StatisticsView.as_view(), name="statistics"), - re_path( - "^documents/post_document/", - PostDocumentView.as_view(), - name="post_document", + include( + [ + re_path( + "^$", + GlobalSearchView.as_view(), + name="global_search", + ), + re_path( + "^autocomplete/", + SearchAutoCompleteView.as_view(), + name="autocomplete", + ), + ], + ), ), re_path( - "^documents/bulk_edit/", - BulkEditView.as_view(), - name="bulk_edit", + "^statistics/", + StatisticsView.as_view(), + name="statistics", ), re_path( - "^documents/selection_data/", - SelectionDataView.as_view(), - name="selection_data", + "^documents/", + include( + [ + re_path( + "^post_document/", + PostDocumentView.as_view(), + name="post_document", + ), + re_path( + "^bulk_edit/", + BulkEditView.as_view(), + name="bulk_edit", + ), + re_path( + "^bulk_download/", + BulkDownloadView.as_view(), + name="bulk_download", + ), + re_path( + "^selection_data/", + SelectionDataView.as_view(), + name="selection_data", + ), + ], + ), ), - re_path( - "^documents/bulk_download/", - BulkDownloadView.as_view(), - name="bulk_download", - ), - re_path( - "^remote_version/", - RemoteVersionView.as_view(), - name="remoteversion", - ), - re_path("^ui_settings/", UiSettingsView.as_view(), name="ui_settings"), - re_path( - "^mail_accounts/test/", - MailAccountTestView.as_view(), - name="mail_accounts_test", - ), - path("token/", views.obtain_auth_token), re_path( "^bulk_edit_objects/", BulkEditObjectsView.as_view(), name="bulk_edit_objects", ), + re_path( + "^remote_version/", + RemoteVersionView.as_view(), + name="remoteversion", + ), + re_path( + "^ui_settings/", + UiSettingsView.as_view(), + name="ui_settings", + ), + path( + "token/", + views.obtain_auth_token, + ), re_path( "^profile/", include( [ + re_path( + "^$", + ProfileView.as_view(), + name="profile_view", + ), path( "generate_auth_token/", GenerateAuthTokenView.as_view(), @@ -158,11 +180,6 @@ urlpatterns = [ "social_account_providers/", SocialAccountProvidersView.as_view(), ), - re_path( - "^$", - ProfileView.as_view(), - name="profile_view", - ), path( "totp/", TOTPView.as_view(), @@ -181,11 +198,6 @@ urlpatterns = [ TrashView.as_view(), name="trash", ), - re_path( - "^storage_paths/test/", - StoragePathTestView.as_view(), - name="storage_paths_test", - ), re_path( r"^oauth/callback/", OauthCallbackView.as_view(), @@ -223,14 +235,6 @@ urlpatterns = [ ], ), ), - re_path( - r"^push$", - csrf_exempt( - RedirectView.as_view( - url=settings.BASE_URL + "api/documents/post_document/", - ), - ), - ), # Frontend assets TODO: this is pretty bad, but it works. path( "assets/", diff --git a/src/paperless_mail/views.py b/src/paperless_mail/views.py index 745ecb5fb..724d8e91e 100644 --- a/src/paperless_mail/views.py +++ b/src/paperless_mail/views.py @@ -6,6 +6,7 @@ from django.http import HttpResponseBadRequest from django.http import HttpResponseRedirect from django.utils import timezone from httpx_oauth.oauth2 import GetAccessTokenError +from rest_framework.decorators import action from rest_framework.generics import GenericAPIView from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response @@ -34,22 +35,14 @@ class MailAccountViewSet(ModelViewSet, PassUserMixin): permission_classes = (IsAuthenticated, PaperlessObjectPermissions) filter_backends = (ObjectOwnedOrGrantedPermissionsFilter,) + def get_permissions(self): + if self.action == "test": + # Test action does not require object level permissions + self.permission_classes = (IsAuthenticated,) + return super().get_permissions() -class MailRuleViewSet(ModelViewSet, PassUserMixin): - model = MailRule - - queryset = MailRule.objects.all().order_by("order") - serializer_class = MailRuleSerializer - pagination_class = StandardPagination - permission_classes = (IsAuthenticated, PaperlessObjectPermissions) - filter_backends = (ObjectOwnedOrGrantedPermissionsFilter,) - - -class MailAccountTestView(GenericAPIView): - permission_classes = (IsAuthenticated,) - serializer_class = MailAccountSerializer - - def post(self, request, *args, **kwargs): + @action(methods=["post"], detail=False) + def test(self, request): logger = logging.getLogger("paperless_mail") request.data["name"] = datetime.datetime.now().isoformat() serializer = self.get_serializer(data=request.data) @@ -95,6 +88,16 @@ class MailAccountTestView(GenericAPIView): return HttpResponseBadRequest("Unable to connect to server") +class MailRuleViewSet(ModelViewSet, PassUserMixin): + model = MailRule + + queryset = MailRule.objects.all().order_by("order") + serializer_class = MailRuleSerializer + pagination_class = StandardPagination + permission_classes = (IsAuthenticated, PaperlessObjectPermissions) + filter_backends = (ObjectOwnedOrGrantedPermissionsFilter,) + + class OauthCallbackView(GenericAPIView): permission_classes = (IsAuthenticated,)