mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-10-30 03:56:23 -05:00 
			
		
		
		
	update API access for logs
This commit is contained in:
		| @@ -153,19 +153,6 @@ class DocumentSerializer(DynamicFieldsModelSerializer): | ||||
|         ) | ||||
|  | ||||
|  | ||||
| class LogSerializer(serializers.ModelSerializer): | ||||
|  | ||||
|     class Meta: | ||||
|         model = Log | ||||
|         fields = ( | ||||
|             "id", | ||||
|             "created", | ||||
|             "message", | ||||
|             "group", | ||||
|             "level" | ||||
|         ) | ||||
|  | ||||
|  | ||||
| class SavedViewFilterRuleSerializer(serializers.ModelSerializer): | ||||
|  | ||||
|     class Meta: | ||||
|   | ||||
| @@ -4,7 +4,9 @@ import shutil | ||||
| import tempfile | ||||
| from unittest import mock | ||||
|  | ||||
| from django.conf import settings | ||||
| from django.contrib.auth.models import User | ||||
| from django.test import override_settings | ||||
| from rest_framework.test import APITestCase | ||||
| from whoosh.writing import AsyncWriter | ||||
|  | ||||
| @@ -717,6 +719,28 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): | ||||
|         v1 = SavedView.objects.get(id=v1.id) | ||||
|         self.assertEqual(v1.filter_rules.count(), 0) | ||||
|  | ||||
|     def test_get_logs(self): | ||||
|         response = self.client.get("/api/logs/") | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertCountEqual(response.data, ["mail", "paperless"]) | ||||
|  | ||||
|     def test_get_invalid_log(self): | ||||
|         response = self.client.get("/api/logs/bogus_log/") | ||||
|         self.assertEqual(response.status_code, 404) | ||||
|  | ||||
|     @override_settings(LOGGING_DIR="bogus_dir") | ||||
|     def test_get_nonexistent_log(self): | ||||
|         response = self.client.get("/api/logs/paperless/") | ||||
|         self.assertEqual(response.status_code, 404) | ||||
|  | ||||
|     def test_get_log(self): | ||||
|         log_data = "test\ntest2\n" | ||||
|         with open(os.path.join(settings.LOGGING_DIR, "paperless.log"), "w") as f: | ||||
|             f.write(log_data) | ||||
|         response = self.client.get("/api/logs/paperless/") | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertListEqual(response.data, ["test", "test2"]) | ||||
|  | ||||
|  | ||||
| class TestBulkEdit(DirectoriesMixin, APITestCase): | ||||
|  | ||||
|   | ||||
| @@ -1,66 +0,0 @@ | ||||
| import logging | ||||
| import uuid | ||||
| from unittest import mock | ||||
|  | ||||
| from django.test import TestCase, override_settings | ||||
|  | ||||
| from ..models import Log | ||||
|  | ||||
|  | ||||
| class TestPaperlessLog(TestCase): | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         TestCase.__init__(self, *args, **kwargs) | ||||
|         self.logger = logging.getLogger( | ||||
|             "documents.management.commands.document_consumer") | ||||
|  | ||||
|     @override_settings(DISABLE_DBHANDLER=False) | ||||
|     def test_that_it_saves_at_all(self): | ||||
|  | ||||
|         kw = {"group": uuid.uuid4()} | ||||
|  | ||||
|         self.assertEqual(Log.objects.all().count(), 0) | ||||
|  | ||||
|         with mock.patch("logging.StreamHandler.emit") as __: | ||||
|  | ||||
|             # Debug messages are ignored by default | ||||
|             self.logger.debug("This is a debugging message", extra=kw) | ||||
|             self.assertEqual(Log.objects.all().count(), 1) | ||||
|  | ||||
|             self.logger.info("This is an informational message", extra=kw) | ||||
|             self.assertEqual(Log.objects.all().count(), 2) | ||||
|  | ||||
|             self.logger.warning("This is an warning message", extra=kw) | ||||
|             self.assertEqual(Log.objects.all().count(), 3) | ||||
|  | ||||
|             self.logger.error("This is an error message", extra=kw) | ||||
|             self.assertEqual(Log.objects.all().count(), 4) | ||||
|  | ||||
|             self.logger.critical("This is a critical message", extra=kw) | ||||
|             self.assertEqual(Log.objects.all().count(), 5) | ||||
|  | ||||
|     @override_settings(DISABLE_DBHANDLER=False) | ||||
|     def test_groups(self): | ||||
|  | ||||
|         kw1 = {"group": uuid.uuid4()} | ||||
|         kw2 = {"group": uuid.uuid4()} | ||||
|  | ||||
|         self.assertEqual(Log.objects.all().count(), 0) | ||||
|  | ||||
|         with mock.patch("logging.StreamHandler.emit") as __: | ||||
|  | ||||
|             self.logger.info("This is an informational message", extra=kw2) | ||||
|             self.assertEqual(Log.objects.all().count(), 1) | ||||
|             self.assertEqual(Log.objects.filter(group=kw2["group"]).count(), 1) | ||||
|  | ||||
|             self.logger.warning("This is an warning message", extra=kw1) | ||||
|             self.assertEqual(Log.objects.all().count(), 2) | ||||
|             self.assertEqual(Log.objects.filter(group=kw1["group"]).count(), 1) | ||||
|  | ||||
|             self.logger.error("This is an error message", extra=kw2) | ||||
|             self.assertEqual(Log.objects.all().count(), 3) | ||||
|             self.assertEqual(Log.objects.filter(group=kw2["group"]).count(), 2) | ||||
|  | ||||
|             self.logger.critical("This is a critical message", extra=kw1) | ||||
|             self.assertEqual(Log.objects.all().count(), 4) | ||||
|             self.assertEqual(Log.objects.filter(group=kw1["group"]).count(), 2) | ||||
| @@ -19,12 +19,15 @@ def setup_directories(): | ||||
|     dirs.originals_dir = os.path.join(dirs.media_dir, "documents", "originals") | ||||
|     dirs.thumbnail_dir = os.path.join(dirs.media_dir, "documents", "thumbnails") | ||||
|     dirs.archive_dir = os.path.join(dirs.media_dir, "documents", "archive") | ||||
|     dirs.logging_dir = os.path.join(dirs.data_dir, "log") | ||||
|  | ||||
|     os.makedirs(dirs.index_dir, exist_ok=True) | ||||
|     os.makedirs(dirs.originals_dir, exist_ok=True) | ||||
|     os.makedirs(dirs.thumbnail_dir, exist_ok=True) | ||||
|     os.makedirs(dirs.archive_dir, exist_ok=True) | ||||
|  | ||||
|     os.makedirs(dirs.logging_dir, exist_ok=True) | ||||
|  | ||||
|     dirs.settings_override = override_settings( | ||||
|         DATA_DIR=dirs.data_dir, | ||||
|         SCRATCH_DIR=dirs.scratch_dir, | ||||
| @@ -33,6 +36,7 @@ def setup_directories(): | ||||
|         THUMBNAIL_DIR=dirs.thumbnail_dir, | ||||
|         ARCHIVE_DIR=dirs.archive_dir, | ||||
|         CONSUMPTION_DIR=dirs.consumption_dir, | ||||
|         LOGGING_DIR=dirs.logging_dir, | ||||
|         INDEX_DIR=dirs.index_dir, | ||||
|         MODEL_FILE=os.path.join(dirs.data_dir, "classification_model.pickle"), | ||||
|         MEDIA_LOCK=os.path.join(dirs.media_dir, "media.lock") | ||||
|   | ||||
| @@ -29,7 +29,7 @@ from rest_framework.views import APIView | ||||
| from rest_framework.viewsets import ( | ||||
|     GenericViewSet, | ||||
|     ModelViewSet, | ||||
|     ReadOnlyModelViewSet | ||||
|     ViewSet | ||||
| ) | ||||
|  | ||||
| import documents.index as index | ||||
| @@ -40,16 +40,14 @@ from .filters import ( | ||||
|     CorrespondentFilterSet, | ||||
|     DocumentFilterSet, | ||||
|     TagFilterSet, | ||||
|     DocumentTypeFilterSet, | ||||
|     LogFilterSet | ||||
|     DocumentTypeFilterSet | ||||
| ) | ||||
| from .matching import match_correspondents, match_tags, match_document_types | ||||
| from .models import Correspondent, Document, Log, Tag, DocumentType, SavedView | ||||
| from .models import Correspondent, Document, Tag, DocumentType, SavedView | ||||
| from .parsers import get_parser_class_for_mime_type | ||||
| from .serialisers import ( | ||||
|     CorrespondentSerializer, | ||||
|     DocumentSerializer, | ||||
|     LogSerializer, | ||||
|     TagSerializer, | ||||
|     DocumentTypeSerializer, | ||||
|     PostDocumentSerializer, | ||||
| @@ -307,16 +305,28 @@ class DocumentViewSet(RetrieveModelMixin, | ||||
|             raise Http404() | ||||
|  | ||||
|  | ||||
| class LogViewSet(ReadOnlyModelViewSet): | ||||
|     model = Log | ||||
| class LogViewSet(ViewSet): | ||||
|  | ||||
|     queryset = Log.objects.all() | ||||
|     serializer_class = LogSerializer | ||||
|     pagination_class = StandardPagination | ||||
|     permission_classes = (IsAuthenticated,) | ||||
|     filter_backends = (DjangoFilterBackend, OrderingFilter) | ||||
|     filterset_class = LogFilterSet | ||||
|     ordering_fields = ("created",) | ||||
|  | ||||
|     log_files = ["paperless", "mail"] | ||||
|  | ||||
|     def retrieve(self, request, pk=None, *args, **kwargs): | ||||
|         if not pk in self.log_files: | ||||
|             raise Http404() | ||||
|  | ||||
|         filename = os.path.join(settings.LOGGING_DIR, f"{pk}.log") | ||||
|  | ||||
|         if not os.path.isfile(filename): | ||||
|             raise Http404() | ||||
|  | ||||
|         with open(filename, "r") as f: | ||||
|             lines = [l.rstrip() for l in f.readlines()] | ||||
|  | ||||
|         return Response(lines) | ||||
|  | ||||
|     def list(self, request, *args, **kwargs): | ||||
|         return Response(self.log_files) | ||||
|  | ||||
|  | ||||
| class SavedViewViewSet(ModelViewSet): | ||||
|   | ||||
| @@ -31,7 +31,7 @@ api_router = DefaultRouter() | ||||
| api_router.register(r"correspondents", CorrespondentViewSet) | ||||
| api_router.register(r"document_types", DocumentTypeViewSet) | ||||
| api_router.register(r"documents", DocumentViewSet) | ||||
| api_router.register(r"logs", LogViewSet) | ||||
| api_router.register(r"logs", LogViewSet, basename="logs") | ||||
| api_router.register(r"tags", TagViewSet) | ||||
| api_router.register(r"saved_views", SavedViewViewSet) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 jonaswinkler
					jonaswinkler