Erreur 496 : Impossible d'arrêter de rire    —  Bill Gates

Discussions

Base de données / Python / AngularJS / ...

Fabe 610 Geek
Reprise automatique du message précédent.
La relation n'est navigable que dans un sens ?
L'objet A ne donne pas le lien vers les objets B associés ?

Sinon le principe du filtre semble valide mais il est moins "auto-découvrable" que de simplement naviguer entre les ressources de l'API.

Par contre dans une API REST, il faut éviter d'avoir des verbes d'actions comme "list" dans les chemins de l'API : /api/B doit lister toutes les entités "B", "/api/B/3" doit retourner uniquement celle d'identifiant 3.
Le principe du REST est d'utiliser exclusivement les verbes fournis par HTTP.
Guybrush 8428 Bob
FabeLa relation n'est navigable que dans un sens ?
L'objet A ne donne pas le lien vers les objets B associés ?
Il s'agit grosso modo de compétences qu'une personne possède. J'ai d'un coté une liste de personnes, de l'autre une liste de compétences, et entre les deux le lien. En pratique, l'application doit permettre d'obtenir les compétences d'une personne, et aussi d'obtenir les personnes à partir d'une compétence. Donc, oui, c'est navigable dans les deux sens malheureusement.

J'ai donc :
- /personnes/3/competences --> liste des compétences de la personne 3.
- /competences/14/personnes --> liste des personnes de la compétence 14

ou
- /nom-du-lien/?personne=3 --> liste des compétences de la personne 3.
- /nom-du-lien/?competence=14 --> liste des compétences de la personne 14.

En "GET", ça ne change pas fondamentalement grand chose. Par contre, en PUT ou DELETE, ça signifie que :
- Dans le premier cas, je peux faire un appel sur /personnes/3/competences/14 -> supprime/modifie le lien entre la personne 3 et la compétence 14.
- Dans le deuxième cas, je peux faire un appel sur /nom-du-lien/1230 --> supprime/modifie le lien dont la pk est 1230, et qui implicitement correspond à la personne 3 et la compétence 14.

J'ai donc une préférence pour la première solution...
FabeSinon le principe du filtre semble valide mais il est moins "auto-découvrable" que de simplement naviguer entre les ressources de l'API.
Dans l'application que j'envisage, l'API n'est utilisée que par l'application, elle n'a pas vocation de pouvoir être utilisée par d'autres personnes (et je souhaite d'ailleurs fortement limiter cela, notamment en interdisant les cross-requests, sauf le temps du développement, parce que ce sera accédé à partir d'une page statique + angularJS, donc pas besoin d'un serveur de test).

