diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2023-11-16 15:50:38 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2024-04-16 16:38:33 +0200 |
commit | ffd47cbfa1baa5eb2556e38253f548495b4189f1 (patch) | |
tree | a66abf26a5c5a3827e52e2e804ce63863640ca2c | |
parent | 03445eca8b1acff04a0f2ff50d1862f6a6ea1315 (diff) | |
download | Ishtar-ffd47cbfa1baa5eb2556e38253f548495b4189f1.tar.bz2 Ishtar-ffd47cbfa1baa5eb2556e38253f548495b4189f1.zip |
🗃️ GDPR: add related models
-rw-r--r-- | docs/fr/source/administrateur-applicatif.rst | 7 | ||||
-rw-r--r-- | example_project/settings.py | 4 | ||||
-rw-r--r-- | ishtar_common/migrations/0233_gdprlog_gdprperson.py | 45 | ||||
-rw-r--r-- | ishtar_common/models.py | 47 |
4 files changed, 101 insertions, 2 deletions
diff --git a/docs/fr/source/administrateur-applicatif.rst b/docs/fr/source/administrateur-applicatif.rst index 03ef53c39..1f11728ac 100644 --- a/docs/fr/source/administrateur-applicatif.rst +++ b/docs/fr/source/administrateur-applicatif.rst @@ -304,11 +304,14 @@ La journalisation consiste à assurer la traçabilité des actions opérées sur - le type de traitement, - des liens vers les personnes concernées par le traitement. +Si une personne est supprimée de la base de données, nom et prénom de cette personne sont sauvegardées dans une table intermédiaire le temps que des données de journalisation concernant cette personne existent. Les types de traitements identifiés sont : - consultation de l'annuaire (listing de personnes), -- consultation de fiche personne, +- export de l'annuaire, +- consultation de la notice personne, +- export de la notice personne, - création de personne (formulaire ou import), - modification de personne (formulaire, import ou fusion), - suppression de fiche personne. @@ -320,7 +323,7 @@ Cette journalisation est activée par défaut. Elle peut être désactivée par La durée de conservation des données de journalisation est fixée à 6 mois (durée minimale préconisée par la CNIL). Cette durée peut être changée par l'administrateur serveur (paramètre `GDPR_RETENTION_PERIOD` dans le fichier `local_settings.py`) mais il convient de rester dans le cadre légal (sauf exception la durée de conservation ne peut excéder un an). Au-delà de la durée paramétrée les données sont supprimées automatiquement (un script vérifie quotidiennement la péremption des données). -Ces données sont accessibles en consultation uniquement via l'interface d'administrateur aux utilisateurs : statut « super utilisateur » ou dans le groupe « Administrateur RGPD » (et disposant du statut équipe : cf. :ref:`gestion des comptes <gestion-comptes>` ). +Ces données sont accessibles en consultation uniquement (la suppression et la modification ne sont pas possible) via l'interface d'administrateur aux utilisateurs : statut « super utilisateur » ou dans le groupe « Administrateur RGPD » (et disposant du statut équipe : cf. :ref:`gestion des comptes <gestion-comptes>` ). .. note:: Si des utilisateurs disposent d'un statut « super utilisateur » mais ne sont pas administrateur RGPD, il est nécessaire de leur retirer ce statut pour leur donner le groupe « administrateur technique ». diff --git a/example_project/settings.py b/example_project/settings.py index 8e9077aad..74638e353 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -292,6 +292,10 @@ JOINT = " | " # not managed cautiously the dir contening these scripts is not set by default ISHTAR_SCRIPT_DIR = "" +# GDPR +GDPR_LOGGING = True +GDPR_RETENTION_PERIOD = int(30.5 * 6) + 1 # ~ 6 month of logging + # TODO: clean... ISHTAR_FILE_PREFIX = "" ISHTAR_OPE_PREFIX = "OA" diff --git a/ishtar_common/migrations/0233_gdprlog_gdprperson.py b/ishtar_common/migrations/0233_gdprlog_gdprperson.py new file mode 100644 index 000000000..374134fce --- /dev/null +++ b/ishtar_common/migrations/0233_gdprlog_gdprperson.py @@ -0,0 +1,45 @@ +# Generated by Django 2.2.24 on 2023-11-16 15:48 + +import datetime +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), + ('ishtar_common', '0232_default_mandatory_keys_import_permissions'), + ] + + operations = [ + migrations.CreateModel( + name='GDPRPerson', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('raw_name', models.CharField(default='-', max_length=300, verbose_name='Raw name')), + ('person', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='ishtar_common.Person', verbose_name='Person')), + ], + options={ + 'verbose_name': 'GDPR - Person', + 'verbose_name_plural': 'GDPR - Persons', + }, + ), + migrations.CreateModel( + name='GDPRLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date', models.DateTimeField(default=datetime.datetime.now, verbose_name='Date')), + ('ip', models.GenericIPAddressField(verbose_name='IP')), + ('activity', models.CharField(choices=[('DC', 'Directory consultation'), ('DE', 'Directory export'), ('PV', "Viewing a person's notice"), ('PE', "Exporting a person's notice"), ('PC', 'Person creation'), ('PM', 'Person modification'), ('PD', 'Person deletion')], max_length=2, verbose_name='Activity')), + ('persons', models.ManyToManyField(blank=True, to='ishtar_common.GDPRPerson', verbose_name='Persons')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='User')), + ], + options={ + 'verbose_name': 'GDPR - Log', + 'verbose_name_plural': 'GDPR - Logs', + 'ordering': ('date',), + }, + ), + ] diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 696020c58..944cbcf5d 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -3203,6 +3203,53 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem): post_save.connect(cached_label_changed, sender=Person) +GDPR_ACTIVITY = ( + ("DC", _("Directory consultation")), + ("DE", _("Directory export")), + ("PV", _("Viewing a person's notice")), + ("PE", _("Exporting a person's notice")), + ("PC", _("Person creation")), + ("PM", _("Person modification")), + ("PD", _("Person deletion")), +) + + +class GDPRPerson(models.Model): + person = models.ForeignKey(Person, verbose_name=_("Person"), on_delete=models.SET_NULL, + blank=True, null=True) + raw_name = models.CharField(_("Raw name"), max_length=300, default="-") + + class Meta: + verbose_name = _("GDPR - Person") + verbose_name_plural = _("GDPR - Persons") + + def __str__(self): + return self.raw_name + + +class GDPRLog(models.Model): + user = models.ForeignKey(User, verbose_name=_("User"), on_delete=models.PROTECT) + date = models.DateTimeField(verbose_name=_("Date"), default=datetime.datetime.now) + ip = models.GenericIPAddressField(verbose_name=_("IP")) + activity = models.CharField(_("Activity"), max_length=2, choices=GDPR_ACTIVITY) + persons = models.ManyToManyField(GDPRPerson, verbose_name=_("Persons"), blank=True) + + class Meta: + verbose_name = _("GDPR - Log") + verbose_name_plural = _("GDPR - Logs") + ordering = ("date",) + ADMIN_SECTION = _("GDPR") + + @property + def activity_lbl(self): + gdpr_activity_dict = dict(GDPR_ACTIVITY) + if self.activity not in gdpr_activity_dict: + return str(_("Unknown activity :")) + self.activity + return gdpr_activity_dict[self.activity] + + def __str__(self): + return f"{self.user.username} - {self.date} - {self.activity_lbl}" + class ProfileType(GeneralType): groups = models.ManyToManyField(Group, verbose_name=_("Groups"), blank=True) |