From 2b73036e86d1bef8af8e1a9dd6e85bd8abec26c8 Mon Sep 17 00:00:00 2001 From: Matti Lamppu Date: Sat, 25 Nov 2023 11:06:03 +0200 Subject: [PATCH] Update auth_token and last_response columns' max lengths --- Makefile | 10 +++++ signal_webhooks/migrations/0001_initial.py | 4 +- ...auth_token_and_last_response_max_length.py | 38 ++++++++++++++++++ signal_webhooks/models.py | 6 +-- signal_webhooks/typing.py | 4 ++ signal_webhooks/utils.py | 4 +- tests/my_app/migrations/0001_initial.py | 28 +++---------- tests/project/settings.py | 6 +-- tests/project/testdb | Bin 180224 -> 180224 bytes tests/test_utils.py | 9 +++-- 10 files changed, 72 insertions(+), 37 deletions(-) create mode 100644 signal_webhooks/migrations/0002_change_auth_token_and_last_response_max_length.py diff --git a/Makefile b/Makefile index 9c8f9a1..a00aaa4 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,8 @@ export DJANGO_SETTINGS_MODULE = tests.project.settings .PHONY: tox .PHONY: hook .PHONY: lint +.PHONY: migrate +.PHONY: migrations .PHONY: mypy .PHONY: Makefile @@ -30,6 +32,8 @@ define helptext tox Run all tests with tox. hook Install pre-commit hook. lint Run pre-commit hooks on all files. + migrate Run migrations. + migrations Create migrations. mypy Run mypy on all files. Use quotes (" ") if command contains flags (-h / --help) @@ -61,5 +65,11 @@ hook: lint: @poetry run pre-commit run --all-files +migrate: + @poetry run python manage.py migrate + +migrations: + @poetry run python manage.py makemigrations + mypy: @poetry run mypy django_signal_webhooks/ diff --git a/signal_webhooks/migrations/0001_initial.py b/signal_webhooks/migrations/0001_initial.py index 94b9bde..21b54b8 100644 --- a/signal_webhooks/migrations/0001_initial.py +++ b/signal_webhooks/migrations/0001_initial.py @@ -84,7 +84,7 @@ class Migration(migrations.Migration): blank=True, default="", help_text="Authentication token to use in an Authorization header.", - max_length=10000, + max_length=8000, validators=[signal_webhooks.utils.decode_cipher_key], verbose_name="authentication token", ), @@ -127,7 +127,7 @@ class Migration(migrations.Migration): blank=True, default="", help_text="Latest response to this webhook.", - max_length=10000, + max_length=8000, verbose_name="last response", ), ), diff --git a/signal_webhooks/migrations/0002_change_auth_token_and_last_response_max_length.py b/signal_webhooks/migrations/0002_change_auth_token_and_last_response_max_length.py new file mode 100644 index 0000000..64ae66a --- /dev/null +++ b/signal_webhooks/migrations/0002_change_auth_token_and_last_response_max_length.py @@ -0,0 +1,38 @@ +# Generated by Django 4.2.6 on 2023-11-25 08:58 + +from django.db import migrations, models + +import signal_webhooks.fields +import signal_webhooks.utils + + +class Migration(migrations.Migration): + dependencies = [ + ("signal_webhooks", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="webhook", + name="auth_token", + field=signal_webhooks.fields.TokenField( + blank=True, + default="", + help_text="Authentication token to use in an Authorization header.", + max_length=8000, + validators=[signal_webhooks.utils.decode_cipher_key], + verbose_name="authentication token", + ), + ), + migrations.AlterField( + model_name="webhook", + name="last_response", + field=models.CharField( + blank=True, + default="", + help_text="Latest response to this webhook.", + max_length=8000, + verbose_name="last response", + ), + ), + ] diff --git a/signal_webhooks/models.py b/signal_webhooks/models.py index 0615ed9..95566ef 100644 --- a/signal_webhooks/models.py +++ b/signal_webhooks/models.py @@ -6,7 +6,7 @@ from .fields import TokenField from .settings import webhook_settings -from .typing import METHOD_SIGNALS, SignalChoices +from .typing import MAX_COL_SIZE, METHOD_SIGNALS, SignalChoices from .utils import decode_cipher_key, is_dict, model_from_reference, reference_for_model if TYPE_CHECKING: @@ -73,7 +73,7 @@ class WebhookBase(models.Model): auth_token: str = TokenField( default="", blank=True, - max_length=10_000, + max_length=MAX_COL_SIZE, verbose_name="authentication token", help_text="Authentication token to use in an Authorization header.", validators=[decode_cipher_key], @@ -101,7 +101,7 @@ class WebhookBase(models.Model): last_response: str = models.CharField( default="", blank=True, - max_length=10_000, + max_length=MAX_COL_SIZE, verbose_name="last response", help_text="Latest response to this webhook.", ) diff --git a/signal_webhooks/typing.py b/signal_webhooks/typing.py index 1716e22..e6c85f0 100644 --- a/signal_webhooks/typing.py +++ b/signal_webhooks/typing.py @@ -152,3 +152,7 @@ def delete_choises(cls) -> set["SignalChoices"]: "UPDATE": SignalChoices.update_choises(), "DELETE": SignalChoices.delete_choises(), } + +# Define a maximum column size based on MS SQL Server limitation: +# https://docs.microsoft.com/en-us/sql/sql-server/maximum-capacity-specifications-for-sql-server +MAX_COL_SIZE: int = 8_000 diff --git a/signal_webhooks/utils.py b/signal_webhooks/utils.py index c239725..6eb736a 100644 --- a/signal_webhooks/utils.py +++ b/signal_webhooks/utils.py @@ -15,7 +15,7 @@ from .serializers import webhook_serializer from .settings import webhook_settings -from .typing import ClientKwargs +from .typing import MAX_COL_SIZE, ClientKwargs if TYPE_CHECKING: from django.db.models import Model @@ -56,7 +56,7 @@ def is_dict(value: str) -> None: raise ValidationError(msg) -def truncate(string: str, limit: int = 10_000) -> str: +def truncate(string: str, limit: int = MAX_COL_SIZE) -> str: if len(string) > limit: string = string[: limit - 3] + "..." return string diff --git a/tests/my_app/migrations/0001_initial.py b/tests/my_app/migrations/0001_initial.py index dd91eff..161bd19 100644 --- a/tests/my_app/migrations/0001_initial.py +++ b/tests/my_app/migrations/0001_initial.py @@ -1,7 +1,6 @@ -# Generated by Django 4.1 on 2022-08-21 20:06 +# Generated by Django 4.2.6 on 2023-11-25 09:03 from django.db import migrations, models - import signal_webhooks.fields import signal_webhooks.utils @@ -24,12 +23,7 @@ class Migration(migrations.Migration): verbose_name="ID", ), ), - ( - "name", - models.CharField( - max_length=256, - ), - ), + ("name", models.CharField(max_length=256)), ], ), migrations.CreateModel( @@ -104,7 +98,7 @@ class Migration(migrations.Migration): blank=True, default="", help_text="Authentication token to use in an Authorization header.", - max_length=10000, + max_length=8000, validators=[signal_webhooks.utils.decode_cipher_key], verbose_name="authentication token", ), @@ -147,7 +141,7 @@ class Migration(migrations.Migration): blank=True, default="", help_text="Latest response to this webhook.", - max_length=10000, + max_length=8000, verbose_name="last response", ), ), @@ -169,12 +163,7 @@ class Migration(migrations.Migration): verbose_name="last failure", ), ), - ( - "code", - models.CharField( - max_length=256, - ), - ), + ("code", models.CharField(max_length=256)), ], options={ "abstract": False, @@ -192,12 +181,7 @@ class Migration(migrations.Migration): verbose_name="ID", ), ), - ( - "name", - models.CharField( - max_length=256, - ), - ), + ("name", models.CharField(max_length=256)), ], ), migrations.AddConstraint( diff --git a/tests/project/settings.py b/tests/project/settings.py index 7c85677..2b7746f 100644 --- a/tests/project/settings.py +++ b/tests/project/settings.py @@ -55,7 +55,7 @@ DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", - "NAME": BASE_DIR / "django" / "testdb", + "NAME": BASE_DIR / "project" / "testdb", "OPTIONS": { "timeout": 1, }, @@ -70,9 +70,7 @@ AUTH_PASSWORD_VALIDATORS = [ - { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" - }, + {"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"}, {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"}, {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, diff --git a/tests/project/testdb b/tests/project/testdb index fe0c8edc66a513d87213be9e5cb51bfb45006127..2bd5ec2520db7fe9219868fdc0b8ab47bf607cac 100644 GIT binary patch delta 1480 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