[quote=Fabe
Par contre dans une API REST, il faut éviter d'avoir des verbes d'actions comme "list" dans les chemins de l'API : /api/B doit lister toutes les entités "B", "/api/B/3" doit retourner uniquement celle d'identifiant 3.
[/quote]

En effet. Il me semblait avoir vu "list" quelque part, mais même si c'était le cas, je suis convaincu qu'il vaut mieux s'en passer ;-)


Fabe 610 Geek
GuybrushJ'ai donc :
- /personnes/3/competences --> liste des compétences de la personne 3.
- /competences/14/personnes --> liste des personnes de la compétence 14
...
- Dans le premier cas, je peux faire un appel sur /personnes/3/competences/14 -> supprime/modifie le lien entre la personne 3 et la compétence 14.
...
J'ai donc une préférence pour la première solution...
[/quote}

Moi aussi ! Surtout si ton lien n'est pas porteur d'information, il n'a pas besoin d'être exposé dans l'API.

[quote=Guybrush]
Dans l'application que j'envisage, l'API n'est utilisée que par l'application, elle n'a pas vocation de pouvoir être utilisée par d'autres personnes (et je souhaite d'ailleurs fortement limiter cela, notamment en interdisant les cross-requests, sauf le temps du développement, parce que ce sera accédé à partir d'une page statique + angularJS, donc pas besoin d'un serveur de test).
Une API bien construite et auto-documentée est la partie visible d'une application bien conçue. Tu te remercieras plus tard si un jour ou l'autre tu souhaite améliorer ton client AngularJS, d'avoir une API qui suggère son utilisation :-)
Rien à voir avec la sécurité cela dit.
GuybrushEn effet. Il me semblait avoir vu "list" quelque part, mais même si c'était le cas, je suis convaincu qu'il vaut mieux s'en passer ;-)
Ça va parfois mieux en le disant, j'ai déjà fait démonter un petit nombre d'API qui nous faisait des routes en /users/create et /users/list. I
l y a malheureusement beaucoup de gens qui pensent que faire un début de distinction entre POST et GET suffisent à faire du REST et qui ne remettent pas en questions leurs mauvais réflexes de formulaires HTML :-)
Guybrush 8428 Bob
J'ai finalisé mon API, et elle est auto-documentée (merci Django Rest Framework). J'ai déjà bien entamé mon application AngularJS (évidement, ça demande un peu de temps vu que c'est ma première tentative). Pour l'instant, je suis content : j'ai pu faire tout ce que je voulais, et le code reste extrêmement propre !

Dans les grandes lignes, via un unique tableau :
- Liste d'objets avec modification "inline" des différents attributs ;
- Ajout/suppression d'objets ;
- Ajout/suppression d'éléments dans une relation one-to-many directement depuis la case (avec petits boutons + et -, coloration des éléments ajoutés/supprimés et validation via le bouton en fin de ligne qui valide aussi les modifications des attributs sur la ligne).

Mes services sont bien découplés des contrôleurs, ce qui rend le tout très simple à modifier pour ajouter d'autres tableaux. Prochaines étapes :
- Gérer un tableau qui vise à fournir une vue d'un agenda hebdomadaire ;
- Permettre de "colorer" le tableau pour indiquer des préférences d'horaire ;
- Permettre du drag&drop dans le tableau (et en dehors, les éléments non placés) avec coloration des emplacements "non-autorisés".
Guybrush 8428 Bob
Encore une question à propos d'API, etc.

J'ai commencé à faire mes armes avec AngularJS et aussi avec Node (Express, et tout ce qui tourne autour, et y a un paquet de trucs qui tournent autour :-D) et je me posais une question sur les applications single-page (ou même pour les "multi-pages", mais reposant sur une API) : comment gérer l'authentification ?

Je veux dire : il m'est simple de concevoir un truc du genre /api/auth/login, /api/auth/logout, /api/auth/signin, etc. mais comment "mémoriser" le statut de la personne ? Actuellement, sur Lexpage, c'est un cookie qui stocke un id de session chiffré et signé, et j'utilise cet id de session pour repêcher les informations liées à l'utilisateur. Mais quand on a essentiellement du code coté client, que faire ?

1. La page affiche la partie "visiteur", et propose un formulaire pour s'identifier. Ce formulaire effectue un appel à /api/auth/login, et une session est débutée sur le serveur, identifiée via cookie sur le client, et les appels ultérieurs à l'api suppose l'existence d'une telle session (par ex : DELETE /api/world/all retournera une erreur sur le user de la session n'est pas un dieu, mais fonctionnera le cas contraire). Dans ce cas, l'api n'est pas stateless et pas "auto-consistante" (puisque deux appels identiques peuvent générer des résultats différents sur base de l'historique des appels, à savoir avoir /api/auth/login qui répond positivement).

2. Un peu pareil que le précédent, sauf que /api/auth/login va retourner un token (l'équivalent de l'identifiant de session stocké dans le cookie). Ce token sera systématiquement envoyé lors d'un appel à l'api et servira à authentifier l'utilisateur à chacune de ses requêtes. L'avantage, c'est que l'api est stateless. L'inconvénient, c'est que le token doit être transmis à chaque appel (bon, ok, un cookie fait pareil) et que ce n'est pas vraiment faisable pour certains verbes HTTP (il me semble que DELETE n'accepte pas de "data" normalement ?).

Je suis plutôt partant pour la première solution (vu que les cookies/sessions font partie du HTTP), mais avant de m'engager là-dedans, j'aimerai vos avis d'experts :-D
Fabe 610 Geek
Lire la RFC OAuth (oui bon c'est de la RFC, faut s'la farcir) va certainement t'inspirer.

En ce qui me concerne, pour un cas simple comme le tiens, je privilégierai une solution basée sur le workflow Client Credentials. Les tokens peuvent passer dans les entêtes d'Authorization HTTP Basic, et ton API reste bien stateless :-)

C'est ce qui est le plus proche de ta solution 2 :-)


Ce message a été modifié 1 fois. Dernière modification : 26 décembre 2014 à 14:26 par Fabe.

