cartads cs: sync subscribers with authentic role (#36888)

This commit is contained in:
Frédéric Péters 2019-10-09 20:54:14 +02:00
parent 57c124de38
commit 99d0eb02a4
2 changed files with 67 additions and 0 deletions

View File

@ -37,6 +37,7 @@ from django.core.urlresolvers import reverse
from django.db import models
from django.http import HttpResponse
from django.utils.encoding import force_text
from django.utils.text import slugify
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from django.utils.six.moves.urllib import parse as urlparse
@ -46,6 +47,7 @@ import zeep.exceptions
import zeep.helpers as zeep_helpers
from passerelle.base.models import BaseResource
from passerelle.base.signature import sign_url
from passerelle.utils.api import endpoint
from passerelle.utils.jsonresponse import APIError, JSONEncoder
@ -321,6 +323,7 @@ class AbstractCartaDSCS(BaseResource):
except zeep.exceptions.Fault as e:
self.logger.exception('error getting dossier infos (%s) (%r)', dossier.id, e.message)
dossier.save()
self.sync_subscribers_role(dossier)
def hourly(self):
super(AbstractCartaDSCS, self).hourly()
@ -790,6 +793,7 @@ class AbstractCartaDSCS(BaseResource):
if notification.find('Succes').text == 'true':
dossier.cartads_id_dossier = notification.find('InformationsComplementaires/IdDossierCartads').text
dossier.cartads_numero_dossier = notification.find('InformationsComplementaires/NumeroDossier').text
self.sync_subscribers_role(dossier)
dossier.save()
return HttpResponse('ok', content_type='text/plain')
@ -1059,6 +1063,7 @@ class AbstractCartaDSCS(BaseResource):
dossier.save()
dossier.subscribers.add(CartaDSSubscriber.objects.get_or_create(name_id=name_id)[0])
self.sync_subscribers_role(dossier)
return {'err': 0,
'dossier_id': dossier.id,
'formdata_url': dossier.formdata_url,
@ -1089,8 +1094,43 @@ class AbstractCartaDSCS(BaseResource):
if subscriber not in dossier.subscribers.all():
raise APIError('subscriber not subscribed to that dossier')
dossier.subscribers.remove(subscriber)
self.sync_subscribers_role(dossier)
return {'err': 0, 'dossier_id': dossier.id}
def sync_subscribers_role(self, dossier):
if not getattr(settings, 'KNOWN_SERVICES', {}).get('authentic'):
return
dossier_number = dossier.cartads_numero_dossier
idp_service = settings.KNOWN_SERVICES['authentic'].values()[0]
# sync subscribers with an authentic role, this can fail and it will
# be retried again later.
role_api_url = sign_url(
urlparse.urljoin(
idp_service['url'],
'api/roles/?get_or_create=slug&orig=%s' % idp_service.get('orig')),
key=idp_service.get('secret'))
response = self.requests.post(role_api_url,
json={'name': 'Suivi Cart@DS %s' % dossier_number,
'slug': '_cartads_%s' % slugify(dossier_number),
})
if response.status_code != 200:
return
try:
role_uuid = response.json()['uuid']
except (KeyError, TypeError, ValueError):
return
role_api_url = sign_url(
urlparse.urljoin(
idp_service['url'],
'api/roles/%s/relationships/members/?orig=%s' % (
role_uuid,
idp_service.get('orig')
)),
key=idp_service.get('secret'))
response = self.requests.patch(role_api_url,
json={'data': [{'uuid': x.name_id} for x in dossier.subscribers.all()]}
)
class CartaDSCS(AbstractCartaDSCS):
category = _('Misc')

View File

@ -2,6 +2,7 @@
from collections import OrderedDict
import datetime
import json
import os
import mock
@ -9,6 +10,7 @@ from httmock import HTTMock
import pytest
from django.core.files.storage import default_storage
from django.test import override_settings
from passerelle.apps.cartads_cs.models import CartaDSCS, CartaDSFile, CartaDSDossier
from passerelle.base.models import Job
@ -637,3 +639,28 @@ def test_unsubscribe(connector, app, cached_data):
assert resp.json['err'] == 1
resp = app.get('/cartads-cs/test/unsubscribe?name_id=4567&dossier_number=434')
assert resp.json['err'] == 1
def test_role_sync(connector, app, cached_data):
def idp_mock(url, request):
assert url.netloc == 'idp.example.org'
if url.path == '/api/roles/':
assert request.body == '{"name": "Suivi Cart@DS 123", "slug": "_cartads_123"}'
return {'content': json.dumps({'uuid': 'role-uuid'}), 'status_code': 200}
elif url.path == '/api/roles/role-uuid/relationships/members/':
body = json.loads(request.body)
idp_mock.subscribed_roles = set([x['uuid'] for x in body['data']])
return {'content': json.dumps({'err': 0}), 'status_code': 200}
raise Exception('unhandled http call (%s)' % url)
with HTTMock(idp_mock), override_settings(
KNOWN_SERVICES={
'authentic': {
'idp': {
'url': 'http://idp.example.org/',
'verif_orig': 'abc',
'secret': 'def',
}
}}):
test_join(connector, app, cached_data)
assert idp_mock.subscribed_roles == set(['2345', '3456'])