From 85d97a89efdb89f8aa497463bfa4d3bbc9d12c1c Mon Sep 17 00:00:00 2001 From: Andrea Carmisciano Date: Mon, 28 Oct 2019 15:18:57 +0100 Subject: [PATCH 1/2] attempt to crypt fields --- .../migrations/0054_auto_20191027_2220.py | 22 +++++++++++++ .../migrations/0055_auto_20191027_2224.py | 33 +++++++++++++++++++ anagrafica/models.py | 11 ++++--- base/migrations/0020_auto_20191027_2220.py | 20 +++++++++++ config/pgsql.cnf.sample | 2 +- requirements.txt | 1 + .../migrations/0002_auto_20191027_2220.py | 19 +++++++++++ .../migrations/0019_auto_20191027_2220.py | 20 +++++++++++ 8 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 anagrafica/migrations/0054_auto_20191027_2220.py create mode 100644 anagrafica/migrations/0055_auto_20191027_2224.py create mode 100644 base/migrations/0020_auto_20191027_2220.py create mode 100644 static_page/migrations/0002_auto_20191027_2220.py create mode 100644 ufficio_soci/migrations/0019_auto_20191027_2220.py diff --git a/anagrafica/migrations/0054_auto_20191027_2220.py b/anagrafica/migrations/0054_auto_20191027_2220.py new file mode 100644 index 000000000..5b9962d5b --- /dev/null +++ b/anagrafica/migrations/0054_auto_20191027_2220.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2019-10-27 22:20 +from __future__ import unicode_literals + +import base.utils +from django.db import migrations +import django_cryptography.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('anagrafica', '0053_merge'), + ] + + operations = [ + migrations.AlterField( + model_name='persona', + name='cognome', + field=django_cryptography.fields.encrypt(base.utils.TitleCharField(db_index=True, max_length=64, verbose_name='Cognome')), + ), + ] diff --git a/anagrafica/migrations/0055_auto_20191027_2224.py b/anagrafica/migrations/0055_auto_20191027_2224.py new file mode 100644 index 000000000..9a279c38d --- /dev/null +++ b/anagrafica/migrations/0055_auto_20191027_2224.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2019-10-27 22:24 +from __future__ import unicode_literals + +import anagrafica.validators +import base.utils +from django.db import migrations, models +import django_cryptography.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('anagrafica', '0054_auto_20191027_2220'), + ] + + operations = [ + migrations.AlterField( + model_name='persona', + name='codice_fiscale', + field=django_cryptography.fields.encrypt(base.utils.UpperCaseCharField(db_index=True, max_length=16, unique=True, validators=[anagrafica.validators.valida_codice_fiscale], verbose_name='Codice Fiscale')), + ), + migrations.AlterField( + model_name='persona', + name='domicilio_indirizzo', + field=django_cryptography.fields.encrypt(models.CharField(blank=True, max_length=512, null=True, verbose_name='Indirizzo di domicilio')), + ), + migrations.AlterField( + model_name='persona', + name='domicilio_provincia', + field=django_cryptography.fields.encrypt(models.CharField(blank=True, max_length=2, null=True, verbose_name='Provincia di domicilio')), + ), + ] diff --git a/anagrafica/models.py b/anagrafica/models.py index 1520d24eb..d88e5bb34 100755 --- a/anagrafica/models.py +++ b/anagrafica/models.py @@ -3,6 +3,7 @@ import codicefiscale import phonenumbers import mptt +from django_cryptography.fields import encrypt from mptt.querysets import TreeQuerySet from autoslug import AutoSlugField @@ -58,9 +59,9 @@ class Persona(ModelloSemplice, ConMarcaTemporale, ConAllegati, ConVecchioID): # Informazioni anagrafiche nome = TitleCharField("Nome", max_length=64, db_index=True) - cognome = TitleCharField("Cognome", max_length=64, db_index=True) - codice_fiscale = UpperCaseCharField("Codice Fiscale", max_length=16, blank=False, - unique=True, db_index=True, validators=[valida_codice_fiscale,]) + cognome = encrypt(TitleCharField("Cognome", max_length=64, db_index=True)) + codice_fiscale = encrypt(UpperCaseCharField("Codice Fiscale", max_length=16, blank=False, + unique=True, db_index=True, validators=[valida_codice_fiscale,])) data_nascita = models.DateField("Data di nascita", db_index=True, null=True) genere = models.CharField("Sesso", max_length=1, choices=GENERE, db_index=True) stato = models.CharField("Stato", max_length=1, choices=STATO, default=PERSONA, db_index=True) @@ -78,9 +79,9 @@ class Persona(ModelloSemplice, ConMarcaTemporale, ConAllegati, ConVecchioID): # Domicilio domicilio_uguale_a_residenza = models.BooleanField(default=False, verbose_name='Domicilio uguale a residenza') - domicilio_indirizzo = models.CharField("Indirizzo di domicilio", max_length=512, null=True, blank=True) + domicilio_indirizzo = encrypt(models.CharField("Indirizzo di domicilio", max_length=512, null=True, blank=True)) domicilio_comune = models.CharField("Comune di domicilio", max_length=64, null=True, blank=True) - domicilio_provincia = models.CharField("Provincia di domicilio", max_length=2, null=True, blank=True) + domicilio_provincia = encrypt(models.CharField("Provincia di domicilio", max_length=2, null=True, blank=True)) domicilio_stato = CountryField("Stato di domicilio", default="IT", null=True, blank=True) domicilio_cap = models.CharField("CAP di domicilio", max_length=16, null=True, blank=True) diff --git a/base/migrations/0020_auto_20191027_2220.py b/base/migrations/0020_auto_20191027_2220.py new file mode 100644 index 000000000..6a120db03 --- /dev/null +++ b/base/migrations/0020_auto_20191027_2220.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2019-10-27 22:20 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('base', '0019_auto_20190109_1053'), + ] + + operations = [ + migrations.AlterField( + model_name='autorizzazione', + name='destinatario_ruolo', + field=models.CharField(choices=[('PRES', 'Presidenza'), ('COM', 'Commissario'), ('US-GEN', 'Gestione dei Soci'), ('US-TRASF', 'Gestione dei Trasferimenti'), ('US-EST', 'Gestione delle Estensioni'), ('US-FOT', 'Gestione delle Fototessere'), ('US-TIT', 'Gestione dei Titoli nella Sede'), ('US-RIS', 'Gestione delle Riserve'), ('ATT-PART', "Gestione dei Partecipanti all'Attività"), ('CB-PART', 'Gestione dei Partecipanti al Corso Base'), ('US-APP', 'Gestione degli Appartenenti alla Sede'), ('SA-SAN', 'Gestione delle Donazioni Sangue'), ('ASP', 'Autogestione Aspirante')], db_index=True, max_length=16), + ), + ] diff --git a/config/pgsql.cnf.sample b/config/pgsql.cnf.sample index 2eeb12613..60439273c 100755 --- a/config/pgsql.cnf.sample +++ b/config/pgsql.cnf.sample @@ -1,6 +1,6 @@ [client] host = db port = 5432 -database = qq +database = postgres user = postgres password = diff --git a/requirements.txt b/requirements.txt index 98a7d1310..0ab69c879 100755 --- a/requirements.txt +++ b/requirements.txt @@ -56,3 +56,4 @@ xlrd WeasyPrint https://github.com/emfcamp/python-barcode/archive/0.7.zip # pyBarcode==0.7 https://github.com/nephila/django-filer/archive/296fa6170a3749532b85ceb033eeae0fb839e9a6.zip +django-cryptography==0.3 diff --git a/static_page/migrations/0002_auto_20191027_2220.py b/static_page/migrations/0002_auto_20191027_2220.py new file mode 100644 index 000000000..9352aef7f --- /dev/null +++ b/static_page/migrations/0002_auto_20191027_2220.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2019-10-27 22:20 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('static_page', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='page', + options={'verbose_name': 'Pagina statica', 'verbose_name_plural': 'Pagine statiche'}, + ), + ] diff --git a/ufficio_soci/migrations/0019_auto_20191027_2220.py b/ufficio_soci/migrations/0019_auto_20191027_2220.py new file mode 100644 index 000000000..5b611132e --- /dev/null +++ b/ufficio_soci/migrations/0019_auto_20191027_2220.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2019-10-27 22:20 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ufficio_soci', '0018_auto_20190416_1051'), + ] + + operations = [ + migrations.AlterField( + model_name='riduzione', + name='descrizione', + field=models.CharField(help_text='Dicitura riportata sulle ricevute e nella causale della quota', max_length=500), + ), + ] From 1522e8d2a2fb41f0e20a506465e3d033a5953d65 Mon Sep 17 00:00:00 2001 From: Andrea Carmisciano Date: Tue, 29 Oct 2019 22:19:01 +0100 Subject: [PATCH 2/2] custom migration --- .../migrations/0054_auto_20191027_2220.py | 22 ------ .../migrations/0054_convert_to_crypt.py | 74 +++++++++++++++++++ .../migrations/0055_auto_20191027_2224.py | 33 --------- anagrafica/models.py | 8 +- 4 files changed, 78 insertions(+), 59 deletions(-) delete mode 100644 anagrafica/migrations/0054_auto_20191027_2220.py create mode 100644 anagrafica/migrations/0054_convert_to_crypt.py delete mode 100644 anagrafica/migrations/0055_auto_20191027_2224.py diff --git a/anagrafica/migrations/0054_auto_20191027_2220.py b/anagrafica/migrations/0054_auto_20191027_2220.py deleted file mode 100644 index 5b9962d5b..000000000 --- a/anagrafica/migrations/0054_auto_20191027_2220.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.13 on 2019-10-27 22:20 -from __future__ import unicode_literals - -import base.utils -from django.db import migrations -import django_cryptography.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('anagrafica', '0053_merge'), - ] - - operations = [ - migrations.AlterField( - model_name='persona', - name='cognome', - field=django_cryptography.fields.encrypt(base.utils.TitleCharField(db_index=True, max_length=64, verbose_name='Cognome')), - ), - ] diff --git a/anagrafica/migrations/0054_convert_to_crypt.py b/anagrafica/migrations/0054_convert_to_crypt.py new file mode 100644 index 000000000..659562fe9 --- /dev/null +++ b/anagrafica/migrations/0054_convert_to_crypt.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.13 on 2019-10-29 22:14 +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +from django_cryptography.fields import encrypt + +app_with_model = 'anagrafica' +model_with_column = 'Persona' +column_to_encrypt = 'cognome' +column_field_class = models.CharField +column_attrs = {'max_length': 150} +column_null_status = False +temporary_column = f'temp_{column_to_encrypt}' + +def replicate_to_temporary(apps, schema_editor): + Model = apps.get_model(app_with_model, model_with_column) + for row in Model.objects.all(): + setattr(row, temporary_column, getattr(row, column_to_encrypt, None)) + setattr(row, column_to_encrypt, None) + row.save(update_fields=[temporary_column, column_to_encrypt]) + +def replicate_to_real(apps, schema_editor): + Model = apps.get_model(app_with_model, model_with_column) + for row in Model.objects.all(): + setattr(row, column_to_encrypt, getattr(row, temporary_column)) + row.save(update_fields=[column_to_encrypt]) + +class Migration(migrations.Migration): + + dependencies = [ + (app_with_model, '0053_merge'), + ] + + operations = [ + # create temporary column + migrations.AddField( + model_name=model_with_column.lower(), + name=temporary_column, + field=column_field_class( + verbose_name=temporary_column, null=True, **column_attrs), + ), + # allow null entries in the real column + migrations.AlterField( + model_name=model_with_column.lower(), + name=column_to_encrypt, + field=column_field_class( + verbose_name=column_to_encrypt, null=True, **column_attrs), + ), + # push all data from real to temporary + migrations.RunPython(replicate_to_temporary), + # encrypt the real column (still allowing null values) + migrations.AlterField( + model_name=model_with_column.lower(), + name=column_to_encrypt, + field=encrypt(column_field_class( + verbose_name=column_to_encrypt, null=True, **column_attrs)), + ), + # push all data from temporary to real (encrypting in the processes) + migrations.RunPython(replicate_to_real), + # remove the temporary column + migrations.RemoveField( + model_name=model_with_column.lower(), + name=temporary_column), + # disallow null values (if applicable) + migrations.AlterField( + model_name=model_with_column.lower(), + name=column_to_encrypt, + field=encrypt(column_field_class( + verbose_name=column_to_encrypt, null=column_null_status, + **column_attrs)), + ), + ] diff --git a/anagrafica/migrations/0055_auto_20191027_2224.py b/anagrafica/migrations/0055_auto_20191027_2224.py deleted file mode 100644 index 9a279c38d..000000000 --- a/anagrafica/migrations/0055_auto_20191027_2224.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.13 on 2019-10-27 22:24 -from __future__ import unicode_literals - -import anagrafica.validators -import base.utils -from django.db import migrations, models -import django_cryptography.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('anagrafica', '0054_auto_20191027_2220'), - ] - - operations = [ - migrations.AlterField( - model_name='persona', - name='codice_fiscale', - field=django_cryptography.fields.encrypt(base.utils.UpperCaseCharField(db_index=True, max_length=16, unique=True, validators=[anagrafica.validators.valida_codice_fiscale], verbose_name='Codice Fiscale')), - ), - migrations.AlterField( - model_name='persona', - name='domicilio_indirizzo', - field=django_cryptography.fields.encrypt(models.CharField(blank=True, max_length=512, null=True, verbose_name='Indirizzo di domicilio')), - ), - migrations.AlterField( - model_name='persona', - name='domicilio_provincia', - field=django_cryptography.fields.encrypt(models.CharField(blank=True, max_length=2, null=True, verbose_name='Provincia di domicilio')), - ), - ] diff --git a/anagrafica/models.py b/anagrafica/models.py index d88e5bb34..7b516087f 100755 --- a/anagrafica/models.py +++ b/anagrafica/models.py @@ -60,8 +60,8 @@ class Persona(ModelloSemplice, ConMarcaTemporale, ConAllegati, ConVecchioID): # Informazioni anagrafiche nome = TitleCharField("Nome", max_length=64, db_index=True) cognome = encrypt(TitleCharField("Cognome", max_length=64, db_index=True)) - codice_fiscale = encrypt(UpperCaseCharField("Codice Fiscale", max_length=16, blank=False, - unique=True, db_index=True, validators=[valida_codice_fiscale,])) + codice_fiscale = UpperCaseCharField("Codice Fiscale", max_length=16, blank=False, + unique=True, db_index=True, validators=[valida_codice_fiscale,]) data_nascita = models.DateField("Data di nascita", db_index=True, null=True) genere = models.CharField("Sesso", max_length=1, choices=GENERE, db_index=True) stato = models.CharField("Stato", max_length=1, choices=STATO, default=PERSONA, db_index=True) @@ -79,9 +79,9 @@ class Persona(ModelloSemplice, ConMarcaTemporale, ConAllegati, ConVecchioID): # Domicilio domicilio_uguale_a_residenza = models.BooleanField(default=False, verbose_name='Domicilio uguale a residenza') - domicilio_indirizzo = encrypt(models.CharField("Indirizzo di domicilio", max_length=512, null=True, blank=True)) + domicilio_indirizzo = models.CharField("Indirizzo di domicilio", max_length=512, null=True, blank=True) domicilio_comune = models.CharField("Comune di domicilio", max_length=64, null=True, blank=True) - domicilio_provincia = encrypt(models.CharField("Provincia di domicilio", max_length=2, null=True, blank=True)) + domicilio_provincia = models.CharField("Provincia di domicilio", max_length=2, null=True, blank=True) domicilio_stato = CountryField("Stato di domicilio", default="IT", null=True, blank=True) domicilio_cap = models.CharField("CAP di domicilio", max_length=16, null=True, blank=True)