diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d3324b6e..10175d72 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,6 +77,7 @@ jobs: EMAIL_HOST_PASSWORD_SES: ${{ secrets.EMAIL_HOST_PASSWORD_SES }} EMAIL_HOST_SES: ${{ secrets.EMAIL_HOST_SES }} EMAIL_HOST_USER_SES: ${{ secrets.EMAIL_HOST_USER_SES }} + FIELD_ENCRYPTION_KEY: ${{ secrets.FIELD_ENCRYPTION_KEY }} OD_API_BASE_URL: ${{ secrets.OD_API_BASE_URL }} OD_APPLICATION_ID: ${{ secrets.OD_APPLICATION_ID }} OD_APPLICATION_KEY_1: ${{ secrets.OD_APPLICATION_KEY_1 }} diff --git a/aa_project/settings/base.py b/aa_project/settings/base.py index 3e933cf9..7cd8f0e6 100644 --- a/aa_project/settings/base.py +++ b/aa_project/settings/base.py @@ -47,6 +47,7 @@ 'django_otp.plugins.otp_totp', 'two_factor', 'axes', + 'encrypted_model_fields', ] # Project Apps @@ -274,5 +275,6 @@ AWS_BASE_BUCKET_ADDRESS = os.environ['AWS_BASE_BUCKET_ADDRESS'] # Email Token Settings +FIELD_ENCRYPTION_KEY = os.environ['FIELD_ENCRYPTION_KEY'] EMAIL_CHALLENGE_EXPIRATION_IN_SECS = 60 * 5 EMAIL_TOKEN_EXPIRATION_IN_SECS = 60 * 60 * 24 * 28 diff --git a/aa_project/settings/dev.py b/aa_project/settings/dev.py index 550f6d82..ffeca916 100644 --- a/aa_project/settings/dev.py +++ b/aa_project/settings/dev.py @@ -109,10 +109,6 @@ def skip_debug_requests(record): 'level': 'INFO', 'propagate': False, }, - 'django.db.backends': { - 'handlers': ['console'], - 'level': 'DEBUG', - }, 'two_factor': { 'handlers': ['console'], 'level': 'INFO', diff --git a/apps/users/migrations/0004_emaildevice.py b/apps/users/migrations/0004_generate_email_token_model.py similarity index 53% rename from apps/users/migrations/0004_emaildevice.py rename to apps/users/migrations/0004_generate_email_token_model.py index e31475b1..d9df1be7 100644 --- a/apps/users/migrations/0004_emaildevice.py +++ b/apps/users/migrations/0004_generate_email_token_model.py @@ -1,10 +1,11 @@ -# Generated by Django 3.2.5 on 2021-07-27 12:32 +# Generated by Django 3.2.12 on 2022-02-19 20:36 import apps.users.utils from django.conf import settings from django.db import migrations, models import django.db.models.deletion import django_otp.util +import encrypted_model_fields.fields class Migration(migrations.Migration): @@ -15,18 +16,23 @@ class Migration(migrations.Migration): ] operations = [ + migrations.AlterField( + model_name='profile', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='profile', serialize=False, to=settings.AUTH_USER_MODEL), + ), migrations.CreateModel( - name='EmailDevice', + name='EmailToken', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('challenge_email_address', models.EmailField(max_length=254)), - ('challenge_token_generated', models.CharField(default=django_otp.util.random_hex, help_text='Hex-encoded secret token', max_length=40, validators=[apps.users.utils.token_validator])), + ('challenge_token', encrypted_model_fields.fields.EncryptedCharField(default=django_otp.util.random_hex, validators=[apps.users.utils.token_validator])), ('challenge_generation_timestamp', models.DateTimeField(auto_now_add=True, null=True)), - ('challenge_expiration_timestamp', models.DateTimeField(default=apps.users.utils.get_challenge_expiration_timestamp, null=True)), - ('challenge_token_returned', models.CharField(help_text='Hex-encoded secret token', max_length=40)), + ('challenge_expiration_timestamp', models.DateTimeField(blank=True, default=apps.users.utils.get_challenge_expiration_timestamp, null=True)), ('challenge_completed', models.BooleanField(default=False)), - ('challenge_completed_timestamp', models.DateTimeField(editable=False, null=True)), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_email_devices', to=settings.AUTH_USER_MODEL)), + ('challenge_completed_timestamp', models.DateTimeField(blank=True, null=True)), + ('token_expiration_timestamp', models.DateTimeField(blank=True, null=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_email_tokens', to=settings.AUTH_USER_MODEL)), ], ), ] diff --git a/apps/users/migrations/0005_rename_model.py b/apps/users/migrations/0005_rename_model.py deleted file mode 100644 index ae7aebc5..00000000 --- a/apps/users/migrations/0005_rename_model.py +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by Django 3.2.5 on 2021-08-05 09:33 - -import apps.users.utils -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import django_otp.util - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('users', '0004_emaildevice'), - ] - - operations = [ - migrations.CreateModel( - name='EmailToken', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('challenge_email_address', models.EmailField(max_length=254)), - ('challenge_token_generated', models.CharField(default=django_otp.util.random_hex, max_length=40, validators=[apps.users.utils.token_validator])), - ('challenge_generation_timestamp', models.DateTimeField(auto_now_add=True, null=True)), - ('challenge_expiration_timestamp', models.DateTimeField(default=apps.users.utils.get_challenge_expiration_timestamp, null=True)), - ('challenge_token_returned', models.CharField(help_text='Hex-encoded secret token', max_length=40)), - ('challenge_completed', models.BooleanField(default=False)), - ('challenge_completed_timestamp', models.DateTimeField(editable=False, null=True)), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_email_devices', to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.DeleteModel( - name='EmailDevice', - ), - ] diff --git a/apps/users/migrations/0006_alter_challenge_completed_timestamp_field.py b/apps/users/migrations/0006_alter_challenge_completed_timestamp_field.py deleted file mode 100644 index 1ccf66da..00000000 --- a/apps/users/migrations/0006_alter_challenge_completed_timestamp_field.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.5 on 2021-08-05 11:12 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0005_rename_model'), - ] - - operations = [ - migrations.AlterField( - model_name='emailtoken', - name='challenge_completed_timestamp', - field=models.DateTimeField(null=True), - ), - ] diff --git a/apps/users/migrations/0007_remove_challenge_token_returned_field.py b/apps/users/migrations/0007_remove_challenge_token_returned_field.py deleted file mode 100644 index db145271..00000000 --- a/apps/users/migrations/0007_remove_challenge_token_returned_field.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.2.5 on 2021-08-05 13:48 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0006_alter_challenge_completed_timestamp_field'), - ] - - operations = [ - migrations.RemoveField( - model_name='emailtoken', - name='challenge_token_returned', - ), - migrations.AlterField( - model_name='emailtoken', - name='challenge_completed_timestamp', - field=models.DateTimeField(auto_now=True, null=True), - ), - ] diff --git a/apps/users/migrations/0008_add_encryption_to_challenge_token_field.py b/apps/users/migrations/0008_add_encryption_to_challenge_token_field.py deleted file mode 100644 index 43853362..00000000 --- a/apps/users/migrations/0008_add_encryption_to_challenge_token_field.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.2.5 on 2021-08-05 15:08 - -from django.db import migrations, models - -import django_cryptography.fields -import django_otp.util - -import apps.users.utils - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0007_remove_challenge_token_returned_field'), - ] - - operations = [ - migrations.AlterField( - model_name='emailtoken', - name='challenge_token_generated', - field=django_cryptography.fields.encrypt(models.CharField(default=django_otp.util.random_hex, max_length=40, validators=[apps.users.utils.token_validator])), - ), - ] diff --git a/apps/users/migrations/0009_rename_challenge_token_field.py b/apps/users/migrations/0009_rename_challenge_token_field.py deleted file mode 100644 index 8942b001..00000000 --- a/apps/users/migrations/0009_rename_challenge_token_field.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.5 on 2021-08-05 16:13 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0008_add_encryption_to_challenge_token_field'), - ] - - operations = [ - migrations.RenameField( - model_name='emailtoken', - old_name='challenge_token_generated', - new_name='challenge_token', - ), - ] diff --git a/apps/users/migrations/0010_alter_challenge_completed_timestamp_field.py b/apps/users/migrations/0010_alter_challenge_completed_timestamp_field.py deleted file mode 100644 index 42f1cae5..00000000 --- a/apps/users/migrations/0010_alter_challenge_completed_timestamp_field.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.6 on 2021-08-10 12:11 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0009_rename_challenge_token_field'), - ] - - operations = [ - migrations.AlterField( - model_name='emailtoken', - name='challenge_completed_timestamp', - field=models.DateTimeField(null=True), - ), - ] diff --git a/apps/users/migrations/0011_alter_challenge_completed_timestamp_field.py b/apps/users/migrations/0011_alter_challenge_completed_timestamp_field.py deleted file mode 100644 index bbe4c923..00000000 --- a/apps/users/migrations/0011_alter_challenge_completed_timestamp_field.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.6 on 2021-08-10 12:50 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0010_alter_challenge_completed_timestamp_field'), - ] - - operations = [ - migrations.AlterField( - model_name='emailtoken', - name='challenge_completed_timestamp', - field=models.DateTimeField(default=None, null=True), - ), - ] diff --git a/apps/users/migrations/0012_alter_challenge_completed_timestamp_field.py b/apps/users/migrations/0012_alter_challenge_completed_timestamp_field.py deleted file mode 100644 index c1b63261..00000000 --- a/apps/users/migrations/0012_alter_challenge_completed_timestamp_field.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.6 on 2021-08-10 13:34 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0011_alter_challenge_completed_timestamp_field'), - ] - - operations = [ - migrations.AlterField( - model_name='emailtoken', - name='challenge_completed_timestamp', - field=models.DateTimeField(null=True), - ), - ] diff --git a/apps/users/migrations/0013_alter_timestamp_fields.py b/apps/users/migrations/0013_alter_timestamp_fields.py deleted file mode 100644 index 6bd7bc1a..00000000 --- a/apps/users/migrations/0013_alter_timestamp_fields.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.2.6 on 2021-08-10 13:40 - -import apps.users.utils -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0012_alter_challenge_completed_timestamp_field'), - ] - - operations = [ - migrations.AlterField( - model_name='emailtoken', - name='challenge_completed_timestamp', - field=models.DateTimeField(blank=True, null=True), - ), - migrations.AlterField( - model_name='emailtoken', - name='challenge_expiration_timestamp', - field=models.DateTimeField(blank=True, default=apps.users.utils.get_challenge_expiration_timestamp, null=True), - ), - ] diff --git a/apps/users/migrations/0014_add_token_expiration_timestamp_field.py b/apps/users/migrations/0014_add_token_expiration_timestamp_field.py deleted file mode 100644 index cf35e0d1..00000000 --- a/apps/users/migrations/0014_add_token_expiration_timestamp_field.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.2.6 on 2021-08-11 09:35 - -import apps.users.utils -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0013_alter_timestamp_fields'), - ] - - operations = [ - migrations.AddField( - model_name='emailtoken', - name='token_expiration_timestamp', - field=models.DateTimeField(blank=True, default=apps.users.utils.get_token_expiration_timestamp, null=True), - ), - ] diff --git a/apps/users/migrations/0015_remove_default_for_token_expiration_timestamp_field.py b/apps/users/migrations/0015_remove_default_for_token_expiration_timestamp_field.py deleted file mode 100644 index 207dd7ba..00000000 --- a/apps/users/migrations/0015_remove_default_for_token_expiration_timestamp_field.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.6 on 2021-08-11 09:38 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0014_add_token_expiration_timestamp_field'), - ] - - operations = [ - migrations.AlterField( - model_name='emailtoken', - name='token_expiration_timestamp', - field=models.DateTimeField(blank=True, null=True), - ), - ] diff --git a/apps/users/migrations/0016_alter_related_name_for_user_field_profile_model.py b/apps/users/migrations/0016_alter_related_name_for_user_field_profile_model.py deleted file mode 100644 index 3713f9b0..00000000 --- a/apps/users/migrations/0016_alter_related_name_for_user_field_profile_model.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.2.6 on 2021-08-11 11:15 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('users', '0015_remove_default_for_token_expiration_timestamp_field'), - ] - - operations = [ - migrations.AlterField( - model_name='profile', - name='user', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='profile', serialize=False, to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/apps/users/migrations/0017_alter_related_name_for_user_field_email_token_model.py b/apps/users/migrations/0017_alter_related_name_for_user_field_email_token_model.py deleted file mode 100644 index 33dc295a..00000000 --- a/apps/users/migrations/0017_alter_related_name_for_user_field_email_token_model.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.2.6 on 2021-08-11 14:45 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('users', '0016_alter_related_name_for_user_field_profile_model'), - ] - - operations = [ - migrations.AlterField( - model_name='emailtoken', - name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_email_tokens', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/apps/users/migrations/0018_amend_max_length_of_challenge_token.py b/apps/users/migrations/0018_amend_max_length_of_challenge_token.py deleted file mode 100644 index 0ffb1e4e..00000000 --- a/apps/users/migrations/0018_amend_max_length_of_challenge_token.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.2.6 on 2021-08-23 12:08 - -import apps.users.utils -from django.db import migrations, models -import django_cryptography.fields -import django_otp.util - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0017_alter_related_name_for_user_field_email_token_model'), - ] - - operations = [ - migrations.AlterField( - model_name='emailtoken', - name='challenge_token', - field=django_cryptography.fields.encrypt(models.CharField(default=django_otp.util.random_hex, max_length=255, validators=[apps.users.utils.token_validator])), - ), - ] diff --git a/apps/users/models.py b/apps/users/models.py index 93e0d244..61becb9a 100644 --- a/apps/users/models.py +++ b/apps/users/models.py @@ -1,3 +1,5 @@ +import imp + from datetime import timedelta from django.conf import settings @@ -8,8 +10,8 @@ from django.urls import reverse from django.utils import timezone -from django_cryptography.fields import encrypt from django_otp.util import random_hex +from encrypted_model_fields.fields import EncryptedCharField from apps.users.utils import get_challenge_expiration_timestamp, token_validator @@ -84,8 +86,8 @@ def is_two_factor_authenticated(self) -> bool: class EmailToken(models.Model): challenge_email_address = models.EmailField() - challenge_token = encrypt(models.CharField( - max_length=255, default=random_hex, validators=[token_validator])) + challenge_token = EncryptedCharField( + max_length=255, default=random_hex, validators=[token_validator]) challenge_generation_timestamp = models.DateTimeField( null=True, blank=True, auto_now_add=True, editable=False) challenge_expiration_timestamp = models.DateTimeField( diff --git a/poetry.lock b/poetry.lock index 957f9d57..2c2dc348 100644 --- a/poetry.lock +++ b/poetry.lock @@ -326,17 +326,6 @@ sqlparse = ">=0.2.2" argon2 = ["argon2-cffi (>=19.1.0)"] bcrypt = ["bcrypt"] -[[package]] -name = "django-appconf" -version = "1.0.5" -description = "A helper class for handling configuration defaults of packaged apps gracefully." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -django = "*" - [[package]] name = "django-axes" version = "5.31.0" @@ -381,18 +370,6 @@ category = "main" optional = false python-versions = ">=3.7" -[[package]] -name = "django-cryptography" -version = "1.0" -description = "Easily encrypt data in Django" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -cryptography = "*" -django-appconf = "*" - [[package]] name = "django-debug-toolbar" version = "3.2.4" @@ -417,6 +394,18 @@ python-versions = "*" django-debug-toolbar = ">=2.0" wrapt = "*" +[[package]] +name = "django-encrypted-model-fields" +version = "0.6.1" +description = "A set of django fields that internally are encrypted using the cryptography.io native python encryption library." +category = "main" +optional = false +python-versions = ">=3.6, <=3.11" + +[package.dependencies] +cryptography = ">=3.4" +Django = ">=2.2" + [[package]] name = "django-extensions" version = "3.1.5" @@ -485,11 +474,11 @@ qrcode = ["qrcode"] [[package]] name = "django-phonenumber-field" -version = "6.0.0" +version = "6.1.0" description = "An international phone number field for django models." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] Django = ">=2.2" @@ -770,7 +759,7 @@ python-versions = ">=3.5" [[package]] name = "importlib-metadata" -version = "4.11.0" +version = "4.11.1" description = "Read metadata from Python packages" category = "dev" optional = false @@ -782,7 +771,7 @@ zipp = ">=0.5" [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] perf = ["ipython"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] [[package]] name = "inflection" @@ -930,7 +919,7 @@ format_nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- [[package]] name = "jupyter-core" -version = "4.9.1" +version = "4.9.2" description = "Jupyter core package. A base package on which Jupyter projects rely." category = "dev" optional = false @@ -1117,7 +1106,7 @@ python-versions = ">=3.7" [[package]] name = "platformdirs" -version = "2.5.0" +version = "2.5.1" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false @@ -1678,7 +1667,7 @@ test = ["pytest"] [[package]] name = "typing-extensions" -version = "4.1.0" +version = "4.1.1" description = "Backported and Experimental Type Hints for Python 3.6+" category = "dev" optional = false @@ -1791,7 +1780,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest- [metadata] lock-version = "1.1" python-versions = "==3.9.10" -content-hash = "efe16a5a8eb6cc29c6ad961337b90578d82e5c8b1bf62e96aa399fd065db69e4" +content-hash = "c16dc69d328b185843c74218b90b795043d2dd2dd837d74b6720749746f888b3" [metadata.files] appnope = [ @@ -2034,10 +2023,6 @@ django = [ {file = "Django-3.2.12-py3-none-any.whl", hash = "sha256:9b06c289f9ba3a8abea16c9c9505f25107809fb933676f6c891ded270039d965"}, {file = "Django-3.2.12.tar.gz", hash = "sha256:9772e6935703e59e993960832d66a614cf0233a1c5123bc6224ecc6ad69e41e2"}, ] -django-appconf = [ - {file = "django-appconf-1.0.5.tar.gz", hash = "sha256:be3db0be6c81fa84742000b89a81c016d70ae66a7ccb620cdef592b1f1a6aaa4"}, - {file = "django_appconf-1.0.5-py3-none-any.whl", hash = "sha256:ae9f864ee1958c815a965ed63b3fba4874eec13de10236ba063a788f9a17389d"}, -] django-axes = [ {file = "django-axes-5.31.0.tar.gz", hash = "sha256:e6754be4c8a9e55a25381e4aea6aeb1ec1f0d8dd025f233d9caa910ce9be6728"}, {file = "django_axes-5.31.0-py3-none-any.whl", hash = "sha256:17f1884a439d2a20495c0c03427922634ab7828cd030d9bc1ce3d0425917ff36"}, @@ -2054,10 +2039,6 @@ django-crispy-forms = [ {file = "django-crispy-forms-1.14.0.tar.gz", hash = "sha256:35887b8851a931374dd697207a8f56c57a9c5cb9dbf0b9fa54314da5666cea5b"}, {file = "django_crispy_forms-1.14.0-py3-none-any.whl", hash = "sha256:bc4d2037f6de602d39c0bc452ac3029d1f5d65e88458872cc4dbc01c3a400604"}, ] -django-cryptography = [ - {file = "django-cryptography-1.0.tar.gz", hash = "sha256:13de5cf8f1250744c104b9e24774d03aa6d8488959dd40cdc016934043652445"}, - {file = "django_cryptography-1.0-py3-none-any.whl", hash = "sha256:0a99980b1cee7cc5e52f9b20b322620fea7cc124d770273e7bd285b20fd9d222"}, -] django-debug-toolbar = [ {file = "django-debug-toolbar-3.2.4.tar.gz", hash = "sha256:644bbd5c428d3283aa9115722471769cac1bec189edf3a0c855fd8ff870375a9"}, {file = "django_debug_toolbar-3.2.4-py3-none-any.whl", hash = "sha256:6b633b6cfee24f232d73569870f19aa86c819d750e7f3e833f2344a9eb4b4409"}, @@ -2066,6 +2047,10 @@ django-debug-toolbar-template-profiler = [ {file = "django-debug-toolbar-template-profiler-2.0.2.tar.gz", hash = "sha256:bdbbbbbbce09fb918911e4e8fb9bf5987edee6cac5d0097965f3df61099ee3d9"}, {file = "django_debug_toolbar_template_profiler-2.0.2-py2.py3-none-any.whl", hash = "sha256:31b1bfc3bc8af29193f0b79ae3180352ee369501979f0034d21848372e2a0894"}, ] +django-encrypted-model-fields = [ + {file = "django-encrypted-model-fields-0.6.1.tar.gz", hash = "sha256:cef683c1cb16a635b5ed1261d4e1d82faadc1bdeadc489854a2992c48e8f4dfc"}, + {file = "django_encrypted_model_fields-0.6.1-py3-none-any.whl", hash = "sha256:f9b35b4b4c344f4d3d173828be58a468ff016d7656ea1fb8f6954f3b77bef918"}, +] django-extensions = [ {file = "django-extensions-3.1.5.tar.gz", hash = "sha256:28e1e1bf49f0e00307ba574d645b0af3564c981a6dfc87209d48cb98f77d0b1a"}, {file = "django_extensions-3.1.5-py3-none-any.whl", hash = "sha256:9238b9e016bb0009d621e05cf56ea8ce5cce9b32e91ad2026996a7377ca28069"}, @@ -2091,8 +2076,8 @@ django-otp = [ {file = "django_otp-1.1.3-py3-none-any.whl", hash = "sha256:8637be826c0465d0fd1710e4472efe9fc83883853a2141fefdbace9358d20003"}, ] django-phonenumber-field = [ - {file = "django-phonenumber-field-6.0.0.tar.gz", hash = "sha256:9695d3beda772c503ad4e04a4f7012a8227e9e3e4fd0ea4ffb07c43245bf4a8d"}, - {file = "django_phonenumber_field-6.0.0-py3-none-any.whl", hash = "sha256:bbb9cb2e6fc53c476de40428e1354c313a040e8b2fb69ea8ead4ba41a60f926a"}, + {file = "django-phonenumber-field-6.1.0.tar.gz", hash = "sha256:b1ff950f90a8911ff323ccf77c8f6fe4299a9f671fa61c8734a6994359f07446"}, + {file = "django_phonenumber_field-6.1.0-py3-none-any.whl", hash = "sha256:897b902a1654b0eb21f6268498a3359e2c4eb90af9585cb8693af186ede8c5bb"}, ] django-recaptcha = [ {file = "django-recaptcha-3.0.0.tar.gz", hash = "sha256:253197051288923cae675d7eff91b619e3775311292a5dbaf27a8a55ffebc670"}, @@ -2231,8 +2216,8 @@ idna = [ {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.11.0-py3-none-any.whl", hash = "sha256:6affcdb3aec542dd98df8211e730bba6c5f2bec8288d47bacacde898f548c9ad"}, - {file = "importlib_metadata-4.11.0.tar.gz", hash = "sha256:9e5e553bbba1843cb4a00823014b907616be46ee503d2b9ba001d214a8da218f"}, + {file = "importlib_metadata-4.11.1-py3-none-any.whl", hash = "sha256:e0bc84ff355328a4adfc5240c4f211e0ab386f80aa640d1b11f0618a1d282094"}, + {file = "importlib_metadata-4.11.1.tar.gz", hash = "sha256:175f4ee440a0317f6e8d81b7f8d4869f93316170a65ad2b007d2929186c8052c"}, ] inflection = [ {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, @@ -2274,8 +2259,8 @@ jsonschema = [ {file = "jsonschema-4.4.0.tar.gz", hash = "sha256:636694eb41b3535ed608fe04129f26542b59ed99808b4f688aa32dcf55317a83"}, ] jupyter-core = [ - {file = "jupyter_core-4.9.1-py3-none-any.whl", hash = "sha256:1c091f3bbefd6f2a8782f2c1db662ca8478ac240e962ae2c66f0b87c818154ea"}, - {file = "jupyter_core-4.9.1.tar.gz", hash = "sha256:dce8a7499da5a53ae3afd5a9f4b02e5df1d57250cf48f3ad79da23b4778cd6fa"}, + {file = "jupyter_core-4.9.2-py3-none-any.whl", hash = "sha256:f875e4d27e202590311d468fa55f90c575f201490bd0c18acabe4e318db4a46d"}, + {file = "jupyter_core-4.9.2.tar.gz", hash = "sha256:d69baeb9ffb128b8cd2657fcf2703f89c769d1673c851812119e3a2a0e93ad9a"}, ] lazy-object-proxy = [ {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, @@ -2464,8 +2449,8 @@ pillow = [ {file = "Pillow-9.0.0.tar.gz", hash = "sha256:ee6e2963e92762923956fe5d3479b1fdc3b76c83f290aad131a2f98c3df0593e"}, ] platformdirs = [ - {file = "platformdirs-2.5.0-py3-none-any.whl", hash = "sha256:30671902352e97b1eafd74ade8e4a694782bd3471685e78c32d0fdfd3aa7e7bb"}, - {file = "platformdirs-2.5.0.tar.gz", hash = "sha256:8ec11dfba28ecc0715eb5fb0147a87b1bf325f349f3da9aab2cd6b50b96b692b"}, + {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, + {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, ] plotly = [ {file = "plotly-4.14.3-py2.py3-none-any.whl", hash = "sha256:d68fc15fcb49f88db27ab3e0c87110943e65fee02a47f33a8590f541b3042461"}, @@ -2801,8 +2786,8 @@ traitlets = [ {file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"}, ] typing-extensions = [ - {file = "typing_extensions-4.1.0-py3-none-any.whl", hash = "sha256:c13180fbaa7cd97065a4915ceba012bdb31dc34743e63ddee16360161d358414"}, - {file = "typing_extensions-4.1.0.tar.gz", hash = "sha256:ba97c5143e5bb067b57793c726dd857b1671d4b02ced273ca0538e71ff009095"}, + {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, + {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, ] urllib3 = [ {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, diff --git a/pyproject.toml b/pyproject.toml index 35b9f983..c40ad0ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,6 @@ django-filter = "==21.1" django-tinymce = "==3.4.0" django-bootstrap4 = "==21.2" django-two-factor-auth = "==1.13.2" -django-cryptography = "==1.0" psycopg2-binary = "2.9.3" dj-database-url = "==0.5.0" gunicorn = "==20.1.0" @@ -33,7 +32,8 @@ markdown = "==3.3.4" boto3 = "1.20.54" pygments = "==2.11.2" pillow = "==9.0.0" -phonenumbers = "8.12.43" +phonenumbers = "==8.12.43" +django-encrypted-model-fields = "0.6.1" [tool.poetry.dev-dependencies] django-debug-toolbar = "3.2.4"