diff --git a/src/documents/consumer.py b/src/documents/consumer.py index c583abc60..bc344abb9 100644 --- a/src/documents/consumer.py +++ b/src/documents/consumer.py @@ -140,13 +140,13 @@ class Consumer(LoggingMixin): if not self.override_asn: # check not necessary in case no ASN gets set return - # Validate the range is above zero and less than int32 max + # Validate the range is above zero and less than uint32_t max # otherwise, Whoosh can't handle it in the index - if self.override_asn < 0 or self.override_asn > 2_147_483_647: + if self.override_asn < 0 or self.override_asn > 0xFF_FF_FF_FF: self._fail( MESSAGE_ASN_RANGE, f"Not consuming {self.filename}: " - "Given ASN is out of range [0, 2147483647]", + f"Given ASN {self.override_asn} is out of range [0, 4,294,967,295]", ) if Document.objects.filter(archive_serial_number=self.override_asn).exists(): self._fail( diff --git a/src/documents/index.py b/src/documents/index.py index 7ba50a324..7add84bb7 100644 --- a/src/documents/index.py +++ b/src/documents/index.py @@ -34,7 +34,7 @@ def get_schema(): id=NUMERIC(stored=True, unique=True), title=TEXT(sortable=True), content=TEXT(), - asn=NUMERIC(sortable=True), + asn=NUMERIC(sortable=True, signed=False), correspondent=TEXT(sortable=True), correspondent_id=NUMERIC(), has_correspondent=BOOLEAN(), diff --git a/src/documents/migrations/1029_alter_document_archive_serial_number.py b/src/documents/migrations/1029_alter_document_archive_serial_number.py new file mode 100644 index 000000000..d7e4b662d --- /dev/null +++ b/src/documents/migrations/1029_alter_document_archive_serial_number.py @@ -0,0 +1,30 @@ +# Generated by Django 4.1.4 on 2023-01-24 17:56 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("documents", "1028_remove_paperlesstask_task_args_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="document", + name="archive_serial_number", + field=models.PositiveIntegerField( + blank=True, + db_index=True, + help_text="The position of this document in your physical document archive.", + null=True, + unique=True, + validators=[ + django.core.validators.MaxValueValidator(4294967295), + django.core.validators.MinValueValidator(0), + ], + verbose_name="archive serial number", + ), + ), + ] diff --git a/src/documents/models.py b/src/documents/models.py index a59340e5b..84e96a79a 100644 --- a/src/documents/models.py +++ b/src/documents/models.py @@ -10,6 +10,8 @@ import pathvalidate from celery import states from django.conf import settings from django.contrib.auth.models import User +from django.core.validators import MaxValueValidator +from django.core.validators import MinValueValidator from django.db import models from django.utils import timezone from django.utils.translation import gettext_lazy as _ @@ -227,12 +229,16 @@ class Document(models.Model): help_text=_("The original name of the file when it was uploaded"), ) - archive_serial_number = models.IntegerField( + archive_serial_number = models.PositiveIntegerField( _("archive serial number"), blank=True, null=True, unique=True, db_index=True, + validators=[ + MaxValueValidator(0xFF_FF_FF_FF), + MinValueValidator(0), + ], help_text=_( "The position of this document in your physical document " "archive.", ), diff --git a/src/documents/tests/samples/barcodes/barcode-128-asn-too-large.pdf b/src/documents/tests/samples/barcodes/barcode-128-asn-too-large.pdf new file mode 100644 index 000000000..2d190c876 Binary files /dev/null and b/src/documents/tests/samples/barcodes/barcode-128-asn-too-large.pdf differ diff --git a/src/documents/tests/test_barcodes.py b/src/documents/tests/test_barcodes.py index 1dc2a88bc..7beeee288 100644 --- a/src/documents/tests/test_barcodes.py +++ b/src/documents/tests/test_barcodes.py @@ -9,6 +9,7 @@ from django.test import override_settings from django.test import TestCase from documents import barcodes from documents import tasks +from documents.consumer import ConsumerError from documents.tests.utils import DirectoriesMixin from PIL import Image @@ -804,3 +805,23 @@ class TestBarcode(DirectoriesMixin, TestCase): args, kwargs = mocked_call.call_args self.assertEqual(kwargs["override_asn"], 123) + + @override_settings(CONSUMER_ENABLE_ASN_BARCODE=True) + def test_asn_too_large(self): + + src = os.path.join( + os.path.dirname(__file__), + "samples", + "barcodes", + "barcode-128-asn-too-large.pdf", + ) + dst = os.path.join(self.dirs.scratch_dir, "barcode-128-asn-too-large.pdf") + shutil.copy(src, dst) + + with mock.patch("documents.consumer.Consumer._send_progress"): + self.assertRaisesMessage( + ConsumerError, + "Given ASN 4294967296 is out of range [0, 4,294,967,295]", + tasks.consume_file, + dst, + )