ldapsaisie/doc/api/api.docbook
Benjamin Renard 0ec390e1fe Add API feature
Some major changes have been made to handle this new feature :
- LSsession now have a flag about API mode. The displayTemplate() and
  displayAjaxReturn() methods have been adjust to correctly handle this
  mode.
- LSauth system have been adjust to handle a custom API mode :
  - LSauthMethod can support or not this mode : the $api_mode_supported
    permit to defined if supported (default, false). Currently, only
    HTTP (default in API mode) and annonymous mode support it.
  - An api_access parameter permit to configure witch type of user
    LSobject types could use the API. This flag must be set to True to
    allow a type of LSobject (default: False). In a same way, a
    web_access parameter now permit to disable Web access for some
    types of users (but this parameter is optional and its default value
    is True).
  - The HTTP method is the privileged first method for API mode. In this
    mode, if auth data aren't present in environment, it will request it
    by triggered a 403 HTTP error. Realm can be configured with new
    LSAUTHMETHOD_HTTP_API_REALM constant.
- The LStemplate system handle API mode to correctly react on errors: it
  return a JSON answer instead of HTML page. Error pages also now return
  adjusted HTTP code (404 or 500).
- The LSurl system have been adjust to handle API mode :
  - On declaring handlers, we could now specify if it's an API view with
    new $api_mode paremeter of add_handler() method
  - The LSurlRequest object have a new attribute to check if it's an API
    request
  - The error_404() method handle the API mode to return JSON answer.
    Furthermore, if no handlers matched with the requested URL, API mode
    is automatically enabled if the requested URL starts with 'api/'.
- LSform implement it own API mode flag and a new submited flag that
  be toggle via the new setSubmited() method. Some major changes also
  occured on LSformElement classes to specifically handle API
  input/output for each types of attributes:
  - a new getApiValue() method permit to retrieve the API value of the
    attribute (on show API view)
  - the getPostData() method now have to correctly handle API input for
    the attribute (on create/modify API views). A programmatic way have
    been adopted for each types of attributes.
- The LSimport and LScli create/modify commands also evolved to enable
  API mode of the LSform. This permit to take advantage of the new
  capability of LSform/LSformElement to handle input values with a
  programmatic way.
- New routes have been add to handle API views. All this new routes
  start with 'api/1.0/' and use the same URL schema as the web UI. The
  API currently permit to search/show/add/modify/remove LSobjects and
  manages their relations.
2021-02-03 14:40:28 +01:00

435 lines
20 KiB
XML

