Merge pull request #5115 from betagouv/5111-jeton-apient-ajour

N'appelle pas api-entreprise si jeton expiré
This commit is contained in:
krichtof 2020-05-06 11:06:13 +02:00 committed by GitHub
commit d3ea20968e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 111 additions and 14 deletions

View file

@ -60,6 +60,7 @@ class ApiEntreprise::API
private private
def self.call(resource_name, siret_or_siren, procedure_id, user_id = nil) 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) url = url(resource_name, siret_or_siren)
params = params(siret_or_siren, procedure_id, user_id) params = params(siret_or_siren, procedure_id, user_id)

View file

@ -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

View file

@ -552,18 +552,18 @@ class Procedure < ApplicationRecord
"Procedure;#{id}" "Procedure;#{id}"
end 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) def api_entreprise_role?(role)
api_entreprise_roles.include?(role) ApiEntrepriseToken.new(api_entreprise_token).role?(role)
end end
def api_entreprise_token def api_entreprise_token
self[:api_entreprise_token].presence || Rails.application.secrets.api_entreprise[:key] self[:api_entreprise_token].presence || Rails.application.secrets.api_entreprise[:key]
end end
def api_entreprise_token_expired?
ApiEntrepriseToken.new(api_entreprise_token).expired?
end
private private
def move_type_de_champ_attributes(types_de_champ, type_de_champ, new_index) def move_type_de_champ_attributes(types_de_champ, type_de_champ, new_index)

View file

@ -230,6 +230,8 @@ describe Users::DossiersController, type: :controller do
let(:api_entreprise_bilans_bdf_status) { 200 } 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(: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 def stub_api_entreprise_requests
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/)
.to_return(status: api_etablissement_status, body: api_etablissement_body) .to_return(status: api_etablissement_status, body: api_etablissement_body)
@ -258,8 +260,9 @@ describe Users::DossiersController, type: :controller do
before do before do
sign_in(user) sign_in(user)
stub_api_entreprise_requests 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"]) .and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"])
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(token_expired)
end end
before { Timecop.freeze(Time.zone.local(2020, 3, 14)) } before { Timecop.freeze(Time.zone.local(2020, 3, 14)) }
after { Timecop.return } 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') it_behaves_like 'the request fails with an error', I18n.t('errors.messages.siret_unknown')
end 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 context 'when the API returns no Entreprise' do
let(:api_entreprise_status) { 404 } let(:api_entreprise_status) { 404 }
let(:api_entreprise_body) { '' } let(:api_entreprise_body) { '' }

View file

@ -78,7 +78,8 @@ feature 'Creating a new dossier:' do
.to_return(status: 404, body: '') .to_return(status: 404, body: '')
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/)
.to_return(status: 404, body: '') .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 end
before { Timecop.freeze(Time.zone.local(2020, 3, 14)) } before { Timecop.freeze(Time.zone.local(2020, 3, 14)) }
after { Timecop.return } after { Timecop.return }

View file

@ -9,6 +9,7 @@ describe ApiEntreprise::API do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=#{token}/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=#{token}/)
.to_return(status: status, body: body) .to_return(status: status, body: body)
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
end end
context 'when the service is unavailable' do context 'when the service is unavailable' do
@ -78,6 +79,7 @@ describe ApiEntreprise::API do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*non_diffusables=true&.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*non_diffusables=true&.*token=/)
.to_return(status: status, body: body) .to_return(status: status, body: body)
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
end end
context 'when siret does not exist' do context 'when siret does not exist' do
@ -105,6 +107,7 @@ describe ApiEntreprise::API do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/.*token=/)
.to_return(status: status, body: body) .to_return(status: status, body: body)
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
end end
context 'when siret does not exist' do context 'when siret does not exist' do
@ -136,6 +139,7 @@ describe ApiEntreprise::API do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/.*token=/)
.to_return(status: status, body: body) .to_return(status: status, body: body)
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
end end
subject { described_class.rna(siren, procedure_id) } 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') } let(:body) { File.read('spec/fixtures/files/api_entreprise/attestation_sociale.json') }
before do 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=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}?.*token=/)
.to_return(body: body, status: status) .to_return(body: body, status: status)
end end
@ -194,7 +199,8 @@ describe ApiEntreprise::API do
let(:body) { File.read('spec/fixtures/files/api_entreprise/attestation_fiscale.json') } let(:body) { File.read('spec/fixtures/files/api_entreprise/attestation_fiscale.json') }
before do 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}/) 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) .to_return(body: body, status: status)
end end
@ -221,7 +227,8 @@ describe ApiEntreprise::API do
let(:body) { File.read('spec/fixtures/files/api_entreprise/bilans_entreprise_bdf.json') } let(:body) { File.read('spec/fixtures/files/api_entreprise/bilans_entreprise_bdf.json') }
before do 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}/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}?.*token=#{token}/)
.to_return(body: body, status: status) .to_return(body: body, status: status)
end end
@ -240,4 +247,18 @@ describe ApiEntreprise::API do
it { expect(subject).to eq(JSON.parse(body, symbolize_names: true)) } it { expect(subject).to eq(JSON.parse(body, symbolize_names: true)) }
end end
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 end