Guybrush 8428 Bob
Ok, je vois un peu mieux comment ça fonctionne. Il faut vraiment que je pense à me renseigner sur OAuth de façon générale, car je crois que c'est quelque chose qui devient peu à peu incontournable (ou en tout cas, rudement pratique pour certains cas "très grand public").
Fabe 610 Geek
GuybrushOk, je vois un peu mieux comment ça fonctionne. Il faut vraiment que je pense à me renseigner sur OAuth de façon générale, car je crois que c'est quelque chose qui devient peu à peu incontournable (ou en tout cas, rudement pratique pour certains cas "très grand public").
Ce qu'on sait moins, c'est que ça convient bien et que ça permet de standardiser les cas d'authentification simples et pas spécialement grand public. A noter aussi l'existence d'SAML comme DSL d'authentification.
Je trouve la spéc d'OAuth assez compliquée, c'est un peu rebutant pour des cas simples où on a l'impression qu'on irait aussi vite à faire un protocole custom, mais ça vaut toujours le coup de standardiser.
Guybrush 8428 Bob
Ca dépend un peu de ce qu'on veut pouvoir proposer. Personnellement, je ne m'identifie jamais en utilisant un réseau social, ou quoique ce soit du genre. J'ai toujours mon bon vieux couple user/password (site-specific) que je n'abandonnerai pas, essentiellement parce que ça devient difficile de se souvenir, dans le cas contraire, sur quel site on s'est "inscrit" en utilisant Facebook, Twitter, Google+ ou autre.

Pour une API, de toute façon, il faut "juste" avoir un token à transmettre systématiquement (y a des snippets pour Angular pour gérer ça de façon transparente, incluant un re-login en cas d'expiration du token, notamment) et du coté serveur, simplement vérifier que ce token a les droits pour accéder à la ressource concernée. Peu importe comment ce token est généré (ou presque). Tant que j'utilise quelque chose de "proche d'OAuth", c'est suffisant :-D

Ensuite, pour identifier réellement l'utilisateur (et éventuellement générer/ré-utiliser un token pour mon API), là, oui, y a un peu plus de boulot si on veut pouvoir permettre l'authentification par des sites extérieurs (et surtout permettre à l'utilisateur d'associer plusieurs comptes s'il le désire, même un compte "local").

Merci pour le pointeur en tout cas, je vais poursuivre mes lectures là-dessus (je suis en phase de "repérage" de tout ce que je souhaite apprendre rapidement dans les "nouvelles technologies" afin de partir avec un stack complet et cohérent ^^).
Fabe 610 Geek
GuybrushCa dépend un peu de ce qu'on veut pouvoir proposer. Personnellement, je ne m'identifie jamais en utilisant un réseau social, ou quoique ce soit du genre. J'ai toujours mon bon vieux couple user/password (site-specific) que je n'abandonnerai pas, essentiellement parce que ça devient difficile de se souvenir, dans le cas contraire, sur quel site on s'est "inscrit" en utilisant Facebook, Twitter, Google+ ou autre.
Ça c'est le cas d'un "client" OAuth, mais toi ton besoin est d'établir un "provider". Donc la question est de soit faire un protocole custom, soit d'utiliser la spéc OAuth :-)

J'ai récemment intégré un site de contenu (CMS) avec un site e-commerce avec OAuth comme mécanisme de "single sign-on". C'est transparent pour l'utilisateur qui n'a nul besoin d'un compte facebook ou que sais-je, seulement de voir sa fiche client e-commerce depuis le CMS par connexion de celui-ci à l'API du e-commerce.

Après OAuth n'est "que" un protocole, la gestion et la génération des tokens, des utilisateurs, etc... reste à ta charge. Il n'est pas non plus spécialement détenu par un ensemble d'acteur du web en particulier et n'impose pas d'utiliser des comptes publics. C'est simplement le descendant de feu OpenID, décliné pour les use-cases courants du web (HTML, API, etc...)


Ce message a été modifié 1 fois. Dernière modification : 26 décembre 2014 à 16:12 par Fabe.

Guybrush 8428 Bob
Je n'ai pas encore lu suffisamment pour saisir la nuance entre "provider OAuth" et "une API proposant un /auth/login" (in: username/password, out: token) :blush:

Y a des histoires de redirection, d'échange d'informations, etc. que je dois encore lire pour saisir tout ça. Mais grosso-modo, je pense dans un premier temps m'orienter vers une solution à base de token jwt, que je stockerai probablement dans le localStorage (vu que je lis partout qu'il faut éviter les cookies, mais il faut encore que je lise pourquoi) et que j'injecterai dans les appels HTTP à l'API comme tu le suggérais.

En gros, c'est la solution actuellement utilisée sur Lexpage, sauf que :
- J'utilise le cookie pour stocker le token plutôt que le localStorage ;
- Le token est plutôt un identifiant de session signé, et pas vraiment un token chiffré ;
- L'injection se fait via le cookie automatiquement, et non pas via un en-tête ;
- L'expiration est réglée coté client, et pas coté serveur.

Oui, ok, ça ne ressemble pas vraiment :-D

Répondre

Vous devez être inscrit et identifié.