Projet

Général

Profil

0001-solis-afi-mss-provide-url-and-credentials-for-GED-60.patch

Nicolas Roche, 28 janvier 2022 11:20

Télécharger (14 ko)

Voir les différences:

Subject: [PATCH] solis-afi-mss: provide url and credentials for GED (#60557)

 .../migrations/0002_auto_20220128_1001.py     | 51 +++++++++++++++++++
 passerelle/contrib/solis_afi_mss/models.py    | 49 +++++++++++-------
 tests/test_solis_afi_mss.py                   | 10 +++-
 3 files changed, 92 insertions(+), 18 deletions(-)
 create mode 100644 passerelle/contrib/solis_afi_mss/migrations/0002_auto_20220128_1001.py
passerelle/contrib/solis_afi_mss/migrations/0002_auto_20220128_1001.py
1
# Generated by Django 2.2.19 on 2022-01-28 09:01
2

  
3
from django.db import migrations, models
4

  
5

  
6
class Migration(migrations.Migration):
7

  
8
    dependencies = [
9
        ('solis_afi_mss', '0001_initial'),
10
    ]
11

  
12
    operations = [
13
        migrations.AddField(
14
            model_name='solisafimss',
15
            name='ged_basic_auth_password',
16
            field=models.CharField(
17
                blank=True, max_length=128, verbose_name='Basic GED authentication password'
18
            ),
19
        ),
20
        migrations.AddField(
21
            model_name='solisafimss',
22
            name='ged_basic_auth_username',
23
            field=models.CharField(
24
                blank=True, max_length=128, verbose_name='Basic GED authentication username'
25
            ),
26
        ),
27
        migrations.AddField(
28
            model_name='solisafimss',
29
            name='ged_url',
30
            field=models.CharField(
31
                blank=True,
32
                help_text='example: https://solis.mon-application.fr/solisapiged/',
33
                max_length=256,
34
                verbose_name='GED Service URL',
35
            ),
36
        ),
37
        migrations.AlterField(
38
            model_name='solisafimss',
39
            name='base_url',
40
            field=models.CharField(
41
                help_text='example: https://msppsolis.mon-application.fr/solisAPI/',
42
                max_length=256,
43
                verbose_name='Service URL',
44
            ),
45
        ),
46
        migrations.AlterField(
47
            model_name='solisafimss',
48
            name='verify_cert',
49
            field=models.BooleanField(blank=True, default=True, verbose_name='TLS verify certificates'),
50
        ),
51
    ]
passerelle/contrib/solis_afi_mss/models.py
10 10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 12
# GNU Affero General Public License for more details.
13 13
#
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import base64
18
from urllib.parse import urljoin
19 18

  
20 19
from django.db import models
21 20
from django.utils.translation import ugettext_lazy as _
22 21

  
23 22
from passerelle.base.models import BaseResource, HTTPResource
24 23
from passerelle.utils.api import endpoint
25 24
from passerelle.utils.jsonresponse import APIError
26 25

  
......
133 132
}
134 133

  
135 134

  
136 135
class SolisAfiMss(BaseResource, HTTPResource):
137 136
    base_url = models.CharField(
138 137
        max_length=256,
139 138
        blank=False,
140 139
        verbose_name=_('Service URL'),
141
        help_text=_('example: https://solis.mon-application.fr/api-mss-afi/'),
140
        help_text=_('example: https://msppsolis.mon-application.fr/solisAPI/'),
141
    )
142
    ged_url = models.CharField(
143
        max_length=256,
144
        blank=True,
145
        verbose_name=_('GED Service URL'),
146
        help_text=_('example: https://solis.mon-application.fr/solisapiged/'),
147
    )
148
    ged_basic_auth_username = models.CharField(
149
        max_length=128, verbose_name=_('Basic GED authentication username'), blank=True
150
    )
151
    ged_basic_auth_password = models.CharField(
152
        max_length=128, verbose_name=_('Basic GED authentication password'), blank=True
142 153
    )
143 154

  
144 155
    category = _('Business Process Connectors')
145 156

  
146 157
    class Meta:
147 158
        verbose_name = _('Solis (mss-afi)')
148 159

  
149
    def request(self, uri, params=None, json=None, files=None):
150
        url = urljoin(self.base_url, uri)
160
    def request(self, url, params=None, json=None, files=None, **kwargs):
151 161
        headers = {'Accept': 'application/json'}
152 162
        if json:
153
            response = self.requests.post(url, json=json, headers=headers)
163
            response = self.requests.post(url, json=json, headers=headers, **kwargs)
154 164
        elif files:
155
            response = self.requests.post(url, files=files, params=params, headers=headers)
165
            response = self.requests.post(url, files=files, params=params, headers=headers, **kwargs)
