Skip to content
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

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from

Conversation

skelz0r
Copy link
Member

@skelz0r skelz0r commented Jun 21, 2024

  • Stocker l'id d'HubEE
  • Finaliser le client HubEE
  • Interactor pour scheduler le job si modality include fqf
  • Mettre le bon code pour le FQF
  • Vérifier avec des communes existantes pour adapter les payloads
  • Mettre une activationDate dans le passé
  • Préciser le accessMode en mode API
  • NOT SURE, est-ce que ça a réellement un intérêt ? | Tester le client HubEE
  • NOT SURE, autant lever une erreur et on verra plus tard ? | Gérer le cas déjà abonné
  • Review

@skelz0r skelz0r self-assigned this Jun 21, 2024
@skelz0r skelz0r force-pushed the features/api-particulier-fqf-modality branch 3 times, most recently from 96a999d to 78e5316 Compare June 25, 2024 05:50
@skelz0r skelz0r marked this pull request as ready for review June 25, 2024 05:55
@skelz0r skelz0r requested review from Un3x and Samuelfaure June 25, 2024 05:55
@skelz0r
Copy link
Member Author

skelz0r commented Jun 25, 2024

Ça se lit commit par commit.

Il manque le processCode pour le formulaire QF, à récupérer auprès d'HubEE.

Pour un peu de contexte: j'ai jugé qu'il était plus logique de s'occuper de la création/gestion des accès à la suite de la validation d'une demande côté APIM (ici donc) plutôt que côté DataPass.

Pourquoi ? Parce que ce n'est pas le job de DataPass. DataPass s'occupe juste de notifier des divers évenements qui surviennent sur les habilitations. En pratique ici on crée déjà chez nous l'accès via un jeton, c'est donc naturel, qu'en fonction des modalités, que l'on crée l'accès sur HubEE de notre côté.
Typiquement si on veut activer de manière rétroactive sur des habilitations existantes on doit le faire de notre côté, pas sur DataPass. En d'autres termes: les habilitations et les accès sont décorelés.

Copy link
Contributor

@Samuelfaure Samuelfaure left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'est ptêtre juste une impression mais j'ai le feeling que tu en as eu un peu marre à la fin x) le code perd un peu en clarté au fur et à mesure

Sinon quelques remarques mais rien de critique.

Comment on lines +44 to +55
context 'when modalities does no include params' do
before do
datapass_webhook_params['data']['data']['modalities'] = ['formulaire_qf']
end

it 'does not create a token' do
expect {
subject
}.not_to change(Token, :count)
end
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

J'ai pas la tête dans datapass ni le formulaire QF donc je vois pas du tout ce que ça implique que modalities inclue params ou pas

Un describe supplémentaire pour documenter peut-être serait pas de trop

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je pense que ce qui me confuse c'est le fait que :

  • sur un modalities = 'formulaire qf' on skip
  • sur un modalities = 'params' on avance

Et le titre c'est "no params modalities". Ca fait beaucoup de params.

Je changerai bien le return if context.modalities.exclude?('params') en return if !from_datapass

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Niveau modalité sur API Particulier il y a:

  1. params, qui correspond en fait à "faire des appels à l'API avec des paramètres d'entrée"
  2. formulaire qf, qui correspond à utiliser le formulaire QF
  3. franceconnect qui utilise uniquement FC pour accéder à l'API

A noter que je n'ai pas trop réfléchi aux ids techniques, ça peut changer encore.

Pour 2. et 3. il n'y a pas besoin de jeton, seul 1. a besoin d'un jeton.
Si il n'y a pas la modalité params il n'y a aucune raison de créer un jeton. En pratique à court terme params sera toujours présent je pense.

Je changerai bien le return if context.modalities.exclude?('params') en return if !from_datapass

Tout vient de DataPass, je ne comprends pas bien ta remarque du coup.

