mdph13: pass client ip to backend (#31445)

This commit is contained in:
Benjamin Dauvergne 2019-03-15 11:17:20 +01:00
parent 74428481d1
commit 5d3369fd61
2 changed files with 40 additions and 25 deletions

View File

@ -84,16 +84,17 @@ class MDPH13Resource(BaseResource, HTTPResource):
response.raise_for_status()
return content
def call_situation_dossier(self, file_number, secret, dob, email=None):
def call_situation_dossier(self, file_number, secret, dob, email=None, ip=None):
url = self.situation_dossier_url(file_number)
email = email or 'appel-sans-utilisateur@cd13.fr'
content = self.url_get(
url,
headers={
'X-CD13-Secret': base64.b64encode(secret.encode('utf-8')).decode('ascii'),
'X-CD13-Email': email,
'X-CD13-DateNaissBenef': dob.isoformat(),
})
headers = {
'X-CD13-Secret': base64.b64encode(secret.encode('utf-8')).decode('ascii'),
'X-CD13-Email': email,
'X-CD13-DateNaissBenef': dob.isoformat(),
}
if ip:
headers['X-CD13-IP'] = ip
content = self.url_get(url, headers=headers)
data = content.get('data')
if not isinstance(data, dict):
@ -199,8 +200,12 @@ class MDPH13Resource(BaseResource, HTTPResource):
'description': _('Publik known email'),
'example_value': 'john.doe@example.com',
},
'ip': {
'description': _('Publik client IP'),
'example_value': '88.67.23.45',
},
})
def link(self, request, NameID, numero_dossier, secret, date_de_naissance, email):
def link(self, request, NameID, numero_dossier, secret, date_de_naissance, email, ip=None):
file_number = numero_dossier.strip()
try:
int(file_number)
@ -220,7 +225,8 @@ class MDPH13Resource(BaseResource, HTTPResource):
file_number=file_number,
secret=secret,
dob=dob,
email=email)
email=email,
ip=ip)
return {'link_id': link.pk, 'created': created, 'updated': updated}
@endpoint(name='unlink',
@ -266,9 +272,13 @@ class MDPH13Resource(BaseResource, HTTPResource):
'link_id': {
'description': _('Link identifier'),
'example_value': '1',
}
},
'ip': {
'description': _('Publik client IP'),
'example_value': '88.67.23.45',
},
})
def dossiers(self, request, NameID, email, link_id=None):
def dossiers(self, request, NameID, email, link_id=None, ip=None):
email = email.strip()
if not self.EMAIL_RE.match(email):
raise APIError('email is not valid', http_status=400)
@ -291,7 +301,7 @@ class MDPH13Resource(BaseResource, HTTPResource):
'err': 0,
}
try:
file_data['dossier'] = link.get_file(email=email)
file_data['dossier'] = link.get_file(email=email, ip=ip)
except Exception as e:
if link_id:
raise
@ -328,13 +338,14 @@ class Link(models.Model):
max_length=128,
blank=True)
def get_file(self, email=None):
def get_file(self, email=None, ip=None):
# email is necessary for audit purpose
mdph_file = self.resource.call_situation_dossier(
file_number=self.file_number,
secret=self.secret,
dob=self.dob,
email=email)
email=email,
ip=ip)
display_name = self._make_display_name(mdph_file)
if self.display_name != display_name:
self.display_name = display_name
@ -342,13 +353,14 @@ class Link(models.Model):
return mdph_file
@classmethod
def create_or_update(self, resource, NameID, file_number, secret, dob, email=None):
def create_or_update(self, resource, NameID, file_number, secret, dob, email=None, ip=None):
# email is necessary for audit purpose
mdph_file = resource.call_situation_dossier(
file_number=file_number,
secret=secret,
dob=dob,
email=email)
email=email,
ip=ip)
display_name = self._make_display_name(mdph_file)
link, created = Link.objects.get_or_create(

View File

@ -37,6 +37,7 @@ DOB = datetime.date(1993, 5, 4)
DOB_ISOFORMAT = '1993-05-04'
EMAIL = 'john.doe@example.com'
SECRET = 'secret'
IP = '88.34.56.56'
VALID_RESPONSE = json.dumps({
'err': 0,
@ -246,11 +247,12 @@ def test_call_situation_dossier(mdph13, mock_http):
assert headers['X-CD13-Secret'] == base64.b64encode(SECRET.encode('utf-8')).decode('ascii')
assert headers['X-CD13-DateNaissBenef'] == '1993-05-04'
assert headers['X-CD13-Email'] == 'appel-sans-utilisateur@cd13.fr'
assert 'X-CD13-IP' not in headers
def test_call_situation_dossier_with_email(mdph13, mock_http):
def test_call_situation_dossier_with_email_and_ip(mdph13, mock_http):
mock_http.add_response(VALID_RESPONSE)
mdph13.call_situation_dossier(1234, SECRET, DOB, email=EMAIL)
mdph13.call_situation_dossier(1234, SECRET, DOB, email=EMAIL, ip=IP)
request = mock_http.last_request
headers = request.headers
url = request.url
@ -258,6 +260,7 @@ def test_call_situation_dossier_with_email(mdph13, mock_http):
assert headers['X-CD13-Secret'] == base64.b64encode(SECRET.encode('utf-8')).decode('ascii')
assert headers['X-CD13-DateNaissBenef'] == DOB_ISOFORMAT
assert headers['X-CD13-Email'] == EMAIL
assert headers['X-CD13-IP'] == IP
def test_check_status_no_link(mdph13):
@ -347,7 +350,7 @@ def test_link_ok(mdph13, mock_http):
assert not Link.objects.count()
response = mdph13.link(request=None, NameID=NAME_ID,
numero_dossier=FILE_NUMBER, secret=SECRET,
date_de_naissance=DOB_ISOFORMAT, email=EMAIL)
date_de_naissance=DOB_ISOFORMAT, email=EMAIL, ip=IP)
link = Link.objects.get()
assert response == {
'link_id': link.pk,
@ -423,7 +426,7 @@ def test_dossier_ok(mdph13, mock_http):
secret=SECRET,
dob=DOB)
mock_http.add_response(VALID_RESPONSE)
response = mdph13.dossiers(None, NAME_ID, EMAIL)
response = mdph13.dossiers(None, NAME_ID, EMAIL, ip=IP)
assert response['data']
assert response['data'][0]['id'] == str(link.pk)
assert response['data'][0]['numero_dossier'] == FILE_NUMBER
@ -446,7 +449,7 @@ def test_dossier_with_link_id_ok(mdph13, mock_http):
secret=SECRET,
dob=DOB)
mock_http.add_response(VALID_RESPONSE)
response = mdph13.dossiers(None, NAME_ID, EMAIL, link_id=str(link.pk))
response = mdph13.dossiers(None, NAME_ID, EMAIL, link_id=str(link.pk), ip=IP)
assert response['data']
assert response['data']['id'] == str(link.pk)
assert response['data']['numero_dossier'] == FILE_NUMBER
@ -486,7 +489,7 @@ def test_dossier_partial_failure(mdph13, mock_http):
assert link2.display_name
mock_http.add_response(VALID_RESPONSE)
mock_http.add_response({'status_code': 500, 'content': ''})
response = mdph13.dossiers(None, NAME_ID, EMAIL)
response = mdph13.dossiers(None, NAME_ID, EMAIL, ip=IP)
assert response['data']
assert response['data'][0]['id'] == str(link1.pk)
assert response['data'][0]['err'] == 0
@ -513,8 +516,8 @@ def test_dossier_bad_date(mdph13, mock_http):
def test_dossier_http_error(app, mdph13, mock_http, caplog):
url = '/mdph13/test1/link/?NameID=%s&numero_dossier=%s&date_de_naissance=%s&secret=%s&email=%s'
url = url % (NAME_ID, FILE_NUMBER, DOB, SECRET, EMAIL)
url = '/mdph13/test1/link/?NameID=%s&numero_dossier=%s&date_de_naissance=%s&secret=%s&email=%s&ip=%s'
url = url % (NAME_ID, FILE_NUMBER, DOB, SECRET, EMAIL, IP)
mock_http.add_response({'status_code': 401, 'content': 'wtf', 'reason': 'Authentication required'})
response = app.post(url, status=500)
assert response.json['err_class'] == 'requests.exceptions.HTTPError'