0002-mdel-add-SFTP-connection-options-to-send-and-receive.patch
passerelle/apps/mdel/migrations/0006_auto_20210126_1440.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
# Generated by Django 1.11.29 on 2021-01-26 13:40 |
|
3 |
from __future__ import unicode_literals |
|
4 | ||
5 |
from django.db import migrations |
|
6 |
import passerelle.utils.sftp |
|
7 | ||
8 | ||
9 |
class Migration(migrations.Migration): |
|
10 | ||
11 |
dependencies = [ |
|
12 |
('mdel', '0005_remove_mdel_log_level'), |
|
13 |
] |
|
14 | ||
15 |
operations = [ |
|
16 |
migrations.AddField( |
|
17 |
model_name='mdel', |
|
18 |
name='incoming_sftp', |
|
19 |
field=passerelle.utils.sftp.SFTPField(blank=True, default=None, verbose_name='SFTP server for incoming files'), |
|
20 |
), |
|
21 |
migrations.AddField( |
|
22 |
model_name='mdel', |
|
23 |
name='outcoming_sftp', |
|
24 |
field=passerelle.utils.sftp.SFTPField(blank=True, default=None, verbose_name='SFTP server for outgoing files'), |
|
25 |
), |
|
26 |
] |
passerelle/apps/mdel/models.py | ||
---|---|---|
24 | 24 |
from passerelle.base.models import BaseResource |
25 | 25 |
from passerelle.compat import json_loads |
26 | 26 |
from passerelle.utils.api import endpoint |
27 |
from passerelle.utils.files import atomic_write |
|
27 | 28 |
from passerelle.utils.jsonresponse import APIError |
29 |
from passerelle.utils import SFTPField |
|
28 | 30 | |
29 | 31 |
from . import mdel |
30 | 32 | |
... | ... | |
74 | 76 |
- Acte d'Etat Civil (AEC-LA) |
75 | 77 |
- Recensement Citoyen Obligatoire (RCO-LA) |
76 | 78 |
""" |
79 | ||
80 |
outcoming_sftp = SFTPField(verbose_name=_('SFTP server for outgoing files'), blank=True) |
|
81 |
incoming_sftp = SFTPField(verbose_name=_('SFTP server for incoming files'), blank=True) |
|
82 | ||
77 | 83 |
category = _('Civil Status Connectors') |
78 | 84 | |
79 | 85 |
class Meta: |
... | ... | |
120 | 126 | |
121 | 127 |
demand.save() |
122 | 128 | |
129 |
if self.outcoming_sftp: |
|
130 |
self.add_job('send_demand', demand_id=demand.demand_id) |
|
131 | ||
123 | 132 |
return {'data': {'demand_id': demand.demand_id}} |
124 | 133 | |
125 | 134 |
@endpoint(perm='can_access') |
... | ... | |
161 | 170 |
return os.path.join(mdel.get_resource_base_dir(), |
162 | 171 |
self.slug, 'outputs') |
163 | 172 | |
173 |
def send_demand(self, demand_id): |
|
174 |
try: |
|
175 |
demand = Demand.objects.get(demand_id=demand_id) |
|
176 |
except Demand.DoesNotExist: |
|
177 |
return |
|
178 |
with self.outcoming_sftp.client() as client: |
|
179 |
client.put(demand.filepath, |
|
180 |
os.path.join(client.getcwd(), demand.filename)) |
|
181 | ||
182 |
def get_response_files(self): |
|
183 |
if not os.path.exists(self.output_dir): |
|
184 |
os.makedirs(self.output_dir) |
|
185 | ||
186 |
with self.incoming_sftp.client() as client: |
|
187 |
for filename in client.listdir(): |
|
188 |
if filename in os.listdir(self.output_dir): |
|
189 |
continue |
|
190 |
with atomic_write(os.path.join(self.output_dir, filename)) as fd: |
|
191 |
client.getfo(filename, fd) |
|
192 | ||
193 |
def hourly(self): |
|
194 |
super().hourly() |
|
195 |
if self.incoming_sftp: |
|
196 |
self.get_response_files() |
|
197 | ||
164 | 198 | |
165 | 199 |
@six.python_2_unicode_compatible |
166 | 200 |
class Demand(models.Model): |
... | ... | |
194 | 228 |
def filename(self): |
195 | 229 |
return '%s.zip' % self.name |
196 | 230 | |
231 |
@property |
|
232 |
def filepath(self): |
|
233 |
return os.path.join(self.resource.input_dir, self.filename) |
|
234 | ||
197 | 235 |
def create_zip(self, formdata): |
198 | 236 |
""" |
199 | 237 |
Creates demand as zip folder |
tests/test_mdel.py | ||
---|---|---|
31 | 31 |
from passerelle.apps.mdel.mdel import Message, Description, AttachedFile, get_resource_base_dir |
32 | 32 |
from passerelle.apps.mdel.utils import parse_date |
33 | 33 |
from passerelle.compat import json_loads |
34 |
from passerelle.utils import SFTP |
|
34 | 35 | |
35 | 36 |
import utils |
36 | 37 | |
... | ... | |
305 | 306 |
assert root.find('DemandeActe/Titulaire/Filiation/Pere/Prenoms').text == 'Ryu' |
306 | 307 | |
307 | 308 | |
309 |
def test_create_aec_demand_with_output_sftp(app, setup, aec_payload, sftpserver): |
|
310 |
setup.outcoming_sftp = SFTP('sftp://foo:bar@{server.host}:{server.port}/output/'.format(server=sftpserver)) |
|
311 |
setup.save() |
|
312 |
resp = app.post_json('/mdel/test/create', params=aec_payload, status=200) |
|
313 |
expected_filename = '%s-0.zip' % resp.json['data']['demand_id'] |
|
314 |
with sftpserver.serve_content({'output': {expected_filename: 'content'}}): |
|
315 |
setup.jobs() |
|
316 | ||
317 | ||
318 |
def test_create_aec_demand_with_input_sftp(app, setup, aec_payload, sftpserver): |
|
319 |
setup.incoming_sftp = SFTP('sftp://foo:bar@{server.host}:{server.port}/input/'.format(server=sftpserver)) |
|
320 |
setup.save() |
|
321 |
resp = app.post_json('/mdel/test/create', params=aec_payload, status=200) |
|
322 |
expected_filename = '%s-1.zip' % resp.json['data']['demand_id'] |
|
323 |
with sftpserver.serve_content({'input': {expected_filename: 'content'}}): |
|
324 |
setup.hourly() |
|
325 |
assert expected_filename in os.listdir(setup.output_dir) |
|
326 | ||
327 | ||
308 | 328 |
def test_create_aec_demand_type_without_date_acte(app, setup): |
309 | 329 |
payload = json_loads(get_file_from_test_base_dir('formdata_aec_deces.json')) |
310 | 330 |
payload['fields'].pop('date_acte') |
311 |
- |