spec/support/fixtures_helpers.rb Outdated Show resolved Hide resolved
app/clients/hubee_api_authentication.rb Show resolved Hide resolved
Comment on lines +24 to +47
stub_request(:get, "#{host}/referential/v1/organizations/SI-#{siret}-#{code_commune}").to_return(
status: 200,
headers: { 'Content-Type' => 'application/json' },
body: valid_payload.to_json
)
end

it 'renders a valid json from payload' do
expect(find_organization_payload).to eq(valid_payload)
end
end

context 'when API returns 404' do
before do
stub_request(:get, "#{host}/referential/v1/organizations/SI-#{siret}-#{code_commune}").to_return(
status: 404,
headers: { 'Content-Type' => 'application/json' },
body: {
'header' => {
'statut' => 404,
'message' => "Aucun élément trouvé pour le siret #{siret}"
}
}.to_json
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je mettrais les stub requests dans un module comme tu as fait pour l'INSEE

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour l'INSEE j'ai cherry-pick, j'ai hésité à jarter le module car en pratique c'est seulement utilisé dans le test du client, donc aucun intérêt de l'isoler dans un module. (contrairement à DataPass).

Du coup je vais potentiellement faire l'inverse et simplifier en jartant le module INSEE, ok pour toi ?

spec/clients/hubee_api_client_spec.rb Show resolved Hide resolved
Copy link
Contributor

@Un3x Un3x left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ok globalement pour moi.

J'trouve ca intéressant le fait qu'on passe pas par nos propres services pour aller fetch l'insee, mais je comprends parfaitement pourquoi.

J'trouve les clients un poil lourd, mais en même temps c'est pas grave, c'est assez isolé et si on veut les reprendre plus tard on pourra tjrs le faire.

Comment on lines +44 to +55
context 'when modalities does no include params' do
before do
datapass_webhook_params['data']['data']['modalities'] = ['formulaire_qf']
end

it 'does not create a token' do
expect {
subject
}.not_to change(Token, :count)
end
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je pense que ce qui me confuse c'est le fait que :

  • sur un modalities = 'formulaire qf' on skip
  • sur un modalities = 'params' on avance

Et le titre c'est "no params modalities". Ca fait beaucoup de params.

Je changerai bien le return if context.modalities.exclude?('params') en return if !from_datapass

@skelz0r
Copy link
Member Author

skelz0r commented Jun 27, 2024

C'est ptêtre juste une impression mais j'ai le feeling que tu en as eu un peu marre à la fin x) le code perd un peu en clarté au fur et à mesure

C'est un souci ici. Qu'est-ce qui n'est pas clair ?

@skelz0r
Copy link
Member Author

skelz0r commented Jun 27, 2024

J'trouve les clients un poil lourd, mais en même temps c'est pas grave, c'est assez isolé et si on veut les reprendre plus tard on pourra tjrs le faire.

Une suggestion pour rendre ça moins lourd ?

@Un3x
Copy link
Contributor

Un3x commented Jun 27, 2024

Je pense que c'est juste le feeling des payloads des méthodes de subscription à hubee / insee.

On peut toujours pousser, je reprend l'exemple hubee on pourrait avoir une méthode create_element(url, payload) qui s'occupe uniquement de la requête + du raise et appeler cette méthode côté create_subscription et create_organization mais est ce qu'on s'en fiche pas un peu ? Ici on est dans une mise en place que j'imagine "temporaire" tant qu'on sait pas exactement jusqu'où ira FQF et HubEE

@skelz0r
Copy link
Member Author

skelz0r commented Jun 27, 2024

