introduce API with devise_token_auth for absence creation
Created by: adipasquale
https://trello.com/c/HT5A8XUE/1086-api-entrante-pour-les-absences
La doc allant avec cette nouvelle API a été rédigée et publiée en avance de phase sur https://doc.rdv-solidarites.fr/technique/api . Mieux vaut parcourir cette doc avant de review cette PR
Choix
- utilise https://github.com/lynndylanhurley/devise_token_auth qui semble être populaire et à peu près maintenue, mais pas parfaite, voir plus bas. La doc (https://devise-token-auth.gitbook.io/devise-token-auth) est bien rédigée mais pas très complète
- le
Gemfile
pointe vers le github de la gem pour recuperer la version 1.1.4 de cette gem qui retire la dépendance à sprockets - par défaut la gem rafraîchit l'access-token à chaque requête. Les clients utilisant l'API doivent donc coder cette logique pour utiliser l'access-token de la réponse précédente. Par souci de simplification pour l'instant, j'ai désactivé ce rafraîchissement automatique.
- Pour balancer cette baisse de la sécurité, j'ai par contre diminué le temps de validité d'un token. Par défaut il est à 2 semaines, je l'ai réduit à 1 jour. Cela signifie que les clients devront récupérer un nouveau token d'accès via la route
/api/v1/auth/sign_in
toutes les 24h . cela me parait acceptable, surtout pour les premiers usages qui seront des imports ponctuels d'absences - Je m'appuie sur les policies existantes, ce qui me semble la meilleure option pour maintenir la cohérence des droits d'accès entre l'interface web et l'API. J'ai du "améliorer" un peu
AbsencePolicy
pour supporter l'absence d'organisation dans les contextes pundit, je trouve ça plus clair et agréable que la route/api/v1/absences
ne soit pas nécessairement scopée par orga, mais que ça soit un param de filtrage optionnel
Concern DeviseTokenAuth::Concerns::User
Le concern DeviseTokenAuth::Concerns::User à ajouter sur le modèle de la gem fait beaucoup de choses et override des comportements de devise. Je n'arrivais pas à tout faire fonctionner en l'incluant directement dans Agent. Entre autres, ca demandait de renommer les routes agent_registration_path
qui faisaient des conflits, et d'autres soucis divers.
Pour éviter que ça ne casse des comportements de devise sur le modèle existant, j'ai créé un modèle distinct class AgentWithTokenAuth < Agent
dans lequel j'inclus ce concern.
Je dois tout de même inclure deux concerns dans Agent :
include DeviseTokenAuth::Concerns::ConfirmableSupport
include DeviseTokenAuth::Concerns::UserOmniauthCallbacks
Le deuxième est important car c'est lui qui s'assure que uid
reste synchronisé avec l'email des agents.
Points d'inquiétudes / défauts
- on est obligés d'ajouter 4 champs sur les agents et on ne peut pas modifier les noms qui ne sont pas très explicites :
provider
,uid
,tokens,
allow_password_change` - la gem n'a pas l'air complètement compatible avec Rails 6 cf issue https://github.com/lynndylanhurley/devise_token_auth/issues/1425
- La gem modifie le callback path d'omniauth et je n'arrive pas a reprendre la main dessus. pour verifier que la super admin fonctionne toujours, j'ai du modifier le callback path sur l'app de dev (temporairement) : https://github.com/organizations/rdv-solidarites/settings/applications , de
http://localhost:5000/super_admins/auth/github/callback
vershttp://localhost:5000/omniauth/github/callback
Outils utiles
- https://curl2httpie.online/ pour rédiger la doc
Pour review avec httpie sur la demo app
# sign_in and get header values
http --json POST 'https://demo-rdv-solidarites-pr946.osc-secnum-fr1.scalingo.io/api/v1/auth/sign_in' \
email='martine@demo.rdv-solidarites.fr' password='123456'
# list absences
http 'https://demo-rdv-solidarites-pr946.osc-secnum-fr1.scalingo.io/api/v1/absences' \
uid:martine@demo.rdv-solidarites.fr access-token:XXXXX client:XXX
# create absence
http --json POST 'https://demo-rdv-solidarites-pr946.osc-secnum-fr1.scalingo.io' \
access-token:XXXXX client:XXX uid:'martine@demo.rdv-solidarites.fr' \
organisation_id=1 agent_id=1 title="Congé parental" \
first_day="2020-11-20" start_time="08:00" \
end_day="2020-11-20" end_time="18:00"