Accueil > OpenID Connect OAuth Serveur dédié > Développer > Adaptation des applications > API HTTP REST + TreeQL

API HTTP REST + TreeQL

OAuthSD expose maintenant une deuxième API HTTP REST. Comme la première (qui reste disponible) cette API permet d’automatiser certaines tâches autour du serveur d’authentification. Une application d’administration (supervision) peut ainsi contrôler les données du serveur.
Cette nouvelle API s’appuie sur php-crud-api. Les objets sont manipulés sous des format scalaires ou json simples. Elle offre plus de possibilités de requêtes en suivant le format TreeQL.

Remarque : Cette API pourrait remplacer l’API HTTP REST à moyen terme.

Sécurisation de l’accès à l’API et transmission du rôle de l’utilisateur final

La sécurisation de l’accès à l’API HTTP REST + TreeQL est effectué à l’aide d’un jeton d’identité au format JWT émis par l’application cliente.

Ce jeton transmet le rôle de l’utilisateur au moyen de la déclaration ’scope’ prenant l’une des valeurs ’admin’, ’writer’, ’reader’ and ’none’. Pour cela (voir Définition des scopes OIDC et généralités sur leur utilisation par les applications) :
- l’application cliente doit utiliser OIDC et initialiser le flux d’autorisation avec code avec la demande d’autorisation (requested_scope) ’scope=privileges’,
- L’application cliente doit avoir été enregistrée avec la valeur ’privileges’ dans la liste de Scopes disponibles (Available scopes),
- une valeur parmi ’admin’, ’writer’, ’reader’ and ’none’ doit avoir été enregistrée dans la table users pour l’utilisateur final considéré.

Le jeton peut être passé dans l’URL (méthode GET), par POST ou par la méthode Authorization : Bearer.

Exemple d’appel avec la méthode GET :

https://oa.dnc.global/http.api/api.php/records/spip_users/1/?token=eyJ0eXAiOiJKV...

L’API valide le jeton JWT par introspection. OAuthSD garantit ainsi l’authenticité de l’application cliente. Voir : Vérification de l’origine de la requête reçue par un serveur de ressource.

En cas d’erreur d’authentification, l’API retourne un code HTTP 403 Forbidden et un corps vide.

Limitation de l’accès aux tables et aux champs

- seules les tables ’users’, ’clients’, ’scopes’, ’oidc_logs’ sont accessibles.

L’authentification de l’utilisateur final conduit à définir les rôles ’admin’, ’writer’, ’reader’ et ’none’. Le rôle ’admin’ peut effectuer l’ensemble des opérations.

Pour le rôle "writer" :
- dans la table ’public_keys’, la seule opération permise est la lecture de la clé clé publique.
- dans la table ’oauth_clients’, l’accès au champ password est interdit.
- dans la table ’oauth_users’, l’accès au champ client_secret est interdit.

Pour le rôle ’reader’ :
- les restriction d’accès sont les mêmes que le rôle ’writer’,
- seules les opérations ’read’ et ’list’ sont autorisées.

Le rôle ’none’ ne peut que lire la table ’oidc_logs’.

Opérations CRUD + List : Référence de l’API

Voyez également :
- https://oa.dnc.global/http.api/spec/swagger/static/
- https://editor.swagger.io/?url=https://oa.dnc.global/http.api/api.php/openapi

Sélections avancées

Sur les opérations de liste, vous pouvez appliquer des filtres et des jointures.

Les exemples suivants supposent la table suivante :

posts
id
titre
content message

Filtres

Les filtres fournissent une fonctionnalité de recherche sur les appels de liste, en utilisant le paramètre "filter". Vous devez spécifier le nom de la colonne, une virgule, le type de correspondance, une autre virgule et la valeur que vous souhaitez filtrer.

Types de match supportés :

"cs" : contient une chaîne (la chaîne contient une valeur)
"sw" : commence par (chaîne commence par valeur)
"ew" : se termine par (chaîne se termine par valeur)
"eq" : égal (la chaîne ou le nombre correspond exactement)
"lt" : inférieur à (nombre inférieur à la valeur)
"le" : inférieur ou égal (le nombre est inférieur ou égal à la valeur)
"ge" : supérieur ou égal (le nombre est supérieur ou égal à la valeur)
"gt" : supérieur à (nombre supérieur à la valeur)
"bt" : entre (le nombre est entre deux valeurs séparées par une virgule)
"in" : in (le nombre ou la chaîne est dans une liste de valeurs séparées par des virgules)
"is" : est null (le champ contient la valeur "NULL")

