46_MIME_Type_check_for_file_upload #47

Merged
mpeltriaux merged 2 commits from 46_MIME_Type_check_for_file_upload into master 3 years ago

@ -354,7 +354,7 @@ class NewDocumentForm(BaseModalForm):
file = forms.FileField( file = forms.FileField(
label=_("File"), label=_("File"),
label_suffix=_(""), label_suffix=_(""),
help_text=_("Must be smaller than 15 Mb"), help_text=_("Allowed formats: pdf, jpg, png. Max size 15 MB."),
widget=forms.FileInput( widget=forms.FileInput(
attrs={ attrs={
"class": "form-control-file", "class": "form-control-file",
@ -391,6 +391,28 @@ class NewDocumentForm(BaseModalForm):
if not self.document_model: if not self.document_model:
raise NotImplementedError("Unsupported document type for {}".format(self.instance.__class__)) raise NotImplementedError("Unsupported document type for {}".format(self.instance.__class__))
def is_valid(self):
super_valid = super().is_valid()
_file = self.cleaned_data.get("file", None)
mime_type_valid = self.document_model.is_mime_type_valid(_file)
if not mime_type_valid:
self.add_error(
"file",
_("Unsupported file type")
)
file_size_valid = self.document_model.is_file_size_valid(_file)
if not file_size_valid:
self.add_error(
"file",
_("File too large")
)
file_valid = mime_type_valid and file_size_valid
return super_valid and file_valid
def save(self): def save(self):
with transaction.atomic(): with transaction.atomic():
action = UserActionLogEntry.get_created_action(self.user) action = UserActionLogEntry.get_created_action(self.user)

@ -5,6 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 15.11.21 Created on: 15.11.21
""" """
import mimetypes
import os import os
from django.db import models from django.db import models
@ -62,6 +63,15 @@ class AbstractDocument(BaseResource):
file = models.FileField() file = models.FileField()
comment = models.TextField() comment = models.TextField()
_valid_mime_types = {
mimetypes.types_map[".pdf"],
mimetypes.types_map[".jpg"],
mimetypes.types_map[".jpeg"],
mimetypes.types_map[".png"],
}
# _maximum_file_size in MB
_maximum_file_size = 15
class Meta: class Meta:
abstract = True abstract = True
@ -82,3 +92,12 @@ class AbstractDocument(BaseResource):
pass pass
super().delete(using=using, keep_parents=keep_parents) super().delete(using=using, keep_parents=keep_parents)
@classmethod
def is_mime_type_valid(cls, _file: str):
mime_type = _file.content_type
return mime_type in cls._valid_mime_types
@classmethod
def is_file_size_valid(cls, _file):
max_size = cls._maximum_file_size * pow(1000, 2)
return _file.size <= max_size

@ -0,0 +1,73 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 09.12.21
"""
import mimetypes
from django.core.files.uploadedfile import InMemoryUploadedFile
from konova.models import AbstractDocument
from konova.tests.test_views import BaseTestCase
class TestCaseDocuments(BaseTestCase):
"""
Tests for the Documents functionalities
"""
@classmethod
def setUpTestData(cls):
""" Creates a test file in memory for using in further tests
Returns:
"""
super().setUpTestData()
cls.max_file_size = AbstractDocument._maximum_file_size * pow(1000, 2)
cls.test_file = InMemoryUploadedFile(
charset="utf-8",
name="test_file",
size=cls.max_file_size,
file=None,
content_type=None,
field_name=None
)
def test_allowed_mime_types(self):
""" Unit test for mime type validity checker
Checks that only as acceptable configured mime types of an AbstractDocument object will pass the
validity check.
Returns:
"""
accepted_mime_types = []
for file_ending, mime_type in mimetypes.types_map.items():
self.test_file.content_type = mime_type
valid = AbstractDocument.is_mime_type_valid(self.test_file)
if valid:
accepted_mime_types.append(mime_type)
accepted_mime_types = set(accepted_mime_types)
self.assertEqual(accepted_mime_types, AbstractDocument._valid_mime_types)
def test_max_file_size(self):
""" Unit test for maximum file size validity checker
Returns:
"""
# Test for exact maximum size
self.assertTrue(AbstractDocument.is_file_size_valid(self.test_file))
# Test for lower than maximum size
self.test_file.size = self.max_file_size - 1
self.assertTrue(AbstractDocument.is_file_size_valid(self.test_file))
# Test for larger than maximum size
self.test_file.size = self.max_file_size + 1
self.assertFalse(AbstractDocument.is_file_size_valid(self.test_file))

Binary file not shown.

@ -19,7 +19,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-17 14:27+0100\n" "POT-Creation-Date: 2021-12-09 12:36+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -1311,7 +1311,7 @@ msgstr "Datum des Widerspruchs"
msgid "Document" msgid "Document"
msgstr "Dokument" msgstr "Dokument"
#: intervention/forms/modalForms.py:140 konova/forms.py:357 #: intervention/forms/modalForms.py:140
msgid "Must be smaller than 15 Mb" msgid "Must be smaller than 15 Mb"
msgstr "Muss kleiner als 15 Mb sein" msgstr "Muss kleiner als 15 Mb sein"
@ -1333,7 +1333,7 @@ msgstr "Kompensationen und Zahlungen geprüft"
msgid "Run check" msgid "Run check"
msgstr "Prüfung vornehmen" msgstr "Prüfung vornehmen"
#: intervention/forms/modalForms.py:196 konova/forms.py:429 #: intervention/forms/modalForms.py:196 konova/forms.py:451
msgid "" msgid ""
"I, {} {}, confirm that all necessary control steps have been performed by " "I, {} {}, confirm that all necessary control steps have been performed by "
"myself." "myself."
@ -1559,27 +1559,39 @@ msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
msgid "File" msgid "File"
msgstr "Datei" msgstr "Datei"
#: konova/forms.py:397 #: konova/forms.py:357
msgid "Allowed formats: pdf, jpg, png. Max size 15 MB."
msgstr "Formate: pdf, jpg, png. Maximal 15 MB."
#: konova/forms.py:403
msgid "Unsupported file type"
msgstr "Dateiformat nicht unterstützt"
#: konova/forms.py:410
msgid "File too large"
msgstr "Datei zu groß"
#: konova/forms.py:419
msgid "Added document" msgid "Added document"
msgstr "Dokument hinzugefügt" msgstr "Dokument hinzugefügt"
#: konova/forms.py:420 #: konova/forms.py:442
msgid "Confirm record" msgid "Confirm record"
msgstr "Verzeichnen bestätigen" msgstr "Verzeichnen bestätigen"
#: konova/forms.py:428 #: konova/forms.py:450
msgid "Record data" msgid "Record data"
msgstr "Daten verzeichnen" msgstr "Daten verzeichnen"
#: konova/forms.py:435 #: konova/forms.py:457
msgid "Confirm unrecord" msgid "Confirm unrecord"
msgstr "Entzeichnen bestätigen" msgstr "Entzeichnen bestätigen"
#: konova/forms.py:436 #: konova/forms.py:458
msgid "Unrecord data" msgid "Unrecord data"
msgstr "Daten entzeichnen" msgstr "Daten entzeichnen"
#: konova/forms.py:437 #: konova/forms.py:459
msgid "I, {} {}, confirm that this data must be unrecorded." msgid "I, {} {}, confirm that this data must be unrecorded."
msgstr "" msgstr ""
"Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen." "Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen."
@ -3182,6 +3194,9 @@ msgstr ""
msgid "A fontawesome icon field" msgid "A fontawesome icon field"
msgstr "" msgstr ""
#~ msgid "No file given!"
#~ msgstr "Keine Datei angegeben!"
#~ msgid "Added payment" #~ msgid "Added payment"
#~ msgstr "Zahlung hinzufügen" #~ msgstr "Zahlung hinzufügen"

Loading…
Cancel
Save