From cbb45f5b05622080239cc3e8818d74a6c4ca9411 Mon Sep 17 00:00:00 2001
From: Serghei Mihai <smihai@entrouvert.com>
Date: Tue, 26 Jan 2021 11:30:44 +0100
Subject: [PATCH 2/2] mdel: add SFTP connection options to send and receive
 demand file (#50543)

---
 .../migrations/0006_auto_20210126_1440.py     | 26 ++++++++++++++
 passerelle/apps/mdel/models.py                | 34 +++++++++++++++++++
 tests/test_mdel.py                            | 20 +++++++++++
 3 files changed, 80 insertions(+)
 create mode 100644 passerelle/apps/mdel/migrations/0006_auto_20210126_1440.py

diff --git a/passerelle/apps/mdel/migrations/0006_auto_20210126_1440.py b/passerelle/apps/mdel/migrations/0006_auto_20210126_1440.py
new file mode 100644
index 00000000..7cba7afa
--- /dev/null
+++ b/passerelle/apps/mdel/migrations/0006_auto_20210126_1440.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.29 on 2021-01-26 13:40
+from __future__ import unicode_literals
+
+from django.db import migrations
+import passerelle.utils.sftp
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('mdel', '0005_remove_mdel_log_level'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='mdel',
+            name='incoming_sftp',
+            field=passerelle.utils.sftp.SFTPField(blank=True, default=None, verbose_name='SFTP server for incoming files'),
+        ),
+        migrations.AddField(
+            model_name='mdel',
+            name='outcoming_sftp',
+            field=passerelle.utils.sftp.SFTPField(blank=True, default=None, verbose_name='SFTP server for outgoing files'),
+        ),
+    ]
diff --git a/passerelle/apps/mdel/models.py b/passerelle/apps/mdel/models.py
index f1822b89..64ca7b42 100644
--- a/passerelle/apps/mdel/models.py
+++ b/passerelle/apps/mdel/models.py
@@ -25,6 +25,7 @@ from passerelle.base.models import BaseResource
 from passerelle.compat import json_loads
 from passerelle.utils.api import endpoint
 from passerelle.utils.jsonresponse import APIError
+from passerelle.utils import SFTPField
 
 from . import mdel
 
@@ -74,6 +75,10 @@ class MDEL(BaseResource):
     - Acte d'Etat Civil (AEC-LA)
     - Recensement Citoyen Obligatoire (RCO-LA)
     """
+
+    outcoming_sftp = SFTPField(verbose_name=_('SFTP server for outgoing files'), blank=True)
+    incoming_sftp = SFTPField(verbose_name=_('SFTP server for incoming files'), blank=True)
+
     category = _('Civil Status Connectors')
 
     class Meta:
@@ -120,6 +125,9 @@ class MDEL(BaseResource):
 
         demand.save()
 
+        if self.outcoming_sftp:
+            self.add_job('send_demand', demand_id=demand.demand_id)
+
         return {'data': {'demand_id': demand.demand_id}}
 
     @endpoint(perm='can_access')
@@ -161,6 +169,28 @@ class MDEL(BaseResource):
         return os.path.join(mdel.get_resource_base_dir(),
                             self.slug, 'outputs')
 
+    def send_demand(self, demand_id):
+        try:
+            demand = Demand.objects.get(demand_id=demand_id)
+        except Demand.DoesNotExist:
+            return
+        with self.outcoming_sftp.client() as client:
+            client.put(demand.filepath,
+                       os.path.join(client.getcwd(), demand.filename))
+
+    def get_response_files(self):
+        if not os.path.exists(self.output_dir):
+            os.makedirs(self.output_dir)
+
+        with self.incoming_sftp.client() as client:
+            for filename in client.listdir():
+                client.get(filename, os.path.join(self.output_dir, filename))
+
+    def hourly(self):
+        super().hourly()
+        if self.incoming_sftp:
+            self.get_response_files()
+
 
 @six.python_2_unicode_compatible
 class Demand(models.Model):
@@ -194,6 +224,10 @@ class Demand(models.Model):
     def filename(self):
         return '%s.zip' % self.name
 
+    @property
+    def filepath(self):
+        return os.path.join(self.resource.input_dir, self.filename)
+
     def create_zip(self, formdata):
         """
         Creates demand as zip folder
diff --git a/tests/test_mdel.py b/tests/test_mdel.py
index 61876f23..52d4c6fd 100644
--- a/tests/test_mdel.py
+++ b/tests/test_mdel.py
@@ -31,6 +31,7 @@ from passerelle.apps.mdel.models import MDEL, Demand
 from passerelle.apps.mdel.mdel import Message, Description, AttachedFile, get_resource_base_dir
 from passerelle.apps.mdel.utils import parse_date
 from passerelle.compat import json_loads
+from passerelle.utils import SFTP
 
 import utils
 
@@ -305,6 +306,25 @@ def test_create_aec_demand_type(app, setup, aec_payload):
         assert root.find('DemandeActe/Titulaire/Filiation/Pere/Prenoms').text == 'Ryu'
 
 
+def test_create_aec_demand_with_output_sftp(app, setup, aec_payload, sftpserver):
+    setup.outcoming_sftp = SFTP('sftp://foo:bar@{server.host}:{server.port}/output/'.format(server=sftpserver))
+    setup.save()
+    resp = app.post_json('/mdel/test/create', params=aec_payload, status=200)
+    expected_filename = '%s-0.zip' % resp.json['data']['demand_id']
+    with sftpserver.serve_content({'output': {expected_filename: 'content'}}):
+        setup.jobs()
+
+
+def test_create_aec_demand_with_input_sftp(app, setup, aec_payload, sftpserver):
+    setup.incoming_sftp = SFTP('sftp://foo:bar@{server.host}:{server.port}/input/'.format(server=sftpserver))
+    setup.save()
+    resp = app.post_json('/mdel/test/create', params=aec_payload, status=200)
+    expected_filename = '%s-1.zip' % resp.json['data']['demand_id']
+    with sftpserver.serve_content({'input': {expected_filename: 'content'}}):
+        setup.hourly()
+    assert expected_filename in os.listdir(setup.output_dir)
+
+
 def test_create_aec_demand_type_without_date_acte(app, setup):
     payload = json_loads(get_file_from_test_base_dir('formdata_aec_deces.json'))
     payload['fields'].pop('date_acte')
-- 
2.30.0