Vous pouvez annuler tous les filtres en ajoutant un caractère "n", afin que "eq" devienne "neq". Exemples d’utilisation du filtre :

GET / records / categories? Filter = nom, eq, Internet
GET / records / categories? Filter = nom, sw, Inter
GET / records / categories? Filter = id, le, 1
GET / records / categories? Filter = id, ngt, 2
GET / records / categories? Filter = id, bt, 1,1

Filtres multiples

Les filtres peuvent être appliqués en répétant le paramètre "filter" dans l’URL. Par exemple l’URL suivante :

GET / records / categories ? Filter = id, gt, 1 & filter = id, lt, 3

demandera toutes les catégories "où id> 1 et id <3". Si vous vouliez "où id = 2 ou id = 4", vous devriez écrire :

GET / enregistrements / catégories ? Filter1 = id, eq, 2 & filter2 = id, eq, 4

Comme vous le voyez, nous avons ajouté un numéro au paramètre "filter" pour indiquer que "OR" au lieu de "AND" doit être appliqué. Notez que vous pouvez également répéter "filter1" et créer un "ET" dans un "OU". Comme vous pouvez également aller plus loin en ajoutant une lettre (a-f), vous pouvez créer presque n’importe quel arbre de conditions relativement complexe.

Notes :
- Vous ne pouvez filtrer que sur la table demandée (pas sur la table incluse) et les filtres ne sont appliqués qu’aux appels de liste.

Sélection de colonne

Par défaut, toutes les colonnes sont sélectionnées. Avec le paramètre "include", vous pouvez sélectionner des colonnes spécifiques. Vous pouvez utiliser un point pour séparer le nom de la table du nom de la colonne. Plusieurs colonnes doivent être séparées par des virgules. Un astérisque ("*") peut être utilisé comme caractère générique pour indiquer "toutes les colonnes". Semblable à "include", vous pouvez utiliser le paramètre "exclude" pour supprimer certaines colonnes :

GET / enregistrements / catégories / 1 ? Include = nom
GET /records/categories/1 ?include=categories.name
GET /records/categories/1 ?exclude=categories.id

Sortie :

   {
       "nom": "Internet"
   }

Notes :
- Les colonnes utilisées pour inclure des entités associées sont automatiquement ajoutées et ne peuvent pas être omises de la sortie.

Tri

Avec le paramètre "order", vous pouvez trier. Par défaut, le tri s’effectue par ordre croissant, mais en spécifiant "desc", cela peut être inversé :

GET / records / categories ? Order = nom, desc
GET / enregistrements / catégories ? Order = id, desc & order = name

Sortie :

   {
       "records": [
           {
               "id": 3
               "name": "développement Web"
           },
           {
               "id": 1
               "nom": "Internet"
           }
       ]
   }

Notes :
- Vous pouvez trier sur plusieurs champs en utilisant plusieurs paramètres "ordre". Vous ne pouvez pas commander sur des colonnes "jointes".

Taille limite

Le paramètre "size" limite le nombre d’enregistrements renvoyés. Ceci peut être utilisé pour les N premières listes avec le paramètre "order" (utilisez l’ordre décroissant).

GET / records / categories ? Order = id, desc & size = 1

Sortie :

   {
       "records": [
           {
               "id": 3
               "name": "développement Web"
           }
       ]
   }

Notes :
- Si vous souhaitez également connaître le nombre total d’enregistrements, vous pouvez utiliser le paramètre "page".

Pagination

Le paramètre "page" contient la page demandée. La taille de page par défaut est 20, mais peut être ajustée (par exemple à 50).

GET / records / categories ? Order = id & page = 1
GET / records / categories ? Order = id & page = 1,50

Sortie :

   {
       "records": [
           {
               "id": 1
               "nom": "Internet"
           },
           {
               "id": 3
               "name": "développement Web"
           }
       ],
       "résultats": 2
   }

Notes :
- les pages non commandées ne pouvant pas être paginées, elles seront classées par clé primaire.

