# Passerelle - uniform access to data and services # Copyright (C) 2021 Entr'ouvert # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; exclude even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a.deepcopy of the GNU Affero General Public License # along with this program. If not, see . import json from urllib.parse import parse_qs, urlparse, urlunparse import pytest from django.utils.timezone import now import tests.utils from passerelle.apps.franceconnect_data.models import Resource from tests.test_rsa13 import mock_response CURRENT_YEAR = now().year USER_INFO_MOCKED_RESPONSES = [ ['/api/v1/token', {'access_token': 'at-1234', 'id_token': '.e30=.'}], [ '/api/v1/userinfo', { 'sub': 'sub-1234', 'given_name': 'John', 'family_name': 'Doe', 'birthdate': '2001-04-28', 'birthplace': '13055', 'birthcountry': '99100', 'gender': 'male', }, ], ] DGFIP_MOCKED_RESPONSES = USER_INFO_MOCKED_RESPONSES + [ [ '/token', { 'access_token': 'eyJ4NXQiOi', 'expires_in': 3600, 'scope': 'RessourceIRDerniere2', 'token_type': 'Bearer', }, ] ] DGFIP_MOCKED_RESPONSES += [ [ '/impotparticulier/1.0/situations/ir/assiettes/annrev/%s' % year, {'rfr': 0, 'revenuBrutGlobal': 0}, ] for year in range(CURRENT_YEAR - 3, CURRENT_YEAR) ] @pytest.fixture def fc(db): return tests.utils.make_resource( Resource, slug='test', fc_platform_slug='prod', fc_client_id='1234', fc_client_secret='abcd', fc_scopes='identite_pivot', ) def test_init_request(app, fc): resp = app.get('/franceconnect-data/test/init_request?origin=http://testserver') parsed_location = urlparse(resp.location) qs = parse_qs(parsed_location.query) assert ( urlunparse(parsed_location._replace(query='')) == 'https://app.franceconnect.gouv.fr/api/v1/authorize' ) assert dict(qs, nonce=None, state=None) == { 'acr_values': ['eidas1'], 'client_id': ['1234'], 'nonce': None, 'redirect_uri': ['http://testserver/franceconnect-data/test/callback?origin=http%3A%2F%2Ftestserver'], 'response_type': ['code'], 'scope': ['openid identite_pivot'], 'state': None, } @mock_response(*USER_INFO_MOCKED_RESPONSES) def test_callback(app, fc): resp = app.get( 'http://testserver/franceconnect-data/test/callback?origin=http%3A%2F%2Ftestserver&code=5678&raise=1' ) data = json.loads(resp.pyquery('#data').text()) assert data assert 'id' in data assert data['text'] == 'John Doe né le April 28, 2001' resp = app.get('/franceconnect-data/test/data_source?id=' + data['id']) assert resp.json['err'] == 0 assert dict(resp.json['data'][0], id=None) == { 'franceconnect': { 'birthdate': '2001-04-28', 'family_name': 'Doe', 'gender': 'male', 'birthplace': '13055', 'birthcountry': '99100', 'given_name': 'John', 'sub': 'sub-1234', 'hash': '50a8c11bcafc175d2571029b29ace5f3bcb3e06643ff4ac8b291772f788e4153', }, 'id': None, 'text': 'John Doe né le April 28, 2001', } @mock_response( ['/api/v1/token', ''], [ '/api/v1/userinfo', { 'sub': 'sub-1234', 'given_name': 'John', 'family_name': 'Doe', 'birthplace': '13055', 'birthcountry': '99100', 'birthdate': '2001-04-28', 'gender': 'male', }, ], ) def test_callback_error(app, fc): resp = app.get( 'http://testserver/franceconnect-data/test/callback?origin=http%3A%2F%2Ftestserver&code=5678&raise=1' ) assert not resp.pyquery('#data').text() error = json.loads(resp.pyquery('#error').text()) assert error assert 'Error in token endpoint response' in resp @mock_response(*DGFIP_MOCKED_RESPONSES) def test_dgfip_mode(app, fc): resp = app.get( 'http://testserver/franceconnect-data/test/callback?origin=http%3A%2F%2Ftestserver&code=5678&raise=1&mode=dgfip' ) data = json.loads(resp.pyquery('#data').text()) assert data assert 'id' in data assert data['text'] == 'John Doe né le April 28, 2001' resp = app.get('/franceconnect-data/test/data_source?mode=dgfip&id=' + data['id']) data = resp.json['data'][0] assert data['dgfip_ir'] for year in range(CURRENT_YEAR - 3, CURRENT_YEAR): assert data['dgfip_ir'][str(year)]