156 166
        else:
157
            response = self.requests.get(url, params=params, headers=headers)
167
            response = self.requests.get(url, params=params, headers=headers, **kwargs)
158 168

  
159 169
        if response.status_code // 100 != 2:
160 170
            try:
161 171
                json_content = response.json()
162 172
            except ValueError:
163 173
                json_content = None
164 174
            raise APIError(
165 175
                'error status:%s %r, content:%r'
......
182 192
        json_response.pop('err_desc', None)
183 193

  
184 194
        return json_response
185 195

  
186 196
    def check_status(self):
187 197
        """
188 198
        Raise an exception if something goes wrong.
189 199
        """
190
        return self.request('main/isAlive/')
200
        return self.request(self.base_url + 'main/isAlive/')
191 201

  
192 202
    def search_from_email(self, email):
193
        response = self.request('afi/agent/rechercherParEmail/', params={'adresseMail': email})
203
        response = self.request(
204
            self.base_url + 'afi/agent/rechercherParEmail/', params={'adresseMail': email}
205
        )
194 206
        index = response.get('indexAgent')
195 207

  
196 208
        adults = []
197 209
        for key in ('agent', 'conjointAgent'):
198 210
            if response.get(key):
199 211
                adults.append(response.get(key))
200 212
        children = response.get('enfantsAgent')
201 213
        for record in adults + children:
......
271 283
        description=_("Update contact details for an agent"),
272 284
        parameters={
273 285
            'email': {'description': _("Agent's email address")},
274 286
        },
275 287
        post={'request_body': {'schema': {'application/json': CONTACT_SCHEMA}}},
276 288
    )
277 289
    def update_contact(self, request, email, post_data):
278 290
        post_data['indexAgent'] = str(self.search_from_email(email)['index'])
279
        response = self.request('afi/agent/updateCoordonnees/', json=post_data)
291
        response = self.request(self.base_url + 'afi/agent/updateCoordonnees/', json=post_data)
280 292
        return {'data': response}
281 293

  
282 294
    @endpoint(
283 295
        display_category=_('Budget'),
284 296
        display_order=1,
285 297
        perm='can_access',
286 298
        methods=['get'],
287 299
        description=_('Retrieve the list of charges for an agent'),
......
291 303
        },
292 304
    )
293 305
    def taxes(self, request, email, year=None):
294 306
        index = self.search_from_email(email)['index']
295 307
        params = {'indexAgent': str(index)}
296 308

  
297 309
        if year:
298 310
            params['anneeImposition'] = year
299
            response = self.request('afi/budget/getImposition/', params=params)
311
            response = self.request(self.base_url + 'afi/budget/getImposition/', params=params)
300 312
            data = [response] if response else []
301 313
        else:
302
            response = self.request('afi/budget/getImpositionsParAgent/', params=params)
314
            response = self.request(self.base_url + 'afi/budget/getImpositionsParAgent/', params=params)
303 315
            data = response.get('listeImposition')
304 316

  
305 317
        for record in data:
306 318
            record['id'] = record.get('anneeImposition')
307 319
            record['text'] = '%(anneeImposition)s: %(montantImposition)s' % record
308 320
        return {'data': data}
309 321

  
310 322
    @endpoint(
......
316 328
        description=_("Register an agent's tax for one year"),
317 329
        parameters={
318 330
            'email': {'description': _("Agent's email address")},
319 331
        },
320 332
        post={'request_body': {'schema': {'application/json': TAX_SCHEMA}}},
321 333
    )
322 334
    def declare_tax(self, request, email, post_data):
323 335
        post_data['indexAgent'] = str(self.search_from_email(email)['index'])
324
        response = self.request('afi/budget/declarerImpot/', json=post_data)
336
        response = self.request(self.base_url + 'afi/budget/declarerImpot/', json=post_data)
325 337
        return {'data': response}
326 338

  
327 339
    @endpoint(
328 340
        display_category=_('Budget'),
329 341
        display_order=3,
330 342
        name='simulate-quotient',
331 343
        perm='can_access',
332 344
        methods=['get'],
......
337 349
        },
338 350
    )
339 351
    def simulate_quotient(self, request, code, nb_parts, amount):
340 352
        params = {
341 353
            'codeCalcul': code,
342 354
            'nbrPartImposition': nb_parts,
343 355
            'mntImposition': amount,
344 356
        }
345
        response = self.request('afi/budget/calculer/', params=params)
357
        response = self.request(self.base_url + 'afi/budget/calculer/', params=params)
346 358
        return {'data': response}
