Projet

Général

Profil

0001-cartads-cs-sync-subscribers-with-authentic-role-3688.patch

Frédéric Péters, 14 octobre 2019 12:03

Télécharger (6,11 ko)

Voir les différences:

Subject: [PATCH] cartads cs: sync subscribers with authentic role (#36888)

 passerelle/apps/cartads_cs/models.py | 36 ++++++++++++++++++++++++++++
 tests/test_cartads_cs.py             | 27 +++++++++++++++++++++
 2 files changed, 63 insertions(+)
passerelle/apps/cartads_cs/models.py
37 37
from django.db import models
38 38
from django.http import HttpResponse
39 39
from django.utils.encoding import force_text
40
from django.utils.text import slugify
40 41
from django.utils.timezone import now
41 42
from django.utils.translation import ugettext_lazy as _
42 43
from django.utils.six.moves.urllib import parse as urlparse
......
46 47
import zeep.helpers as zeep_helpers
47 48

  
48 49
from passerelle.base.models import BaseResource
50
from passerelle.base.signature import sign_url
49 51
from passerelle.utils.api import endpoint
50 52
from passerelle.utils.jsonresponse import APIError, JSONEncoder
51 53

  
......
321 323
            except zeep.exceptions.Fault as e:
322 324
                self.logger.exception('error getting dossier infos (%s) (%r)', dossier.id, e.message)
323 325
            dossier.save()
326
            self.sync_subscribers_role(dossier)
324 327

  
325 328
    def hourly(self):
326 329
        super(AbstractCartaDSCS, self).hourly()
......
790 793
        if notification.find('Succes').text == 'true':
791 794
            dossier.cartads_id_dossier = notification.find('InformationsComplementaires/IdDossierCartads').text
792 795
            dossier.cartads_numero_dossier = notification.find('InformationsComplementaires/NumeroDossier').text
796
            self.sync_subscribers_role(dossier)
793 797
        dossier.save()
794 798
        return HttpResponse('ok', content_type='text/plain')
795 799

  
......
1059 1063
            dossier.save()
1060 1064

  
1061 1065
        dossier.subscribers.add(CartaDSSubscriber.objects.get_or_create(name_id=name_id)[0])
1066
        self.sync_subscribers_role(dossier)
1062 1067
        return {'err': 0,
1063 1068
                'dossier_id': dossier.id,
1064 1069
                'formdata_url': dossier.formdata_url,
......
1089 1094
        if subscriber not in dossier.subscribers.all():
1090 1095
            raise APIError('subscriber not subscribed to that dossier')
1091 1096
        dossier.subscribers.remove(subscriber)
1097
        self.sync_subscribers_role(dossier)
1092 1098
        return {'err': 0, 'dossier_id': dossier.id}
1093 1099

  
1100
    def sync_subscribers_role(self, dossier):
1101
        if not getattr(settings, 'KNOWN_SERVICES', {}).get('authentic'):
1102
            return
1103
        dossier_number = dossier.cartads_numero_dossier
1104
        idp_service = settings.KNOWN_SERVICES['authentic'].values()[0]
1105
        # sync subscribers with an authentic role, this can fail and it will
1106
        # be retried again later.
1107
        role_api_url = sign_url(
1108
                urlparse.urljoin(
1109
                    idp_service['url'],
1110
                    'api/roles/?get_or_create=slug&orig=%s' % idp_service.get('orig')),
1111
                key=idp_service.get('secret'))
1112
        response = self.requests.patch(role_api_url,
1113
                json={'name': 'Suivi Cart@DS %s' % dossier_number,
1114
                      'slug': '_cartads_%s' % slugify(dossier_number),
1115
                })
1116
        role_uuid = response.json()['uuid']
1117
        role_api_url = sign_url(
1118
                urlparse.urljoin(
1119
                    idp_service['url'],
1120
                    'api/roles/%s/relationships/members/?orig=%s' % (
1121
                        role_uuid,
1122
                        idp_service.get('orig')
1123
                    )),
1124
                key=idp_service.get('secret'))
1125
        response = self.requests.post(role_api_url,
1126
                json={'data': [{'uuid': x.name_id} for x in dossier.subscribers.all()]}
1127
                )
1128
        return {}
1129

  
1094 1130

  
1095 1131
class CartaDSCS(AbstractCartaDSCS):
1096 1132
    category = _('Misc')
tests/test_cartads_cs.py
2 2

  
3 3
from collections import OrderedDict
4 4
import datetime
5
import json
5 6
import os
6 7

  
7 8
import mock
......
9 10
import pytest
10 11

  
11 12
from django.core.files.storage import default_storage
13
from django.test import override_settings
12 14

  
13 15
from passerelle.apps.cartads_cs.models import CartaDSCS, CartaDSFile, CartaDSDossier
14 16
from passerelle.base.models import Job
......
637 639
        assert resp.json['err'] == 1
638 640
        resp = app.get('/cartads-cs/test/unsubscribe?name_id=4567&dossier_number=434')
639 641
        assert resp.json['err'] == 1
642

  
643

  
644
def test_role_sync(connector, app, cached_data):
645
    def idp_mock(url, request):
646
        assert url.netloc == 'idp.example.org'
647
        if url.path == '/api/roles/':
648
            assert request.body == '{"name": "Suivi Cart@DS 123", "slug": "_cartads_123"}'
649
            return {'content': json.dumps({'uuid': 'role-uuid'}), 'status_code': 200}
650
        elif url.path == '/api/roles/role-uuid/relationships/members/':
651
            body = json.loads(request.body)
652
            idp_mock.subscribed_roles = set([x['uuid'] for x in body['data']])
653
            return {'content': json.dumps({'err': 0}), 'status_code': 200}
654
        raise Exception('unhandled http call (%s)' % url)
655

  
656
    with HTTMock(idp_mock), override_settings(
657
            KNOWN_SERVICES={
658
                'authentic': {
659
                    'idp': {
660
                        'url': 'http://idp.example.org/',
661
                        'verif_orig': 'abc',
662
                        'secret': 'def',
663
                        }
664
            }}):
665
        test_join(connector, app, cached_data)
666
        assert idp_mock.subscribed_roles == set(['2345', '3456'])
640
-