-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
API Particulier x DataPass : handle Formulaire QF modality #1579
base: develop
Are you sure you want to change the base?
Changes from 15 commits
58b8e7b
4a12489
a52a934
56248bb
deb8673
9252ef3
31df189
03b42ac
cf6e233
4238962
d2f3d7e
3191e73
ec85fd5
a081984
4f1339e
62e40b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
require 'faraday' | ||
|
||
class AbstractHubEEAPIClient | ||
protected | ||
|
||
def http_connection(&block) | ||
Faraday.new do |conn| | ||
conn.request :retry, max: 5 | ||
conn.response :raise_error | ||
conn.response :json | ||
conn.options.timeout = 2 | ||
yield(conn) if block | ||
end | ||
end | ||
|
||
def consumer_key | ||
Rails.application.credentials.hubee_consumer_key | ||
end | ||
|
||
def consumer_secret | ||
Rails.application.credentials.hubee_consumer_secret | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
require 'faraday' | ||
|
||
class AbstractINSEEAPIClient | ||
protected | ||
|
||
def http_connection(&block) | ||
@http_connection ||= Faraday.new do |conn| | ||
conn.request :retry, max: 5 | ||
conn.response :raise_error | ||
conn.response :json | ||
conn.options.timeout = 2 | ||
yield(conn) if block | ||
end | ||
end | ||
|
||
def consumer_key | ||
Rails.application.credentials.insee_consumer_key | ||
end | ||
|
||
def consumer_secret | ||
Rails.application.credentials.insee_consumer_secret | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
class FormulaireQFAPIClient | ||
def create_collectivity(authorization_request) | ||
organization = authorization_request.organization | ||
editor_name = authorization_request.extra_infos.dig('service_provider', 'id') | ||
|
||
params = { | ||
siret: organization.siret, | ||
code_cog: organization.code_commune_etablissement, | ||
departement: organization.code_postal_etablissement[0..1], | ||
name: organization.denomination, | ||
status: 'active', | ||
editor: editor_name | ||
} | ||
|
||
http_connection.post("#{host}/api/collectivites", params.to_json) | ||
end | ||
|
||
private | ||
|
||
def host | ||
Rails.application.credentials.formulaire_qf.host | ||
end | ||
|
||
def http_connection(&block) | ||
Faraday.new do |conn| | ||
conn.headers['Content-Type'] = 'application/json' | ||
conn.request :authorization, 'Bearer', -> { secret } | ||
yield(conn) if block | ||
end | ||
end | ||
|
||
def secret | ||
Rails.application.credentials.formulaire_qf.secret | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
class HubEEAPIAuthentication < AbstractHubEEAPIClient | ||
def access_token | ||
http_connection.post( | ||
auth_url, | ||
'grant_type=client_credentials&scope=ADMIN', | ||
{ | ||
'Authorization' => "Basic #{encoded_client_id_and_secret}" | ||
} | ||
).body['access_token'] | ||
skelz0r marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
|
||
private | ||
|
||
def auth_url | ||
Rails.application.credentials.hubee_auth_url | ||
end | ||
|
||
def encoded_client_id_and_secret | ||
Base64.strict_encode64("#{consumer_key}:#{consumer_secret}") | ||
end | ||
|
||
def http_connection(&block) | ||
@http_connection ||= super do |conn| | ||
conn.response :json | ||
yield(conn) if block | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
class HubEEAPIClient < AbstractHubEEAPIClient | ||
class NotFound < StandardError; end | ||
class AlreadyExists < StandardError; end | ||
|
||
def find_organization(organization) | ||
http_connection.get("#{host}/referential/v1/organizations/SI-#{organization.siret}-#{organization.code_commune_etablissement}").body | ||
rescue Faraday::ResourceNotFound | ||
raise NotFound | ||
end | ||
|
||
def create_organization(organization, email) | ||
http_connection.post( | ||
"#{host}/referential/v1/organizations", | ||
{ | ||
type: 'SI', | ||
companyRegister: organization.siret, | ||
branchCode: organization.code_commune_etablissement, | ||
email:, | ||
name: organization.denomination, | ||
country: 'France', | ||
postalCode: organization.code_postal_etablissement, | ||
territory: organization.code_commune_etablissement, | ||
status: 'Actif' | ||
}.to_json, | ||
'Content-Type' => 'application/json' | ||
) | ||
rescue Faraday::BadRequestError => e | ||
raise AlreadyExists if already_exists_error?(e) | ||
|
||
raise | ||
end | ||
|
||
def create_subscription(authorization_request, organization_payload, process_code) | ||
http_connection.post( | ||
"#{host}/referential/v1/subscriptions", | ||
{ | ||
datapassId: authorization_request.external_id.to_i, | ||
notificationFrequency: 'Aucune', | ||
processCode: process_code, | ||
subscriber: { | ||
type: 'SI', | ||
companyRegister: organization_payload['companyRegister'], | ||
branchCode: organization_payload['branchCode'] | ||
}, | ||
email: authorization_request.demandeur.email, | ||
status: 'Inactif', | ||
localAdministrator: { | ||
email: authorization_request.demandeur.email | ||
}, | ||
validateDateTime: DateTime.now.iso8601, | ||
updateDateTime: DateTime.now.iso8601 | ||
}.to_json, | ||
'Content-Type' => 'application/json' | ||
) | ||
rescue Faraday::BadRequestError => e | ||
raise AlreadyExists if already_exists_error?(e) | ||
|
||
raise | ||
end | ||
|
||
def find_subscription(_authorization_request, organization_payload, process_code) | ||
request = http_connection { |conn| conn.request :gzip }.get( | ||
"#{host}/referential/v1/subscriptions", | ||
companyRegister: organization_payload['companyRegister'], | ||
processCode: process_code | ||
) | ||
request.body.first | ||
end | ||
|
||
def update_subscription(authorization_request, subscription_payload, editor_payload = {}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Je renommerai cette méthode en Pourquoi tout faire ici ? Parce que c'est de la tambouille interne de l'API qui ne fonctionne pas comme il faudrait, et fondamentalement dans le séquençage on ne devrait que faire un Bonus points:
|
||
subscription_id = authorization_request.extra_infos['hubee_subscription_id'] | ||
return if subscription_id.blank? | ||
|
||
payload = subscription_payload.with_indifferent_access.merge({ | ||
status: 'Actif', | ||
activateDateTime: DateTime.now.iso8601, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @skelz0r tu parlais d'une date d'activation dans le passé, y'avait une raison particulière ? ça semble fonctionner comme ça There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. où ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ça me dit quelque chose, mais de toute manière ta ligne est une date dans le passé quasiment instantanément. |
||
accessMode: 'API', | ||
notificationFrequency: 'Aucune' | ||
}.with_indifferent_access) | ||
|
||
payload.delete('id') | ||
payload.delete('creationDateTime') | ||
payload.merge!(editor_payload.with_indifferent_access) if editor_payload.present? | ||
|
||
http_connection.put( | ||
"#{host}/referential/v1/subscriptions/#{subscription_id}", | ||
payload.to_json, | ||
'Content-Type' => 'application/json' | ||
) | ||
end | ||
|
||
protected | ||
|
||
def host | ||
Rails.application.credentials.hubee_api_url | ||
end | ||
|
||
def already_exists_error?(faraday_error) | ||
faraday_error.response[:body]['errors'].any? do |error| | ||
error['message'].include?('already exists') | ||
end | ||
end | ||
|
||
def http_connection(&block) | ||
super do |conn| | ||
conn.request :authorization, 'Bearer', -> { HubEEAPIAuthentication.new.access_token } | ||
yield(conn) if block | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# frozen_string_literal: true | ||
|
||
class INSEEAPIAuthentication < AbstractINSEEAPIClient | ||
def access_token | ||
http_connection.post( | ||
'https://api.insee.fr/token', | ||
'grant_type=client_credentials', | ||
{ | ||
'Authorization' => "Basic #{encoded_client_id_and_secret}" | ||
} | ||
).body['access_token'] | ||
end | ||
|
||
private | ||
|
||
def encoded_client_id_and_secret | ||
Base64.strict_encode64("#{consumer_key}:#{consumer_secret}") | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
class INSEESireneAPIClient < AbstractINSEEAPIClient | ||
def etablissement(siret:) | ||
http_connection.get( | ||
"https://api.insee.fr/entreprises/sirene/V3.11/siret/#{siret}" | ||
).body | ||
end | ||
|
||
protected | ||
|
||
def http_connection | ||
super do |conn| | ||
conn.request :authorization, 'Bearer', -> { INSEEAPIAuthentication.new.access_token } | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,10 +72,17 @@ def authorization_request_attributes | |
).merge(authorization_request_attributes_for_current_event).merge( | ||
'last_update' => fired_at_as_datetime, | ||
'previous_external_id' => context.data['pass']['copied_from_enrollment_id'], | ||
'api' => context.api | ||
'api' => context.api, | ||
'extra_infos' => extra_infos_with_service_provider | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dans 100% des cas il s'agit d'un éditeur, autant mettre |
||
) | ||
end | ||
|
||
def extra_infos_with_service_provider | ||
context.authorization_request.extra_infos.merge({ | ||
'service_provider' => Hash(context.data.dig('pass', 'service_provider')) | ||
}) | ||
end | ||
|
||
def authorization_request_attributes_for_current_event | ||
authorization_request_attributes_for_current_event = {} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
class DatapassWebhook::ScheduleCreateFormulaireQFHubEESubscriptionJob < ApplicationInteractor | ||
def call | ||
return unless context.event == 'approve' | ||
return unless context.modalities.include?('formulaire_qf') | ||
|
||
CreateFormulaireQFHubEESubscriptionJob.perform_later(context.authorization_request.id) | ||
CreateFormulaireQFCollectivityJob.perform_later(context.authorization_request.id) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JeSuisUnCaillou on active directement ? comment on pourrait détecter si ça n'a pas fonctionné correctement côté HubEE ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Je ne comprends pas ta remarque dans le cadre du client qui est complétement décorellé de HubEE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Je ne comprends pas ta remarque dans le cadre du client qui est complétement décorellé de HubEE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Si tu parles du séquençage de l'organizer, c'est la responsabilité de l'organizer d'arrêter la séquence si il y a un souci.