347 359

  
348 360
    @endpoint(
349 361
        display_category=_('Allowance'),
350 362
        display_order=1,
351 363
        perm='can_access',
352 364
        methods=['get'],
353 365
        description=_('Retrieve the list of allowance from an agent'),
354 366
        parameters={
355 367
            'email': {'description': _("Agent's email address")},
356 368
            'text_template': {'description': _('Text template')},
357 369
        },
358 370
    )
359 371
    def helps(self, request, email):
360 372
        params = {'indexAgent': str(self.search_from_email(email)['index'])}
361
        response = self.request('afi/aide/getAidesParAgent/', params=params)
373
        response = self.request(self.base_url + 'afi/aide/getAidesParAgent/', params=params)
362 374

  
363 375
        for record in response['aidesFinancieres']:
364 376
            record['id'] = record.get('indexAideFinanciere')
365 377
            record['text'] = '%(dateDemandeAide)s (%(suiviAide)s)' % record
366 378
        return {'data': response['aidesFinancieres']}
367 379

  
368 380
    @endpoint(
369 381
        display_category=_('Allowance'),
......
383 395
        related_persons = []
384 396
        for person in results['adults'] + results['children']:
385 397
            for index in [x.strip() for x in post_data['individusConcernes'].split(':') if x.strip()]:
386 398
                if str(person['indexIndividu']) == index:
387 399
                    related_persons.append({"indexIndividu": index})
388 400

  
389 401
        post_data['indexAgent'] = str(results['index'])
390 402
        post_data['individusConcernes'] = related_persons
391
        response = self.request('afi/aide/deposer/', json=post_data)
403
        response = self.request(self.base_url + 'afi/aide/deposer/', json=post_data)
392 404
        return {'data': response}
393 405

  
394 406
    @endpoint(
395 407
        display_category=_('Allowance'),
396 408
        display_order=3,
397 409
        name='add-document',
398 410
        perm='can_access',
399 411
        methods=['post'],
......
413 425
            params['typeIdMetierClassement'] = 'INDIVIDU'
414 426
            params['idMetierClassement'] = str(self.search_from_email(email)['index'])
415 427
        else:
416 428
            raise APIError("'email' or 'indexAideFinanciere' is a required property", http_status=400)
417 429

  
418 430
        document = post_data['document']
419 431
        content = base64.b64decode(document['content'])
420 432
        files = {'document': (document['filename'], content, document['content_type'])}
421
        response = self.request('ged/web/document/deposer', params=params, files=files)
433
        auth = (self.ged_basic_auth_username, self.ged_basic_auth_password)
434
        response = self.request(
435
            self.ged_url + 'ged/web/document/deposer', params=params, files=files, auth=auth
436
        )
422 437
        return {'data': response}
tests/test_solis_afi_mss.py
25 25

  
26 26
from passerelle.contrib.solis_afi_mss.models import SolisAfiMss
27 27
from passerelle.utils.jsonresponse import APIError
28 28

  
29 29

  
30 30
@pytest.fixture
31 31
def connector(db):
32 32
    return utils.setup_access_rights(
33
        SolisAfiMss.objects.create(slug='test', base_url='https://solis-afi-mss.example.net')
33
        SolisAfiMss.objects.create(
34
            slug='test',
35
            base_url='https://solis-afi-mss.example.net/',
36
            ged_url='https://solis-ged-mss.example.net/',
37
            ged_basic_auth_username='jdoe',
38
            ged_basic_auth_password='xxx',
39
        )
34 40
    )
35 41

  
36 42

  
37 43
TEST_BASE_DIR = os.path.join(os.path.dirname(__file__), 'data', 'solis_afi_mss')
38 44

  
39 45

  
40 46
def json_get_data(filename):
41 47
    with open(os.path.join(TEST_BASE_DIR, "%s.json" % filename)) as fd:
......
702 708
        'document': {
703 709
            'filename': '201x201.jpg',
704 710
            'content_type': 'image/jpeg',
705 711
            'content': force_text(base64.b64encode(get_media_file('201x201.jpg'))),
706 712
        },
707 713
    }
708 714

  
709 715
    resp = app.post_json(endpoint + '?email=foo@dummy.org', params=payload)
716
    assert mocked_post.mock_calls[0][1][0] == 'https://solis-ged-mss.example.net/ged/web/document/deposer'
717
    assert mocked_post.mock_calls[0][2]['auth'] == ('jdoe', 'xxx')
710 718
    assert mocked_post.mock_calls[0][2]['files']['document'][1] == get_media_file('201x201.jpg')
711 719
    assert mocked_post.mock_calls[0][2]['params'] == {
712 720
        'codeGedDocument': 9,
713 721
        'typeIdMetierClassement': 'INDIVIDU',
714 722
        'idMetierClassement': '389227',
715 723
    }
716 724
    assert not resp.json['err']
717 725

  
718
-