diff --git a/edivorce/apps/core/models.py b/edivorce/apps/core/models.py index b65401b5..39d186f1 100644 --- a/edivorce/apps/core/models.py +++ b/edivorce/apps/core/models.py @@ -177,6 +177,10 @@ class Document(models.Model): q = Document.objects.filter(bceid_user=self.bceid_user, doc_type=self.doc_type, party_code=self.party_code, sort_order__gt=self.sort_order) q.update(sort_order=F('sort_order') - 1) + @staticmethod + def get_file(file_key): + return redis.RedisStorage().open(file_key) + class DontLog: def log_addition(self, *args): diff --git a/edivorce/apps/core/tests/test_logic.py b/edivorce/apps/core/tests/test_logic.py index 2eb0ac8c..f40c7186 100644 --- a/edivorce/apps/core/tests/test_logic.py +++ b/edivorce/apps/core/tests/test_logic.py @@ -5,6 +5,7 @@ from django.test import TestCase from edivorce.apps.core.models import BceidUser, UserResponse from edivorce.apps.core.utils.conditional_logic import get_cleaned_response_value, get_num_children_living_with from edivorce.apps.core.utils.user_response import get_data_for_user +from edivorce.apps.core.views.api import _content_type_from_filename class ConditionalLogicTestCase(TestCase): @@ -51,3 +52,24 @@ class ConditionalLogicTestCase(TestCase): self.assertEqual(get_num_children_living_with(self.questions_dict, 'Lives with you'), '1') self.assertEqual(get_num_children_living_with(self.questions_dict, 'Lives with spouse'), '2') self.assertEqual(get_num_children_living_with(self.questions_dict, 'Lives with both'), '3') + + +class ViewLogic(TestCase): + def test_content_type_from_filename(self): + self.assertEqual(_content_type_from_filename('test_file1.pdf'), 'application/pdf') + self.assertEqual(_content_type_from_filename('redis_key_test_file1_pdf'), 'application/pdf') + self.assertEqual(_content_type_from_filename('test_file2.png'), 'image/png') + self.assertEqual(_content_type_from_filename('redis_key_test_file2_png'), 'image/png') + self.assertEqual(_content_type_from_filename('Test File 3.GIF'), 'image/gif') + self.assertEqual(_content_type_from_filename('redis_key_test_file_3_GIF'), 'image/gif') + self.assertEqual(_content_type_from_filename('Test_File--4.JPEG'), 'image/jpeg') + self.assertEqual(_content_type_from_filename('redis_key_test_file_4_jpeg'), 'image/jpeg') + self.assertEqual(_content_type_from_filename('TestFile5.jpe'), 'image/jpeg') + self.assertEqual(_content_type_from_filename('redis_key_test_file_5_jpe'), 'image/jpeg') + self.assertEqual(_content_type_from_filename('testFile6.jpeg'), 'image/jpeg') + self.assertEqual(_content_type_from_filename('redis_key_testfile_6_jpeg'), 'image/jpeg') + + with self.assertRaises(TypeError): + _content_type_from_filename('test_file7.HEIC') + with self.assertRaises(TypeError): + _content_type_from_filename('redis_key_testfile_7_svg') diff --git a/edivorce/apps/core/urls.py b/edivorce/apps/core/urls.py index 53e613f2..3a3b232a 100644 --- a/edivorce/apps/core/urls.py +++ b/edivorce/apps/core/urls.py @@ -9,6 +9,7 @@ urlpatterns = [ url(r'^api/documents/$', api.DocumentCreateView.as_view(), name='documents'), path('api/documents///', api.DocumentMetaDataView.as_view(), name='documents-meta'), path('api/documents////', api.DocumentView.as_view(), name='document'), + path('api/documents//', api.get_document_file_by_key, name='document_by_key'), # url(r'^login/headers$', system.headers), diff --git a/edivorce/apps/core/views/api.py b/edivorce/apps/core/views/api.py index e3bf3005..819e2c11 100644 --- a/edivorce/apps/core/views/api.py +++ b/edivorce/apps/core/views/api.py @@ -1,12 +1,13 @@ +import re + import graphene import graphene_django -from django.http import HttpResponse, HttpResponseGone +from django.http import Http404, HttpResponse, HttpResponseGone from graphql import GraphQLError from rest_framework import permissions, status from rest_framework.generics import CreateAPIView, ListAPIView, RetrieveUpdateDestroyAPIView from rest_framework.views import APIView from rest_framework.response import Response -from os.path import splitext from ..models import Document, Question from ..serializer import CreateDocumentSerializer, DocumentMetadataSerializer, UserResponseSerializer @@ -80,29 +81,43 @@ class DocumentView(RetrieveUpdateDestroyAPIView): def retrieve(self, request, *args, **kwargs): """ Return the file instead of meta data """ - doc = self.get_object() - - # Get the content-type based on the file extension - content_types = { - ".pdf": "application/pdf", - ".gif": "image/gif", - ".png": "image/png", - ".jpe": "image/jpeg", - ".jpg": "image/jpeg", - ".jpeg": "image/jpeg" - } - _, extension = splitext(doc.filename.lower()) - content_type = content_types[extension] + document = self.get_object() + content_type = _content_type_from_filename(document.filename) # If file doesn't exist anymore, delete it try: - file_contents = doc.file.read() + file_contents = document.file.read() except TypeError: - doc.delete() + document.delete() return HttpResponseGone('File no longer exists') return HttpResponse(file_contents, content_type=content_type) +def get_document_file_by_key(request, file_key): + file = Document.get_file(file_key) + content_type = _content_type_from_filename(file.name) + try: + return HttpResponse(file, content_type=content_type) + except TypeError: + raise Http404("File not found") + + +def _content_type_from_filename(filename): + content_types = { + "pdf": "application/pdf", + "gif": "image/gif", + "png": "image/png", + "jpe": "image/jpeg", + "jpg": "image/jpeg", + "jpeg": "image/jpeg" + } + extension = re.split(r'[\._]', filename.lower())[-1] + content_type = content_types.get(extension) + if not content_type: + raise TypeError(f'Filetype "{extension}" not supported') + return content_type + + class DocumentType(graphene_django.DjangoObjectType): file_url = graphene.String(source='get_file_url') diff --git a/edivorce/apps/poc/views.py b/edivorce/apps/poc/views.py index b6ac114a..69c8c566 100644 --- a/edivorce/apps/poc/views.py +++ b/edivorce/apps/poc/views.py @@ -60,6 +60,7 @@ class UploadStorage(CreateView): class UploadStorageDelete(DeleteView): model = Document success_url = settings.FORCE_SCRIPT_NAME + 'poc/storage' + template_name = 'poc/document_confirm_delete.html' def view_document_file(request, document_id):