Bien, la ZEP arrive doucement à son terme et c'est l'occasion pour moi de vous faire un compte rendu (presque) final de la situation puisque (presque) toutes les exigences de la spécification ont été intégrées dans le projet et sont fonctionnelles.
Avant toutes choses, voici toutes les routes intégrées au projet :
Authentification
Fonctionnalité : Authentifie un utilisateur donné.
URL : http://localhost:8000/oauth2/access_token
Methode : POST
Headers : Aucun obligatoire
Paramètres :
- client_id : Identifiant récupérer à la création du client.
- client_secret : Secret récupérer à la création du client.
- username : Username de l'utilisateur.
- password : Mot de passe de l'utilisateur.
- grant_type : password
Codes HTTP :
- 200 : La réponse est renvoyée sans problème.
Permissions nécessaires : N/A
Exemple de résultat :
| {
"access_token": "27a59cd8b1f3322707781c7347ca20f8e141e594",
"token_type": "Bearer",
"expires_in": 31535999,
"refresh_token": "e751cc50ae9a74e20d9d1f4890b86ab01ad5f343",
"scope": "read"
}
|
Attention : Demande une manipulation dans l'interface administrateur du site pour créer un "client" (au sens OAuth2).
Liste de tous les membres
Fonctionnalité : Renvoie une liste paginée pour lister les membres par 10.
URL : http://localhost:8000/api/membres/
Methode : GET
Headers : Aucun obligatoire
Paramètres :
- page : Affiche les membres de la page voulue.
- search : Effectue une recherche sur le pseudonyme des membres.
Codes HTTP :
- 200 : La réponse est renvoyée sans problème.
- 404 : La page n'existe pas.
Permissions nécessaires : N/A
Exemple de résultat pour l'URL http://localhost:8000/api/membres/?page=2
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 | {
"count": 27,
"next": "http://localhost:8000/api/membres/?page=3",
"previous": "http://localhost:8000/api/membres/?page=1",
"results": [
{
"id": 17,
"username": "user20",
"is_active": false,
"date_joined": "2015-01-10T22:31:50.908831"
},
{
"id": 16,
"username": "user10",
"is_active": false,
"date_joined": "2014-12-29T22:24:49.158187"
},
{
"id": 15,
"username": "user9",
"is_active": false,
"date_joined": "2014-12-29T22:24:00.998709"
},
{
"id": 14,
"username": "user7",
"is_active": false,
"date_joined": "2014-12-29T22:13:43.436301"
},
{
"id": 13,
"username": "user6",
"is_active": false,
"date_joined": "2014-12-29T02:24:43.165852"
},
{
"id": 12,
"username": "user5",
"is_active": false,
"date_joined": "2014-12-29T01:48:24.547008"
},
{
"id": 11,
"username": "user4",
"is_active": false,
"date_joined": "2014-12-29T01:40:18.297339"
},
{
"id": 10,
"username": "user3",
"is_active": false,
"date_joined": "2014-12-29T01:39:32.523008"
},
{
"id": 9,
"username": "user2",
"is_active": true,
"date_joined": "2014-12-29T01:38:56.561351"
},
{
"id": 8,
"username": "user1",
"is_active": true,
"date_joined": "2014-12-29T01:37:16.703046"
}
]
}
|
Création d'un membre
Fonctionnalité : Création d'un membre inactif (un mail est envoyé pour qu'il valide son inscription).
URL : http://localhost:8000/api/membres/
Methode : POST
Headers : Aucun obligatoire
Paramètres :
- username : Pseudo du futur membre.
- email : Adresse e-mail du futur membre.
- password : Mot de passe du futur membre.
Codes HTTP :
- 200 : La réponse est renvoyée sans problème.
- 400 : Dès qu'il y a un problème avec les paramètres de la requête.
| {
"username": [
"This field must be unique."
],
"password": [
"This field may not be blank."
]
}
|
Permissions nécessaires : N/A
Exemple de résultat :
| {
"username": "Andr0",
"email": "test@zestedesavoir.com",
"password": "pbkdf2_sha256$12000$89HbWyOVZTZI$T5Tk9cfKhEzubf8TF92rh/uX1nYnIcYLGKOYp4sFim8="
}
|
Informations d'un membre donné
Fonctionnalité : Donne toutes les informations sur un membre donné.
URL : http://localhost:8000/api/membres/{id}/
Methode : GET
Headers : Aucun obligatoire
Paramètres : N/A
Codes HTTP :
- 200 : La réponse est renvoyée sans problème.
- 404 : Le membre avec l'identifiant donné n'existe pas.
Permissions nécessaires : N/A
Exemple de résultat pour l'URL http://localhost:8000/api/membres/1/
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | {
"id": 1,
"username": "admin",
"show_email": true,
"email": "admin@email.com", # Attribut affiché si show_email est à true
"is_active": true,
"site": "www.zestedesavoir.com",
"avatar_url": "https://cdn-images.xda-developers.com/direct/1/6/3/5/9/8/6/yoda-droid.jpg",
"biography": "testou",
"sign": "Testi",
"email_for_answer": false,
"last_visit": "2015-01-11T17:27:08.264549",
"date_joined": "2014-12-26T23:11:59.200374"
}
|
Modification d'un membre donné
Fonctionnalité : Modifie les informations d'un membre donné.
URL : http://localhost:8000/api/membres/{id}/
Methode : PUT
Headers :
- Authorization : Bearer < access token >
Paramètres :
- Champ du modèle d'un utilisateur
Codes HTTP :
- 200 : La réponse est renvoyée sans problème.
- 400 : Dès qu'il y a un problème avec les paramètres de la requête.
- 401 : Problème avec l'authentification.
- 403 : Pas les permissions nécessaires.
- 404 : Le membre avec l'identifiant donné n'existe pas.
Permissions nécessaires :
- Être identifié (fournir dans
Authorization
dans l'en-tête de la requête).
- L'identifiant renseigné correspond à l'identifiant de l'utilisateur authentifié.
Exemple de résultat pour l'URL http://localhost:8000/api/membres/1/
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | {
"id": 1,
"username": "admin",
"show_email": true,
"email": "admin@email.com",
"is_active": true,
"site": "www.zestedesavoir.com",
"avatar_url": "https://cdn-images.xda-developers.com/direct/1/6/3/5/9/8/6/yoda-droid.jpg",
"biography": "testou",
"sign": "Testi",
"email_for_answer": false,
"last_visit": "2015-01-11T17:27:08.264549",
"date_joined": "2014-12-26T23:11:59.200374"
}
|
Lecture seule sur un membre
Fonctionnalité : Sanctionner un membre en lecture seule.
URL : http://localhost:8000/api/membres/{id}/lecture-seule/
Methode : POST
ou DELETE
Headers :
- Authorization : Bearer < access token >
Paramètres :
- ls-jrs : Pour passer le membre en lecture seule temporairement.
- ls-text : Pour donner une explication à la sanction au membre donné.
Codes HTTP :
- 200 : La réponse est renvoyée sans problème.
- 401 : Si un problème dans l'authentification (utilisateur supprimé ou inactif).
- 403 : Pas les permissions nécessaires.
- 404 : Le membre avec l'identifiant donné n'existe pas.
Permissions nécessaires :
- Être identifié (fournir dans
Authorization
dans l'en-tête de la requête).
- Avoir les permissions d'un staff.
Exemple de résultat pour l'URL http://localhost:8000/api/membres/{id}/lecture-seule/
:
| {
"id": 4,
"username": "ïtrema",
"email": "",
"can_write": false,
"end_ban_write": "2015-01-13T18:50:40.400991",
"can_read": true,
"end_ban_read": null
}
|
Bannissement d'un membre
Fonctionnalité : Sanctionner un membre par un bannissement.
URL : http://localhost:8000/api/membres/{id}/ban/
Methode : POST
ou DELETE
Headers :
- Authorization : Bearer < access token >
Paramètres :
- ban-jrs : Pour passer le membre en bannissement temporairement.
- ban-text : Pour donner une explication à la sanction au membre donné.
Codes HTTP :
- 200 : La réponse est renvoyée sans problème.
- 401 : Si un problème dans l'authentification (utilisateur supprimé ou inactif).
- 403 : Pas les permissions nécessaires.
- 404 : Le membre avec l'identifiant donné n'existe pas.
Permissions nécessaires :
- Être identifié (fournir dans
Authorization
dans l'en-tête de la requête).
- Avoir les permissions d'un staff.
Exemple de résultat pour l'URL http://localhost:8000/api/membres/{id}/ban/
:
| {
"id": 4,
"username": "ïtrema",
"email": "",
"can_write": true,
"end_ban_write": null,
"can_read": false,
"end_ban_read": "2015-01-13T18:51:14.315816"
}
|
Informations générales
Headers possibles
- Accept : L'API accepte plusieurs rendus, à savoir le JSON (par défaut) et l'XML. Toutes les requêtes peuvent donc renvoyer un résultat dans ces deux formats.
- Content-Type : L'API accepte plusieurs parsers, à savoir le JSON (par défaut), l'XML, le formulaire et le multi part (
x-www-form-urlencoded
).
- Authorization : Renseigne le token d'authentification pour toutes les requêtes qui nécessitent une authentification.
- ETag : Attention, header en réponse par le serveur. J'en reviens dans la section juste après.
Cache
Des systèmes de cache ont été installés. Au pluriel puisqu'il y en a deux :
- ETag : Pour toutes les requêtes
GET
et PUT
, un ETag est calculé par le serveur et renvoyé dans l'en-tête de la réponse (disponible sous le même nom, ETag). Il réagit à l'identique que la spécification de cette ZEP.
- Cache : Toutes les requêtes
GET
disposent d'un cache de 15 minutes (paramétrable). Les requêtes peuvent donc passer de plus de 200ms à +/- 70ms. Attention, ces chiffres sont à prendre avec des pincettes puisque les tests ont été effectués en local avec ma configuration de ZdS. Mais il y aura d'office un gain dans le temps de réponse de la requête.
Les différences
Mettons le doigt sur les différences avec la spécification de la ZEP :
- Les URLs ne sont pas sous la forme
http://api.zestedesavoir.com/
mais http://www.zestedesavoir.com/api/
. Cependant, ceci peut changer lors de la mise en production de la fonctionnalité.
User-Agent
n'est pas obligatoire. Je ne suis pas parvenu à savoir comment faire et j'ai fini par me demander si c'était vraiment inutile.
- CORS n'est pas supporté. J'ai pu trouvé une librairie simple à intégrer mais je ne suis pas assez compétent pour sa configuration.
- Erreurs HTTP : Le code de l'erreur n'est pas renseigné dans le body de la réponse mais dans l'en-tête.
- Le format
X-Data-Format
n'est pas supporté au vu de l'absence de nécessité.
- La recherche et les associations (les éléments hors scopes) n'ont pas été intégrés.
- Aucun versionning de l'API n'a été mise en oeuvre.
Voilà, je pense n'avoir rien oublié. En écrivant ce compte-rendu, j'ai pu décelé quelques bugs (notamment lié aux permissions comme vous avez pu le lire dans ce compte-rendu) que je vais corriger dans les heures ou jours à venir.
Après ça et si ce compte rendu va à tout le monde, il suffit de rebase notre ZEP par rapport au dépôt officiel et de faire la PR de la ZEP sur ce même dépôt.