<?xml version="1.0" encoding="UTF-8" ?>
<chapter>
<title>API</title>
<para>Depuis la version 4.0, LdapSaisie offre une API visant à permettre de faire
les mêmes choses que ce qu'il est possible d'accomplir via l'interface web. L'idée
n'est bien entendue pas de se substituer systématiquement à la possibilité de se
connecter directement à l'annuaire, mais plutôt d'offrir une API web pour l'intégration
d'outil préférant ce mode d'interaction, ou encore, pour exposer des méthodes accès aux
données de l'annuaire tout en profitant des logiques métiers implémentées/configurées
dans LdapSaisie : validation syntaxique et d'unicité, règle de génération et
d'interdépendances des attributs, déclencheurs, ...</para>
<note><simpara>Cette API est actuellement dans une phase de test et n'offre pas encore
toutes les fonctionnalités proposées dans l'interface web. Elle est vouée à évoluer pour
intégrer petit à petit un maximum de fonctionnalités. Des contributions à ce sujet seront
plus qu'appréciée !</simpara></note>
<sect1>
<title>Authentification</title>
<para>L'authentification à l'API utilise le même composant <literal>LSauth</literal> que
lors d'une authentification à l'interface web, cependant, ce composant s'adapte pour
prendre en compte de mode de connexion. Par défaut, la méthode d'authentification utilisée
sera &LSauthMethod_HTTP; et permettra de se connecter en spécifiant le nom d'utilisateur
et le mot de l'utilisateur cherchant à se connecter via une authentification basique HTTP.
</para>
<warning><simpara>Il est à noter que tous les types d'utilisateur ne peuvent pas forcément
utiliser l'API : le paramètre <literal>api_access</literal> doit être explicitement
positionné à <literal>True</literal> dans <link linkend='config-srv-ldap'>la configuration
du serveur LDAP</link>.</simpara></warning>
<para>Une fois connecté, l'utilisateur endossera les droits associés à ses &LSprofiles;,
tout comme un utilisateur connecté à l'interface web.</para>
</sect1>
<sect1>
<title>Méthodes exposées</title>
<para>Les URLs des méthodes de l'API ont été construites par mimétisme sur celle de l'interface
web et sous la racine web <literal>api/</literal>. Par ailleurs, un numéro de version d'API a
été insérée dans chacune d'elles afin d'anticiper toutes évolutions futures majeures nécéssitants
de conserver une rétrocompatibilité avec les anciennes versions de l'API.</para>
<para>Toutes les méthodes retournent des informations au format JSON et accepte le paramètre
<literal>pretty</literal> permettant d'obtenir un retour plus facilement lisible. Les chaines de
caractères échangées doivent par ailleurs être encodées en UTF-8. On trouvera par ailleurs dans
le retour JSON :
<variablelist>
<varlistentry>
<term>success</term>
<listitem><simpara>Booléen précisant si l'action demandée a correctement été exécutée.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>messages</term>
<listitem><simpara>Ce tableau pourra être présent et lister les messages d'informations générées
par l'action demandée. Il s'agira des mêmes messages que ceux affichés dans l'interface web
lorsque les actions équivalentes y sont faites.</simpara></listitem>
</varlistentry>
<varlistentry>
<term>errors</term>
<listitem><simpara>Ce tableau pourra être présent et lister les messages d'erreurs générées
par l'action demandée.</simpara></listitem>
</varlistentry>
</variablelist>
</para>
<note><simpara>Les messages d'informations et d'erreurs générées par l'application sont traduites dans
la langue courante qui peut être spécifiée via le paramètre <literal>lang</literal> accepté par toutes
les méthodes (exemple : <literal>fr_FR</literal> ou <literal>en_US</literal>).</simpara></note>
<para>Lorsqu'une méthode cible un type d'objets, voir un objet en particulier, ces informations seront
transmises dans l'URL appelée. Si le type d'objet ou l'objet demandé est introuvable, une erreur HTTP
404 sera générée.</para>
<!-- Début Liste des méthodes exposées -->
<variablelist>
<title>Liste des méthodes exposées</title>
<varlistentry>
<term>/api/1.0/object/[object type]</term>
<listitem>
<para>Cette méthode permet de rechercher/lister les informations d'un type d'objets de
l'annuaire en particulier. Le type de l'objet est précisé dans l'URL et doit être encodé en
conséquence. Par mimétisme du comportement de l'interface web, la recherche est paginée et
accepte des paramètres similaires en plus de paramètre plus appropriés à un fonctionnement
programmatique :
<variablelist>
<title>Paramètres acceptés</title>
<varlistentry>
<term>filter</term>
<listitem><simpara>Permet de spécifier un filtre de recherche LDAP personnalisé. Celui-ci
sera combiné avec les paramètres propres au type d'objets recherchés et aux autres
paramètres spécifiés (<literal>pattern</literal> par exemple).</simpara>
<warning><simpara>Pour le moment, seuls les filtres simples du type <literal>attribut=valeur
</literal> sont acceptés ici.</simpara></warning>
</listitem>
</varlistentry>
<varlistentry>
<term>predefinedFilter</term>
<listitem><simpara>Permet de spécifier un des filtres de recherche LDAP prédéfinis dans la
configuration du type d'objet.</simpara></listitem>
</varlistentry>
<varlistentry>
<term>pattern</term>
<listitem><simpara>Permet de spécifier un mot clé de recherche, comme proposé dans
l'interface web.</simpara></listitem>
</varlistentry>
<varlistentry>
<term>approx</term>
<listitem><simpara>Booléen permettant d'activer/désactiver la recherche approximative
sur le mot clé. Les valeurs acceptées sont <literal>1</literal> ou <literal>0</literal>.
</simpara></listitem>
</varlistentry>
<varlistentry>
<term>basedn</term>
<listitem><simpara>Permet de spécifier une base de recherche personnalisé pour la recherche.
</simpara></listitem>
</varlistentry>
<varlistentry>
<term>subDn</term>
<listitem><simpara>Dans le cas d'un serveur LDAP configuré avec des <link linkend="config-subDn">
sous-niveaux de connexion</link>, permet de spécifier le sous-niveau pour la recherche.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>scope</term>
<listitem><simpara>Permet de spécifier l'étendue de la recherche dans l'annuaire. Valeurs acceptées:
<literal>sub</literal>, <literal>one</literal> et <literal>base</literal>.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>recursive</term>
<listitem><simpara>Booléen permettant d'activer/désactiver la recherche recursive, c'est à dire une
recherche à la racine de l'annuaire (ou du <link linkend="config-subDn">sous-niveau de connexion</link>)
avec une étendue de recherche maximale. Les valeurs acceptées sont <literal>1</literal> ou
<literal>0</literal>.</simpara></listitem>
</varlistentry>
<varlistentry>
<term>displayFormat</term>
<listitem><simpara>Permet de spécifier un &LSformat; personnalisé pour le nom des objets dans le résultat
de recherche.</simpara></listitem>
</varlistentry>
<varlistentry>
<term>extraDisplayedColumns</term>
<listitem><simpara>Booléen permettant d'activer le retour des colonnes personnalisées dans le résultat
de recherche. Les valeurs acceptées sont <literal>1</literal> ou <literal>0</literal>.</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term>attributes</term>
<listitem><simpara>Liste des attributs supplémentaires que devra retourner la recherche.</simpara>
<warning><simpara>Attention, ici ce sont les valeurs brutes des attributs qui seront retournées et
par forcément les valeurs telle que retournées habituellement.</simpara></warning>
</listitem>
</varlistentry>
<varlistentry>
<term>sortBy</term>
<listitem><simpara>Permet de préciser sur quelle information le résultat de recherche doit être
trié. Valeurs acceptées : <literal>displayName</literal>, <literal>subDn</literal> ou un des noms
des colonnes personnalisées.</simpara></listitem>
</varlistentry>
<varlistentry>
<term>sortDirection</term>
<listitem><simpara>Permet de préciser l'ordre de tri du résultat de recherche. Valeurs acceptées :
<literal>ASC</literal> (A-Z) ou <literal>DESC</literal> (Z-A).</simpara></listitem>
</varlistentry>
<varlistentry>
<term>page</term>
<listitem><simpara>Permet de préciser la page du résultat de recherche.</simpara></listitem>
</varlistentry>
<varlistentry>
<term>nbObjectsByPage</term>
<listitem><simpara>Permet de préciser le nombre maximum d'objets retournés par page du résultat de
recherche.</simpara></listitem>
</varlistentry>
<varlistentry>
<term>all</term>
<listitem><simpara>Permet de réclamer le résultat complet de la recherche (désactivation
de la pagination). Seul la présence de ce paramètre suffit à activer ce comportement, sa
valeur n'a pas d'importance.</simpara></listitem>
</varlistentry>
<varlistentry>
<term>withoutCache</term>
<listitem><simpara>Booléen permettant de désactiver l'utilisation du cache. Les valeurs acceptées
sont <literal>1</literal> ou <literal>0</literal>.</simpara></listitem>
</varlistentry>
</variablelist>
</para>
<programlisting linenumbering="unnumbered">
<citetitle>Exemple</citetitle>
<![CDATA[# curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople?extraDisplayedColumns=1&pretty'
{
"success": true,
"objects": {
"uid=hmartin,ou=people,o=ls": {
"name": "Henri MARTIN",
"Mail": "henri.martin@ls.com"
},
"uid=s.ldapsaisie,ou=people,o=ls": {
"name": "Secretariat LdapSaisie",
"Mail": "secretariat@ldapsaisie.biz"
},
"uid=ls,ou=people,o=ls": {
"name": "LdapSaisie",
"Mail": "ldap.saisie@ls.com"
},
"uid=erwpa,ou=people,o=ls": {
"name": "Erwan PAGE",
"Mail": "erwan.page@ldapsaisie.biz"
},
"uid=user2,ou=people,ou=company1,ou=companies,o=ls": {
"name": "prenom2 nom2",
"Mail": "user2@ls.com"
}
},
"total": 14,
"page": 1,
"nbPages": 3
}]]>
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>/api/1.0/object/[object type]/[dn]</term>
<listitem>
<para>Cette méthode permet de récupérer les informations d'un objet de l'annuaire au format
JSON. Le type de l'objet et son DN sont précisés dans l'URL et doivent être encodés en
conséquence.
<programlisting linenumbering="unnumbered">
<citetitle>Exemple</citetitle>
<![CDATA[# curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/uid=hmartin,ou=people,o=ls?pretty'
{
"dn": "uid=hmartin,ou=people,o=ls",
"type": "LSpeople",
"name": "Henri MARTIN",
"attributes": {
"uid": "hmartin",
"givenName": "Henri",
"sn": "MARTIN",
"cn": "Henri MARTIN",
"mail": "henri.martin@ls.com",
"personalTitle": "M.",
"description": [],
"jpegPhoto": null,
"lsGodfatherDn": {
"uid=eeggs,ou=people,o=ls": {
"name": "Easter Eggs",
"object_type": "LSpeople"
}
},
"uidNumber": "101022",
"gidNumber": "102001",
"loginShell": "no",
"homeDirectory": "\/home\/com",
"gecos": null,
"shadowExpire": null,
"shadowMax": null,
"shadowInactive": null,
"shadowLastChange": null,
"sambaSID": "S-1-5-21-2421470416-3566881284-3047381809-203044",
"sambaPrimaryGroupSID": "S-1-5-21-2421470416-3566881284-3047381809-205003",
"sambaAcctFlags": [
"U"
],
"sambaHomeDrive": null,
"sambaHomePath": null,
"sambaProfilePath": null,
"sambaLogonScript": null,
"sambaLogonTime": null,
"sambaLogoffTime": null,
"sambaKickoffTime": null,
"sambaPwdLastSet": null,
"sambaPwdMustChange": null,
"sambaPwdCanChange": null
},
"relations": {
"groups": {
"cn=direction,ou=groups,o=ls": "direction",
"cn=secretariat,ou=groups,o=ls": "secretariat"
},
"godfather": []
}
}]]>
</programlisting>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>/api/1.0/object/[object type]/create</term>
<listitem>
<para>Cette méthode permet de créer un objet dans l'annuaire. Le type de l'objet qui sera créé est
précisé dans l'URL et doit être encodé en conséquence. Les informations de l'objet doivent est
transmises au format <literal>x-www-form-urlencoded</literal>. Elles peuvent également être au
format <literal>multipart/form-data</literal>, en particulier si votre requête contient une image.
Par mimétisme avec l'interface web, seuls les attributs prévus dans le formulaire de création du
type d'objet peuvent être passées ici. De la même manière, les attributs non-spécifiés ici, pouront
être auto-générés en accord avec leur configuration et la requête sera acceptée uniquement si tous les
attributs obligatoires y sont spécifiés ou s'ils peuvent être auto-générés.</para>
<para>Le format et la syntaxe des valeurs des attributs dépends de leur type HTML. Ainsi, par exemple,
un attribut de type HTML <literal>boolean</literal> acceptera comme valeurs possibles <literal>yes
</literal> ou <literal>no</literal>. Pour plus de détails sur le type de valeur acceptée par un type
d'attribut HTML en particulier, consultez sa documentation. Vous pouvez également analyser le code de
la méthode <literal>getPostData()</literal> de la classe PHP correspondante.</para>
<para>Si l'application détecte un souci avec les informations transmises pour les attributs, un tableau
<literal>fields_errors</literal> sera présent dans la réponse JSON et contiendra pour chacun des attributs
problématique, un tableau des messages d'erreurs générées par l'application.</para>
<para>Si le type d'objet en prévoit, vous pouvez également utiliser un
<link linkend="config-LSobject-LSform-dataEntryForm">masque de saisie</link> via le paramètre <literal>
dataEntryForm</literal>.</para>
<programlisting linenumbering="unnumbered">
<citetitle>Exemple</citetitle>
<![CDATA[# curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/create?pretty' -d "uid=foo.bar&personalTitle=M.&givenName=foo&sn=bar&cn=Foo Bar&mail=foo.bar@example.com&userPassword=Y0urS3cr3t&lsGodfatherDn[]=uid=admin,ou=people,o=ls&gidNumber=70000"
{
"success": true,
"type": "LSpeople",
"dn": "uid=foo.bar,ou=people,o=ls",
"name": "Foo Bar",
"messages": [
"Le mail de notification a \u00e9t\u00e9 envoy\u00e9.",
"L'objet a \u00e9t\u00e9 ajout\u00e9."
]
}]]>
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>/api/1.0/object/[object type]/[dn]/modify</term>
<listitem>
<para>Cette méthode permet de modifier un objet dans l'annuaire. Le type de l'objet et son DN sont
précisés dans l'URL et doivent être encodés en conséquence. Les informations de l'objet à modifier
doivent être transmises au même format que pour la méthode <literal>create</literal> (voir ci-dessus).
Comme pour cette dernière, seuls les attributs prévus dans le formulaire de modification du type
d'objet peuvent être passées ici et la réponse JSON pourra contenir un tableau <literal>fields_errors
</literal> contenant les erreurs générées par l'application au sujet des valeurs transmises pour les
attributs.</para>
<programlisting linenumbering="unnumbered">
<citetitle>Exemple</citetitle>
<![CDATA[# curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/uid=foo.bar,ou=peopleo=ls/modify?pretty' -d "givenName=foo&sn=bar&cn=Foo Bar"
{
"dn": "uid=foo.bar,ou=people,o=ls",
"type": "LSpeople",
"name": "Foo Bar",
"success": true,
"messages": [
"L'objet a bien \u00e9t\u00e9 modifi\u00e9."
]
}]]>
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>/api/1.0/object/[object type]/[dn]/remove</term>
<listitem>
<para>Cette méthode permet de supprimer un objet dans l'annuaire. Le type de l'objet et son DN sont
précisés dans l'URL et doivent être encodés en conséquence.</para>
<programlisting linenumbering="unnumbered">
<citetitle>Exemple</citetitle>
<![CDATA[# curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/uid=foo.bar,ou=people,o=ls/remove?pretty'
{
"dn": "uid=foo.bar,ou=people,o=ls",
"type": "LSpeople",
"name": "Foo Bar",
"success": true,
"messages": [
"Foo Bar a bien \u00e9t\u00e9 supprim\u00e9."
]
}]]>
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>/api/1.0/object/[object type]/[dn]/relation/[relation]</term>
<listitem>
<para>Cette méthode permet de gérer les objets en relation avec un objet en particulier de
l'annuaire. Le type de l'objet, son DN et le nom de la relation sont précisés dans l'URL et
doivent être encodés en conséquence. Cette méthode accepte les paramètres <literal>add
</literal> et <literal>remove</literal> permettant de lister le ou les DN d'objet(s) à
respectivement ajouter ou supprimer parmis les objets actuellement en relation avec l'objet
spécifié. Si aucun DN n'est spécifié comme devant être ajouté ou supprimé, la méthode
retournera simplement les DN des objets en relation. En cas de modification demandée, la
méthode retournera la nouvelle liste des DNs des objets en relation, quel que soit le résultat
de l'opération de mise à jour.</para>
<programlisting linenumbering="unnumbered">
<citetitle>Exemple</citetitle>
<![CDATA[# curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/uid=foo.bar,ou=people,o=ls/relation/groups?pretty&add[]=cn=test34,ou=groups,o=ls&add[]=cn=testbr,ou=groups,o=ls'
{
"dn": "uid=foo.bar,ou=people,o=ls",
"type": "LSpeople",
"name": "Foo Bar",
"relation": "groups",
"success": true,
"relatedObjects": [
"cn=test34,ou=groups,o=ls",
"cn=testbr,ou=groups,o=ls"
],
"messages": [
"Objects in relation updated."
]
}]]>
</programlisting>
</listitem>
</varlistentry>
</variablelist>
</sect1>
</chapter>