From bc0f77978ff6dbf3e4f1918d29be9e92d7ba8efb Mon Sep 17 00:00:00 2001 From: kara Diaby Date: Mon, 19 Oct 2020 11:33:36 +0200 Subject: [PATCH] add an api token verification for api entreprise --- .../procedures_controller.rb | 16 ++++++-- app/lib/api_entreprise/api.rb | 37 ++++++++++++++----- app/lib/api_entreprise/privileges_adapter.rb | 20 ++++++++++ .../procedures_controller_spec.rb | 35 ++++++++++++++++-- 4 files changed, 90 insertions(+), 18 deletions(-) create mode 100644 app/lib/api_entreprise/privileges_adapter.rb diff --git a/app/controllers/new_administrateur/procedures_controller.rb b/app/controllers/new_administrateur/procedures_controller.rb index 11116b8db..29cf33abc 100644 --- a/app/controllers/new_administrateur/procedures_controller.rb +++ b/app/controllers/new_administrateur/procedures_controller.rb @@ -125,12 +125,20 @@ module NewAdministrateur end def update_jeton - if !@procedure.update(procedure_params) - flash.now.alert = @procedure.errors.full_messages + token = params[:procedure][:api_entreprise_token] + @procedure.api_entreprise_token = token + + if @procedure.valid? && + ApiEntreprise::PrivilegesAdapter.new(token).valid? && + @procedure.save + + redirect_to jeton_admin_procedure_path(procedure_id: params[:procedure_id]), + notice: 'Le jeton a bien été mis à jour' else - flash.notice = 'Le jeton a bien été mis à jour' + + flash.now.alert = "Mise à jour impossible : le jeton n'est pas valide" + render 'jeton' end - render 'jeton' end def publication diff --git a/app/lib/api_entreprise/api.rb b/app/lib/api_entreprise/api.rb index 716c28f30..62699fa63 100644 --- a/app/lib/api_entreprise/api.rb +++ b/app/lib/api_entreprise/api.rb @@ -8,6 +8,7 @@ class ApiEntreprise::API ATTESTATION_SOCIALE_RESOURCE_NAME = "attestations_sociales_acoss" ATTESTATION_FISCALE_RESOURCE_NAME = "attestations_fiscales_dgfip" BILANS_BDF_RESOURCE_NAME = "bilans_entreprises_bdf" + PRIVILEGES_RESOURCE_NAME = "privileges" TIMEOUT = 15 @@ -24,48 +25,64 @@ class ApiEntreprise::API end def self.entreprise(siren, procedure_id) - call(ENTREPRISE_RESOURCE_NAME, siren, procedure_id) + call_with_siret(ENTREPRISE_RESOURCE_NAME, siren, procedure_id) end def self.etablissement(siret, procedure_id) - call(ETABLISSEMENT_RESOURCE_NAME, siret, procedure_id) + call_with_siret(ETABLISSEMENT_RESOURCE_NAME, siret, procedure_id) end def self.exercices(siret, procedure_id) - call(EXERCICES_RESOURCE_NAME, siret, procedure_id) + call_with_siret(EXERCICES_RESOURCE_NAME, siret, procedure_id) end def self.rna(siret, procedure_id) - call(RNA_RESOURCE_NAME, siret, procedure_id) + call_with_siret(RNA_RESOURCE_NAME, siret, procedure_id) end def self.effectifs(siren, procedure_id, annee, mois) endpoint = [EFFECTIFS_RESOURCE_NAME, annee, mois, "entreprise"].join('/') - call(endpoint, siren, procedure_id) + call_with_siret(endpoint, siren, procedure_id) end def self.effectifs_annuels(siren, procedure_id) - call(EFFECTIFS_ANNUELS_RESOURCE_NAME, siren, procedure_id) + call_with_siret(EFFECTIFS_ANNUELS_RESOURCE_NAME, siren, procedure_id) end def self.attestation_sociale(siren, procedure_id) procedure = Procedure.find(procedure_id) - call(ATTESTATION_SOCIALE_RESOURCE_NAME, siren, procedure_id) if procedure.api_entreprise_role?("attestations_sociales") + call_with_siret(ATTESTATION_SOCIALE_RESOURCE_NAME, siren, procedure_id) if procedure.api_entreprise_role?("attestations_sociales") end def self.attestation_fiscale(siren, procedure_id, user_id) procedure = Procedure.find(procedure_id) - call(ATTESTATION_FISCALE_RESOURCE_NAME, siren, procedure_id, user_id) if procedure.api_entreprise_role?("attestations_fiscales") + call_with_siret(ATTESTATION_FISCALE_RESOURCE_NAME, siren, procedure_id, user_id) if procedure.api_entreprise_role?("attestations_fiscales") end def self.bilans_bdf(siren, procedure_id) procedure = Procedure.find(procedure_id) - call(BILANS_BDF_RESOURCE_NAME, siren, procedure_id) if procedure.api_entreprise_role?("bilans_entreprise_bdf") + call_with_siret(BILANS_BDF_RESOURCE_NAME, siren, procedure_id) if procedure.api_entreprise_role?("bilans_entreprise_bdf") + end + + def self.privileges(token) + call_with_token(PRIVILEGES_RESOURCE_NAME, token) end private - def self.call(resource_name, siret_or_siren, procedure_id, user_id = nil) + def self.call_with_token(resource_name, token) + url = "#{API_ENTREPRISE_URL}/privileges?token=#{token}" + response = Typhoeus.get(url, + timeout: TIMEOUT) + + if response.success? + JSON.parse(response.body, symbolize_names: true) + else + raise RequestFailed, "HTTP Error Code: #{response.code} for #{url}\nheaders: #{response.headers}\nbody: #{response.body}" + end + end + + def self.call_with_siret(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/lib/api_entreprise/privileges_adapter.rb b/app/lib/api_entreprise/privileges_adapter.rb new file mode 100644 index 000000000..8064d5962 --- /dev/null +++ b/app/lib/api_entreprise/privileges_adapter.rb @@ -0,0 +1,20 @@ +class ApiEntreprise::PrivilegesAdapter < ApiEntreprise::Adapter + def initialize(token) + @token = token + end + + def valid? + begin + get_resource + true + rescue + false + end + end + + private + + def get_resource + ApiEntreprise::API.privileges(@token) + end +end diff --git a/spec/controllers/new_administrateur/procedures_controller_spec.rb b/spec/controllers/new_administrateur/procedures_controller_spec.rb index ecc2c4095..de1efc074 100644 --- a/spec/controllers/new_administrateur/procedures_controller_spec.rb +++ b/spec/controllers/new_administrateur/procedures_controller_spec.rb @@ -333,11 +333,38 @@ describe NewAdministrateur::ProceduresController, type: :controller do describe 'PATCH #jeton' do let(:procedure) { create(:procedure, administrateur: admin) } - let(:valid_token) { "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" } + let(:token) { "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" } - it "update api_entreprise_token" do - patch :update_jeton, params: { id: procedure.id, procedure: { api_entreprise_token: valid_token } } - expect(procedure.reload.api_entreprise_token).to eq(valid_token) + subject { patch :update_jeton, params: { id: procedure.id, procedure: { api_entreprise_token: token } } } + + before do + allow_any_instance_of(ApiEntreprise::PrivilegesAdapter).to receive(:valid?).and_return(token_is_valid) + subject + end + + context 'when jeton is valid' do + let(:token_is_valid) { true } + + it { expect(flash.alert).to be_nil } + it { expect(flash.notice).to eq('Le jeton a bien été mis à jour') } + it { expect(procedure.reload.api_entreprise_token).to eq(token) } + end + + context 'when jeton is invalid' do + let(:token_is_valid) { false } + + it { expect(flash.alert).to eq("Mise à jour impossible : le jeton n'est pas valide") } + it { expect(flash.notice).to be_nil } + it { expect(procedure.reload.api_entreprise_token).not_to eq(token) } + end + + context 'when jeton is not a jwt' do + let(:token) { "invalid" } + let(:token_is_valid) { true } # just to check jwt format by procedure model + + it { expect(flash.alert).to eq("Mise à jour impossible : le jeton n'est pas valide") } + it { expect(flash.notice).to be_nil } + it { expect(procedure.reload.api_entreprise_token).not_to eq(token) } end end