Jointures

Supposons que vous ayez une table des publications qui comporte des commentaires (formulés par les utilisateurs) et que les publications puissent avoir des balises. Les exemples suivants supposent le jeu de tables suivant :

posts commentaires utilisateurs post_tags tags
id id id id id
titre post_id nom d’utilisateur post_id nom
content user_id phone tag_id
message créé

Lorsque vous souhaitez répertorier les publications avec leurs commentaires, les utilisateurs et les balises, vous pouvez demander deux chemins "arborescents" :

messages -> commentaires -> utilisateurs
posts -> post_tags -> tags
Ces chemins ont la même racine et cette demande peut être écrite au format URL comme suit :

GET / records / posts ? Join = commentaires, utilisateurs & tags = join

Ici, vous êtes autorisé à laisser de côté la table intermédiaire qui lie les publications aux balises. Dans cet exemple, les trois types de relation de table (hasMany, belongsTo et hasAndBelongsToMany) sont en jeu :

"post" a beaucoup de "commentaires"
"commentaire" appartient à "utilisateur"
"post" a et appartient à beaucoup de "tags"

Cela peut entraîner les données JSON suivantes :

{
   "records": [
       {
           "id": 1,
           "title": "Bonjour tout le monde!",
           "content": "Bienvenue dans le premier message.",
           "created": "2018-03-05T20: 12: 56Z",
           "commentaires": [
               {
                   id: 1,
                   post_id: 1,
                   identifiant d'utilisateur: {
                       id: 1,
                       nom d'utilisateur: "mevdschee",
                       téléphone: null,
                   },
                   message: "Salut!"
               },
               {
                   id: 2,
                   post_id: 1,
                   identifiant d'utilisateur: {
                       id: 1,
                       nom d'utilisateur: "mevdschee",
                       téléphone: null,
                   },
                   message: "Salut encore!"
               }
           ],
           "Mots clés": []
       },
       {
           "id": 2,
           "title": "Le noir est le nouveau rouge",
           "content": "Ceci est le deuxième message.",
           "created": "2018-03-06T21: 34: 01Z",
           "commentaires": [],
           "Mots clés": [
               {
                   id: 1,
                   message: "drôle"
               },
               {
                   id: 2,
                   message: "informatif"
               }
           ]
       }
   ]
}

Vous voyez que les relations "belongsTo" sont détectées et la valeur de la clé étrangère est remplacée par l’objet référencé. Dans le cas de "hasMany" et "hasAndBelongsToMany", le nom de la table est utilisé comme nouvelle propriété de l’objet.

Opérations par lots

Lorsque vous souhaitez créer, lire, mettre à jour ou supprimer, vous pouvez spécifier plusieurs valeurs de clé primaire dans l’URL. Vous devez également envoyer un tableau au lieu d’un objet dans le corps de la demande pour créer et mettre à jour.

Pour lire un enregistrement de cette table, la demande peut être écrite au format URL sous la forme suivante :

GET / records / posts / 1,2

Le résultat peut être :

[
       {
           "id": 1,
           "title": "Bonjour tout le monde!",
           "content": "Bienvenue dans le premier message.",
           "created": "2018-03-05T20: 12: 56Z"
       },
       {
           "id": 2,
           "title": "Le noir est le nouveau rouge",
           "content": "Ceci est le deuxième message.",
           "created": "2018-03-06T21: 34: 01Z"
       }
]

De même, lorsque vous souhaitez effectuer une mise à jour par lot, la demande au format URL est écrite comme suit :

PUT / records / posts / 1,2

Où "1" et "2" sont les valeurs des clés primaires des enregistrements que vous souhaitez mettre à jour. Le corps devrait contenir le même nombre d’objets qu’il y a de clés primaires dans l’URL :

[
   {
       "titre": "Titre ajusté pour ID 1"
   },
   {
       "titre": "Titre ajusté pour ID 2"
   }
]

Ceci ajuste les titres des messages. Et les valeurs de retour sont le nombre de lignes définies :

1,1

Ce qui signifie qu’il y avait deux opérations de mise à jour et que chacune d’entre elles avait défini une ligne. Les opérations en mode batch utilisent des transactions de base de données, de sorte qu’elles réussissent ou échouent (les transactions réussies sont renvoyées).