View file

@ -8,7 +8,8 @@ describe ApiEntreprise::AttestationFiscaleAdapter do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_fiscales_dgfip\/#{siren}?.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_fiscales_dgfip\/#{siren}?.*token=/)
.to_return(body: body, status: status) .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 end
context "when the SIREN is valid" do context "when the SIREN is valid" do

View file

@ -7,7 +7,8 @@ describe ApiEntreprise::AttestationSocialeAdapter do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}?.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}?.*token=/)
.to_return(body: body, status: status) .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 end
context "when the SIREN is valid" do context "when the SIREN is valid" do

View file

@ -8,7 +8,8 @@ describe ApiEntreprise::BilansBdfAdapter do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}?.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}?.*token=/)
.to_return(body: body, status: status) .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 end
context "when the SIREN is valid" do context "when the SIREN is valid" do

View file

@ -10,6 +10,7 @@ describe ApiEntreprise::EffectifsAdapter do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/#{annee}\/#{mois}\/entreprise\/#{siren}?.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/#{annee}\/#{mois}\/entreprise\/#{siren}?.*token=/)
.to_return(body: body, status: status) .to_return(body: body, status: status)
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
end end
context "when the SIREN is valid" do context "when the SIREN is valid" do

View file

@ -8,6 +8,7 @@ describe ApiEntreprise::EffectifsAnnuelsAdapter do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/)
.to_return(body: body, status: status) .to_return(body: body, status: status)
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
end end
context "when the SIREN is valid" do context "when the SIREN is valid" do

View file

@ -8,6 +8,7 @@ describe ApiEntreprise::EntrepriseAdapter do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=/)
.to_return(body: body, status: status) .to_return(body: body, status: status)
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
end end
context "when the SIRET is valid" do context "when the SIRET is valid" do

View file

@ -2,6 +2,10 @@ describe ApiEntreprise::EtablissementAdapter do
let(:procedure) { create(:procedure) } let(:procedure) { create(:procedure) }
let(:procedure_id) { procedure.id } 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 context 'SIRET valide avec infos diffusables' do
let(:siret) { '41816609600051' } let(:siret) { '41816609600051' }
subject { described_class.new(siret, procedure_id).to_params } subject { described_class.new(siret, procedure_id).to_params }

View file

@ -6,6 +6,7 @@ describe ApiEntreprise::ExercicesAdapter do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/.*token=/) 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)) .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 end
it { is_expected.to be_an_instance_of(Hash) } it { is_expected.to be_an_instance_of(Hash) }

View file

@ -11,6 +11,7 @@ describe ApiEntreprise::RNAAdapter do
before do before do
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/.*token=/) stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/.*token=/)
.to_return(body: body, status: status) .to_return(body: body, status: status)
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
end end
context 'when siret is not valid' do context 'when siret is not valid' do

View file

@ -334,6 +334,31 @@ describe Procedure do
end end
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 describe 'clone' do
let!(:service) { create(:service) } let!(:service) { create(:service) }
let(:procedure) { create(:procedure, received_mail: received_mail, service: service) } let(:procedure) { create(:procedure, received_mail: received_mail, service: service) }

View file

@ -68,8 +68,9 @@ describe ApiEntrepriseService do
let(:result) { ApiEntrepriseService.get_etablissement_params_for_siret(siret, procedure.id) } let(:result) { ApiEntrepriseService.get_etablissement_params_for_siret(siret, procedure.id) }
before do 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"]) .and_return(["attestations_sociales", "attestations_fiscales", "bilans_entreprise_bdf"])
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
end end
context 'when service is up' do context 'when service is up' do