Il est vrai que j'aurais pu wrapper dans un api_call avec un block, mais bon dtf en vrai ce qui fait que c'est un feeling un peu huge reste la tête de la payload (et encore, j'ai quasiment rien mis en l'état va falloir que j'ajoute des champs)

@Samuelfaure
Copy link
Contributor

Samuelfaure commented Jun 27, 2024

@skelz0r Pour clarifier mon commentaire, le code est toujours OK dans les dernier commits, sinon j'aurais relevé des points précis plutôt qu'un vague feeling

C'est OK en l'état pour moi

@skelz0r skelz0r force-pushed the features/api-particulier-fqf-modality branch from 78e5316 to ec4f1b4 Compare July 2, 2024 14:39
@skelz0r skelz0r force-pushed the features/api-particulier-fqf-modality branch 2 times, most recently from a17cfb3 to 6747add Compare July 17, 2024 07:20
spec/clients/hubee_api_client_spec.rb Show resolved Hide resolved
app/clients/hubee_api_client.rb Outdated Show resolved Hide resolved
app/organizers/datapass_webhook/api_particulier.rb Outdated Show resolved Hide resolved
@JeSuisUnCaillou
Copy link
Contributor

JeSuisUnCaillou commented Aug 29, 2024

Remrque : Faut pas créer de jeton pour les communes sans éditeurs et sans dévellopeurs.
Je sais pas si c'est pertinent dans cette PR, ou si ça doit être géré dans datapass de ne pas envoyer de requête de création de jeton à api_particulier dans ces cas là.

CF https://linear.app/pole-api/issue/API-3170/sassurer-quaucun-jeton-api-particulier-ne-sera-cree-pour-les

@JeSuisUnCaillou
Copy link
Contributor

JeSuisUnCaillou commented Sep 2, 2024

Pour FQF, on voudrait pouvoir créer une subscription HubEE Active, en mode API, associée à un éditeur.
Pour ça il faut :

  • Créer une subscription "normale" : inactive, sans éditeur (delegationActor), sans accessMode
# POST /referential/v1/subscriptions
sub_body = {
  "datapassId"=>99999,
  "processCode"=>"CERTDC",
  "subscriber"=>{"type"=>"SI", "companyRegister"=>"21890254200016", "branchCode"=>"89254"},
  "notificationFrequency"=>"Unitaire",
  "validateDateTime"=>DateTime.now.iso8601,
  "updateDateTime"=>DateTime.now.iso8601,
  "status"=>"Inactif",
  "email"=>"[email protected]",
  "localAdministrator"=>{"email"=>"[email protected]"},
  # "accessMode"=>"API",
  # "delegationActor"=>{"type"=>"EDT", "companyRegister"=>"42424242424299", "branchCode"=>"92062"},
}
  • Update la subscription avec l'éditeur, et l'access mode, le status actif et la date d'activation. A noter que je ne sais pas ce qui est obligatoire dans le PUT, j'ai pas testé de retirer des champs un par un pour voir.
# PUT /referential/v1/subscriptions/#{subscription_id}
sub_update_body = {
  "datapassId"=>99999,
  "processCode"=>"CERTDC",
  "subscriber"=>{"type"=>"SI", "companyRegister"=>"21890254200016", "branchCode"=>"89254"},
  "notificationFrequency"=>"Unitaire",
  "validateDateTime"=>DateTime.now.iso8601, # à garder ?
  "updateDateTime"=>DateTime.now.iso8601, # à garder ?
  "email"=>"[email protected]",
  "status"=>"Inactif",
  "localAdministrator"=>{"email"=>"[email protected]"},
  "accessMode" => "API",
  "delegationActor"=>{"type"=>"EDT", "companyRegister"=>"42424242424299", "branchCode"=>"92062"},
  "activateDateTime"=>DateTime.now.iso8601, #NEEDED !
  "status"=>"Actif"
}

@jbfeldis jbfeldis force-pushed the features/api-particulier-fqf-modality branch from 2545d90 to 4f1339e Compare October 18, 2024 11:59

payload = subscription_payload.with_indifferent_access.merge({
status: 'Actif',
activateDateTime: DateTime.now.iso8601,

Choose a reason for hiding this comment

The 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

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

où ?

Copy link
Member Author

Choose a reason for hiding this comment

The 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.

@jbfeldis
Copy link

@skelz0r je te repasse la patate, je serai en vacances la semaine prochaine

il faudra un token FQF de prod

ça fonctionne (j'ai bidouillé pas mal pour réussir à faire des tests E2E en local) et ça va avec cette PR (n'hésitez pas à la reprendre !) https://github.com/etalab/data_pass/pull/476/files

Copy link
Member Author

@skelz0r skelz0r left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(je ne peux pas refuse vu que c'est ma PR)

2 gros points:

  1. Faut encapsuler la complexité du create puis update pour créer la subscription comme il faut, ça simplifiera la logique du code et cantonnera les trucs wtf dans le client (et on comprendra tout de suite que c'est l'API qui est mal foutu et non le dev qui a fait n'imp :D)
  2. Faut absolument séquencer avec gestion d'erreur la création de l'abo HubEE puis celle du FQF

app/clients/formulaire_qf_api_client.rb Show resolved Hide resolved

payload = subscription_payload.with_indifferent_access.merge({
status: 'Actif',
activateDateTime: DateTime.now.iso8601,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

où ?

app/clients/formulaire_qf_api_client.rb Show resolved Hide resolved
app/clients/formulaire_qf_api_client.rb Show resolved Hide resolved

payload = subscription_payload.with_indifferent_access.merge({
status: 'Actif',
activateDateTime: DateTime.now.iso8601,
Copy link
Member Author

Choose a reason for hiding this comment

The 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.

request.body.first
end

def update_subscription(authorization_request, subscription_payload, editor_payload = {})
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je renommerai cette méthode en activate_subscription, ainsi que le create_subscription en create_inactive_subscription, et je wrapperai les 2 dans un create_subscription

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 create_subscription, et les implémentations wtf vivent dans le client qui s'occupe de la complexité de l'API.

Bonus points:

  1. tu ne changes rien dans le code de l'organizer pour gérer ça, et demain si ils fixent, tu changes juste le client (ce qui est logique en fait) ;
  2. ça se comprend 100x plus en 1 commit avec un message

@@ -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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dans 100% des cas il s'agit d'un éditeur, autant mettre editor ici imo

Comment on lines 6 to 7
CreateFormulaireQFHubEESubscriptionJob.perform_later(context.authorization_request.id)
CreateFormulaireQFCollectivityJob.perform_later(context.authorization_request.id)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je comprends mieux ta question plus haut: en effet ici on ne peut pas scheduler 2 jobs dépendant de manière indépendante, il faudrait faire un CreateFormulaireQFAccessJob qui fait séquentiellement la création de l'accès HubEE, puis celui chez vous. Autrement c'est un sac de noeud à debug.

service_provider = authorization_request.extra_infos['service_provider']
subscription_update_payload = {}

if service_provider.present? && service_provider['type'] == 'editor'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

je ne comprend pas: ce n'est pas systématiquement le cas ?

@skelz0r
Copy link
Member Author

skelz0r commented Oct 20, 2024

@skelz0r je te repasse la patate, je serai en vacances la semaine prochaine

du coup si je comprends bien ça doit partir en prod semaine prochaine ?

@JeSuisUnCaillou
Copy link
Contributor

du coup si je comprends bien ça doit partir en prod semaine prochaine ?

On n'a pas de hard deadline comme ça, mais on aimerait effectivement pouvoir embarquer plus facilement les nouveaux éditeurs et leurs communes en automatisant la création des communes/abonnements. Je sais qu'on en a quelques uns qui peuvent bientôt arriver, faut checker avec Miryad pour savoir si ça attend.

@jbfeldis jbfeldis force-pushed the features/api-particulier-fqf-modality branch from 62e40b2 to 1eb51ab Compare November 4, 2024 14:02
skelz0r and others added 12 commits November 27, 2024 16:54
Huge cherry-pick from DataPass v2

Ref etalab/data_pass@7c36324
Will be used for HubEE
Co-authored-by: Jean-Baptiste Feldis <[email protected]>
Les abonnements HubEE doivent être créées avant d'être activés, ce
commit met en place cette séparation.
Pour associer un éditeur le webhook envoie maintenant le
service_provider associé à la demande (stocké dans extra_infos).

Une méthode pour récupérer un abonnement existant a aussi été ajoutée
pour rendre le webhook plus robuste.

La collectivité est aussi créée du côté du FormulaireQF.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants