diff --git a/app/lib/api_entreprise/api.rb b/app/lib/api_entreprise/api.rb index 1b8790d2c..884cb1a3c 100644 --- a/app/lib/api_entreprise/api.rb +++ b/app/lib/api_entreprise/api.rb @@ -60,6 +60,7 @@ class ApiEntreprise::API private def self.call(resource_name, siret_or_siren, procedure_id, user_id = nil) + return if ApiEntrepriseToken.new(token_for_procedure(procedure_id)).expired? url = url(resource_name, siret_or_siren) params = params(siret_or_siren, procedure_id, user_id) diff --git a/app/models/api_entreprise_token.rb b/app/models/api_entreprise_token.rb new file mode 100644 index 000000000..4398c1d0b --- /dev/null +++ b/app/models/api_entreprise_token.rb @@ -0,0 +1,25 @@ +class ApiEntrepriseToken + attr_reader :token + + def initialize(token) + @token = token + end + + def roles + decoded_token["roles"] if token.present? + end + + def expired? + Time.zone.now.to_i >= decoded_token["exp"] if token.present? + end + + def role?(role) + roles.include?(role) + end + + private + + def decoded_token + JWT.decode(token, nil, false)[0] + end +end diff --git a/app/models/procedure.rb b/app/models/procedure.rb index f4a83c7d2..e42bb4954 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -552,18 +552,18 @@ class Procedure < ApplicationRecord "Procedure;#{id}" end - def api_entreprise_roles - JWT.decode(api_entreprise_token, nil, false)[0]["roles"] if api_entreprise_token.present? - end - def api_entreprise_role?(role) - api_entreprise_roles.include?(role) + ApiEntrepriseToken.new(api_entreprise_token).role?(role) end def api_entreprise_token self[:api_entreprise_token].presence || Rails.application.secrets.api_entreprise[:key] end + def api_entreprise_token_expired? + ApiEntrepriseToken.new(api_entreprise_token).expired? + end + private def move_type_de_champ_attributes(types_de_champ, type_de_champ, new_index) diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index 5de3592da..ad0bdae98 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -230,6 +230,8 @@ describe Users::DossiersController, type: :controller do let(:api_entreprise_bilans_bdf_status) { 200 } let(:api_entreprise_bilans_bdf_body) { File.read('spec/fixtures/files/api_entreprise/bilans_entreprise_bdf.json') } + let(:token_expired) { false } + def stub_api_entreprise_requests stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/) .to_return(status: api_etablissement_status, body: api_etablissement_body) @@ -258,8 +260,9 @@ describe Users::DossiersController, type: :controller do before do sign_in(user) stub_api_entreprise_requests - allow_any_instance_of(Procedure).to receive(:api_entreprise_roles) + allow_any_instance_of(ApiEntrepriseToken).to receive(:roles) .and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"]) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(token_expired) end before { Timecop.freeze(Time.zone.local(2020, 3, 14)) } after { Timecop.return } @@ -316,6 +319,14 @@ describe Users::DossiersController, type: :controller do it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_unknown') end + context 'when default token has expired' do + let(:api_etablissement_status) { 200 } + let(:api_body_status) { '' } + let(:token_expired) { true } + + it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_unknown') + end + context 'when the API returns no Entreprise' do let(:api_entreprise_status) { 404 } let(:api_entreprise_body) { '' } diff --git a/spec/features/users/dossier_creation_spec.rb b/spec/features/users/dossier_creation_spec.rb index 4c00469f0..6c3edc750 100644 --- a/spec/features/users/dossier_creation_spec.rb +++ b/spec/features/users/dossier_creation_spec.rb @@ -78,7 +78,8 @@ feature 'Creating a new dossier:' do .to_return(status: 404, body: '') stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/) .to_return(status: 404, body: '') - allow_any_instance_of(Procedure).to receive(:api_entreprise_roles).and_return([]) + allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return([]) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end before { Timecop.freeze(Time.zone.local(2020, 3, 14)) } after { Timecop.return } diff --git a/spec/lib/api_entreprise/api_spec.rb b/spec/lib/api_entreprise/api_spec.rb index 81e50b35c..3914fffbd 100644 --- a/spec/lib/api_entreprise/api_spec.rb +++ b/spec/lib/api_entreprise/api_spec.rb @@ -9,6 +9,7 @@ describe ApiEntreprise::API do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=#{token}/) .to_return(status: status, body: body) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context 'when the service is unavailable' do @@ -78,6 +79,7 @@ describe ApiEntreprise::API do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*non_diffusables=true&.*token=/) .to_return(status: status, body: body) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context 'when siret does not exist' do @@ -105,6 +107,7 @@ describe ApiEntreprise::API do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/.*token=/) .to_return(status: status, body: body) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context 'when siret does not exist' do @@ -136,6 +139,7 @@ describe ApiEntreprise::API do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/.*token=/) .to_return(status: status, body: body) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end subject { described_class.rna(siren, procedure_id) } @@ -166,7 +170,8 @@ describe ApiEntreprise::API do let(:body) { File.read('spec/fixtures/files/api_entreprise/attestation_sociale.json') } before do - allow_any_instance_of(Procedure).to receive(:api_entreprise_roles).and_return(roles) + allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(roles) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}?.*token=/) .to_return(body: body, status: status) end @@ -194,7 +199,8 @@ describe ApiEntreprise::API do let(:body) { File.read('spec/fixtures/files/api_entreprise/attestation_fiscale.json') } before do - allow_any_instance_of(Procedure).to receive(:api_entreprise_roles).and_return(roles) + allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(roles) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_fiscales_dgfip\/#{siren}?.*token=#{token}&user_id=#{user_id}/) .to_return(body: body, status: status) end @@ -221,7 +227,8 @@ describe ApiEntreprise::API do let(:body) { File.read('spec/fixtures/files/api_entreprise/bilans_entreprise_bdf.json') } before do - allow_any_instance_of(Procedure).to receive(:api_entreprise_roles).and_return(roles) + allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(roles) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}?.*token=#{token}/) .to_return(body: body, status: status) end @@ -240,4 +247,18 @@ describe ApiEntreprise::API do it { expect(subject).to eq(JSON.parse(body, symbolize_names: true)) } end end + + describe 'with expired token' do + let(:siren) { '111111111' } + subject { described_class.entreprise(siren, procedure_id) } + + before do + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(true) + end + + it 'makes no call to api-entreprise' do + subject + expect(WebMock).not_to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=#{token}/) + end + end end diff --git a/spec/lib/api_entreprise/attestation_fiscale_adapter_spec.rb b/spec/lib/api_entreprise/attestation_fiscale_adapter_spec.rb index 4a2de5a75..dfc19b6bb 100644 --- a/spec/lib/api_entreprise/attestation_fiscale_adapter_spec.rb +++ b/spec/lib/api_entreprise/attestation_fiscale_adapter_spec.rb @@ -8,7 +8,8 @@ describe ApiEntreprise::AttestationFiscaleAdapter do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_fiscales_dgfip\/#{siren}?.*token=/) .to_return(body: body, status: status) - allow_any_instance_of(Procedure).to receive(:api_entreprise_roles).and_return(["attestations_fiscales"]) + allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["attestations_fiscales"]) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context "when the SIREN is valid" do diff --git a/spec/lib/api_entreprise/attestation_sociale_adapter_spec.rb b/spec/lib/api_entreprise/attestation_sociale_adapter_spec.rb index 6f757e9bc..9c38eb95e 100644 --- a/spec/lib/api_entreprise/attestation_sociale_adapter_spec.rb +++ b/spec/lib/api_entreprise/attestation_sociale_adapter_spec.rb @@ -7,7 +7,8 @@ describe ApiEntreprise::AttestationSocialeAdapter do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}?.*token=/) .to_return(body: body, status: status) - allow_any_instance_of(Procedure).to receive(:api_entreprise_roles).and_return(["attestations_sociales"]) + allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["attestations_sociales"]) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context "when the SIREN is valid" do diff --git a/spec/lib/api_entreprise/bilans_bdf_adapter_spec.rb b/spec/lib/api_entreprise/bilans_bdf_adapter_spec.rb index 79029fa2a..572ea02ae 100644 --- a/spec/lib/api_entreprise/bilans_bdf_adapter_spec.rb +++ b/spec/lib/api_entreprise/bilans_bdf_adapter_spec.rb @@ -8,7 +8,8 @@ describe ApiEntreprise::BilansBdfAdapter do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}?.*token=/) .to_return(body: body, status: status) - allow_any_instance_of(Procedure).to receive(:api_entreprise_roles).and_return(["bilans_entreprise_bdf"]) + allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["bilans_entreprise_bdf"]) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context "when the SIREN is valid" do diff --git a/spec/lib/api_entreprise/effectifs_adapter_spec.rb b/spec/lib/api_entreprise/effectifs_adapter_spec.rb index 6f4aa59d1..a34a4740a 100644 --- a/spec/lib/api_entreprise/effectifs_adapter_spec.rb +++ b/spec/lib/api_entreprise/effectifs_adapter_spec.rb @@ -10,6 +10,7 @@ describe ApiEntreprise::EffectifsAdapter do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/#{annee}\/#{mois}\/entreprise\/#{siren}?.*token=/) .to_return(body: body, status: status) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context "when the SIREN is valid" do diff --git a/spec/lib/api_entreprise/effectifs_annuels_adapter_spec.rb b/spec/lib/api_entreprise/effectifs_annuels_adapter_spec.rb index 67cb701cf..0c33626c9 100644 --- a/spec/lib/api_entreprise/effectifs_annuels_adapter_spec.rb +++ b/spec/lib/api_entreprise/effectifs_annuels_adapter_spec.rb @@ -8,6 +8,7 @@ describe ApiEntreprise::EffectifsAnnuelsAdapter do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/) .to_return(body: body, status: status) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context "when the SIREN is valid" do diff --git a/spec/lib/api_entreprise/entreprise_adapter_spec.rb b/spec/lib/api_entreprise/entreprise_adapter_spec.rb index 16eb85294..83fe446dc 100644 --- a/spec/lib/api_entreprise/entreprise_adapter_spec.rb +++ b/spec/lib/api_entreprise/entreprise_adapter_spec.rb @@ -8,6 +8,7 @@ describe ApiEntreprise::EntrepriseAdapter do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=/) .to_return(body: body, status: status) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context "when the SIRET is valid" do diff --git a/spec/lib/api_entreprise/etablissement_adapter_spec.rb b/spec/lib/api_entreprise/etablissement_adapter_spec.rb index a772a4933..e70a74e3b 100644 --- a/spec/lib/api_entreprise/etablissement_adapter_spec.rb +++ b/spec/lib/api_entreprise/etablissement_adapter_spec.rb @@ -2,6 +2,10 @@ describe ApiEntreprise::EtablissementAdapter do let(:procedure) { create(:procedure) } let(:procedure_id) { procedure.id } + before do + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) + end + context 'SIRET valide avec infos diffusables' do let(:siret) { '41816609600051' } subject { described_class.new(siret, procedure_id).to_params } diff --git a/spec/lib/api_entreprise/exercices_adapter_spec.rb b/spec/lib/api_entreprise/exercices_adapter_spec.rb index 04764aeab..fe1c59d09 100644 --- a/spec/lib/api_entreprise/exercices_adapter_spec.rb +++ b/spec/lib/api_entreprise/exercices_adapter_spec.rb @@ -6,6 +6,7 @@ describe ApiEntreprise::ExercicesAdapter do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/.*token=/) .to_return(body: File.read('spec/fixtures/files/api_entreprise/exercices.json', status: 200)) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end it { is_expected.to be_an_instance_of(Hash) } diff --git a/spec/lib/api_entreprise/rna_adapter_spec.rb b/spec/lib/api_entreprise/rna_adapter_spec.rb index 2d5a3f1bb..44aadf035 100644 --- a/spec/lib/api_entreprise/rna_adapter_spec.rb +++ b/spec/lib/api_entreprise/rna_adapter_spec.rb @@ -11,6 +11,7 @@ describe ApiEntreprise::RNAAdapter do before do stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/.*token=/) .to_return(body: body, status: status) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context 'when siret is not valid' do diff --git a/spec/models/procedure_spec.rb b/spec/models/procedure_spec.rb index 7010b4a92..415293c30 100644 --- a/spec/models/procedure_spec.rb +++ b/spec/models/procedure_spec.rb @@ -334,6 +334,31 @@ describe Procedure do end end + describe 'api_entreprise_token_expired?' do + let(:token) { "mon-token" } + let(:procedure) { create(:procedure, api_entreprise_token: token) } + let(:payload) { + [ + { "exp" => expiration_time } + ] + } + let(:subject) { procedure.api_entreprise_token_expired? } + + before do + allow(JWT).to receive(:decode).with(token, nil, false).and_return(payload) + end + + context "with token expired" do + let(:expiration_time) { (Time.zone.now - 1.day).to_i } + it { is_expected.to be_truthy } + end + + context "with token not expired" do + let(:expiration_time) { (Time.zone.now + 1.day).to_i } + it { is_expected.to be_falsey } + end + end + describe 'clone' do let!(:service) { create(:service) } let(:procedure) { create(:procedure, received_mail: received_mail, service: service) } diff --git a/spec/services/api_entreprise_service_spec.rb b/spec/services/api_entreprise_service_spec.rb index 2c0a5f11c..7b2e33cb7 100644 --- a/spec/services/api_entreprise_service_spec.rb +++ b/spec/services/api_entreprise_service_spec.rb @@ -68,8 +68,9 @@ describe ApiEntrepriseService do let(:result) { ApiEntrepriseService.get_etablissement_params_for_siret(siret, procedure.id) } before do - allow_any_instance_of(Procedure).to receive(:api_entreprise_roles) + allow_any_instance_of(ApiEntrepriseToken).to receive(:roles) .and_return(["attestations_sociales", "attestations_fiscales", "bilans_entreprise_bdf"]) + allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false) end context 'when service is up' do