import os.path import subprocess import tempfile from datetime import date, timedelta from pathlib import Path from django.conf import settings from django.contrib.auth.models import Group, Permission from django.core.files import File from django.test import TestCase, override_settings from django.urls import reverse from django.utils.text import slugify from aemo.models import ( Bilan, Document, Famille, LibellePrestation, Personne, Role, Prestation, Rapport, Utilisateur ) from aemo.tests import InitialDataMixin, TempMediaRootMixin from aemo.utils import format_d_m_Y from ..models import Archive public_key_path = os.path.join(settings.BASE_DIR, 'archive/tests/crne_rsa.pub') @override_settings(CRNE_RSA_PUBLIC_KEY=public_key_path) class ArchiveTests(InitialDataMixin, TempMediaRootMixin, TestCase): def setUp(self) -> None: self.user = Utilisateur.objects.create_user('user', 'user@example.org', sigle='XX') self.create_kwargs = { 'nom': 'John Doe', 'unite': 'aemo', 'date_debut': date(2021, 1, 1), 'date_fin': date(2021, 12, 31), 'motif_fin': 'Autre', 'key': '', 'pdf': 'encrypted_data' } def _create_archive(self): fam = Famille.objects.create_famille(nom='Haddock', equipe='aemo') fam.suivi.date_fin_suivi = date(2019, 1, 1) fam.suivi.motif_fin_suivi = 'autres' fam.suivi.save() for idx, doc_name in enumerate(['sample.docx', 'sample.doc', 'sample.pdf', 'sample.msg']): doc = Document(famille=fam, titre=f"Test {idx}") with (Path(__file__).parent / doc_name).open(mode='rb') as fh: doc.fichier = File(fh, name=doc_name) doc.save() self.user.user_permissions.add(Permission.objects.get(codename='can_archive')) self.client.force_login(self.user) self.client.post(reverse('archive-add', args=['aemo', fam.pk])) return Archive.objects.get(nom='Haddock', unite='aemo') def test_model_creation(self): arch = Archive.objects.create(**self.create_kwargs) self.assertEqual(arch.nom, 'John Doe') self.assertEqual(arch.unite, 'aemo') self.assertEqual(arch.date_debut, date(2021, 1, 1)) self.assertEqual(arch.date_fin, date(2021, 12, 31)) self.assertEqual(arch.pdf, 'encrypted_data') def test_sans_permission_d_archiver(self): fam = Famille.objects.create_famille(nom='Haddock', equipe='aemo') fam.suivi.date_fin_suivi = date(2019, 1, 1) fam.suivi.motif_fin_suivi = 'autre' fam.suivi.save() self.assertEqual(fam.can_be_archived(self.user), False) def test_avec_permission_d_archiver(self): fam = Famille.objects.create_famille(nom='Haddock', equipe='aemo') fam.suivi.date_fin_suivi = date(2019, 1, 1) fam.suivi.motif_fin_suivi = 'autre' fam.suivi.save() self.user.user_permissions.add(Permission.objects.get(codename='can_archive')) self.assertEqual(fam.can_be_archived(self.user), True) def test_archivage_aemo(self): famille = Famille.objects.create_famille( nom='Doe', equipe='aemo', rue="Rue du lac", npa='2000', localite='Paris', telephone='012 345 67 89') famille.suivi.date_fin_suivi = date.today() - timedelta(days=700) famille.suivi.motif_fin_suivi = 'autre' famille.suivi.save() file_paths = [] for idx, doc_name in enumerate(['sample.docx', 'sample.doc', 'sample.pdf', 'sample.msg', 'sample-2.msg']): doc = Document(famille=famille, titre=f"Test {idx}") with (Path(__file__).parent / doc_name).open(mode='rb') as fh: doc.fichier = File(fh, name=doc_name) doc.save() file_paths.append(doc.fichier.path) Personne.objects.create_personne( famille=famille, prenom='Archibald', nom='Doe', role=Role.objects.get(nom='Père') ) enfant = Personne.objects.create_personne( famille=famille, prenom='Gaston', nom='Doe', date_naissance=date.today() - timedelta(days=720), role=Role.objects.get(nom='Enfant suivi') ) enfant.formation.creche = 'Les Schtroumpfs' enfant.formation.save() Bilan.objects.create(famille=famille, date=date.today()) Rapport.objects.create(famille=famille, date=date.today(), auteur=self.user) prest = Prestation.objects.create( famille=famille, auteur=self.user, date_prestation=date.today(), duree=timedelta(hours=2), lib_prestation=LibellePrestation.objects.first()) prest.intervenants.add(self.user, through_defaults={'role': Role.objects.get(nom='Référent')}) with (Path(__file__).parent / 'sample.pdf').open(mode='rb') as fh: prest.fichier = File(fh, name=doc_name) prest.save() file_paths.append(prest.fichier.path) grp = Group.objects.get(name='aemo') self.user.groups.add(grp) self.user.user_permissions.add( *list(Permission.objects.filter(codename__in=['view_famille', 'change_famille', 'can_archive'])) ) self.assertTrue(famille.can_be_archived(self.user)) self.client.force_login(self.user) response = self.client.post(reverse('archive-add', args=['aemo', famille.pk])) self.assertRedirects(response, reverse('suivis-termines')) famille.refresh_from_db() self.assertNotEqual(famille.nom, 'Doe') self.assertEqual(len(famille.nom), 10) self.assertEqual(famille.rue, '') self.assertEqual(famille.npa, '2000') self.assertEqual(famille.localite, 'Paris'), self.assertEqual(famille.telephone, '') self.assertEqual(famille.parents(), []) enfant.refresh_from_db() self.assertNotEqual(enfant.nom, 'Doe') self.assertEqual(len(famille.nom), 10) self.assertNotEqual(enfant.prenom, 'Gaston') self.assertEqual(len(famille.nom), 10) self.assertEqual(enfant.formation.creche, '') self.assertEqual(famille.documents.count(), 0) self.assertEqual(famille.bilans.count(), 0) self.assertEqual(famille.rapports.count(), 0) for prest in famille.prestations.all(): self.assertEqual(prest.texte, '') self.assertEqual(prest.duree, timedelta(hours=2)) self.assertEqual(bool(prest.fichier), False) for path in file_paths: self.assertFalse(Path(path).exists()) arch = Archive.objects.get(nom='Doe', unite='aemo') self.assertTrue(os.path.exists(arch.pdf.path)) self.assertIn(f"aemo/doe-{famille.pk}", arch.pdf.name) self.assertTrue(famille.prestations.exists()) # Cannot be archived a second time: response = self.client.post(reverse('archive-add', args=['aemo', famille.pk])) self.assertEqual(response.status_code, 404) def test_decryptage_access(self): arch = self._create_archive() private_key = os.path.join(settings.BASE_DIR, 'archive/tests/crne_rsa') anonymous = Utilisateur.objects.create_user('anonymous', email='anonymous@example.org') self.client.force_login(anonymous) with open(private_key, 'rb') as f: response = self.client.post(reverse('archive-decrypt', args=[arch.pk]), data={'file': f}) self.assertEqual(response.status_code, 403) anonymous.user_permissions.add(Permission.objects.get(codename='can_archive')) self.client.force_login(anonymous) with open(private_key, 'rb') as f: response = self.client.post(reverse('archive-decrypt', args=[arch.pk]), data={'file': f}) self.assertEqual(response.status_code, 200) def test_decryptage_aemo(self): arch = self._create_archive() private_key = os.path.join(settings.BASE_DIR, 'archive/tests/crne_rsa') self.client.force_login(self.user) response = self.client.post(reverse('archive-decrypt', args=[arch.pk]), data={'file': ''}) self.assertEqual(response.context['form'].errors, {'file': ['Ce champ est obligatoire.']}) with open(private_key, 'rb') as f: response = self.client.post(reverse('archive-decrypt', args=[arch.pk]), data={'file': f}) self.assertEqual( response.get('Content-Disposition'), f"attachment; filename={slugify(arch.nom)}.pdf" ) with tempfile.NamedTemporaryFile(delete=True, mode='wb') as fh: fh.write(response.content) subprocess.run(['pdftotext', fh.name], stdout=subprocess.PIPE, stderr=subprocess.PIPE) with open(f'{fh.name}.txt', 'r') as f: content = f.read() self.assertIn('Historique', content) self.assertIn('Fin du suivi le :\n\n01.01.2019', content) self.assertIn('Motif de fin de suivi :\n\nAutres', content) self.assertIn(f"Date d'archivage :\n\n{format_d_m_Y(date.today())}", content) self.assertIn('Famille Haddock', content) self.assertIn('Informations', content) self.assertIn("Fichier docx d’exemple", content) self.assertIn("Exemple de fichier doc", content) self.assertIn("Fichier pdf d’exemple", content) self.assertIn("Kind regards", content)