From a2840db0c5ca7b512b805d6c1acfddc24646b0ec Mon Sep 17 00:00:00 2001
From: Quentin CHEVALIER <quentin.chevalier@polytechnique.edu>
Date: Thu, 1 Mar 2018 16:59:54 +0100
Subject: [PATCH] LDAP avec dictionnaires

---
 doc/db_knex_router.js.html              |    4 +-
 doc/global.html                         | 1409 ++++++++++++++++++++++-
 doc/index.html                          |  126 +-
 doc/knexfile.js.html                    |    4 +-
 doc/src_admin_view_admin_router.js.html |   10 +-
 doc/src_graphql_schema.js.html          |  105 ++
 doc/src_index.js.html                   |    4 +-
 doc/src_ldap_ldap_auth.js.html          |    8 +-
 doc/src_ldap_ldap_data.js.html          |  277 ++++-
 doc/src_server.js.html                  |   25 +-
 ldap_config.json                        |    4 +-
 src/ldap/ldap_data.js                   |  129 ++-
 12 files changed, 1938 insertions(+), 167 deletions(-)
 create mode 100644 doc/src_graphql_schema.js.html

diff --git a/doc/db_knex_router.js.html b/doc/db_knex_router.js.html
index 77b0a19..23c54c2 100644
--- a/doc/db_knex_router.js.html
+++ b/doc/db_knex_router.js.html
@@ -45,13 +45,13 @@ module.exports = require('knex')(config);</code></pre>
 </div>
 
 <nav>
-    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
+    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#idTOL">idTOL</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listAdmins">listAdmins</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listGroups2">listGroups2</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#modifierLDAP">modifierLDAP</a></li><li><a href="global.html#rechercheLDAP">rechercheLDAP</a></li><li><a href="global.html#rens">rens</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
 </nav>
 
 <br class="clear">
 
 <footer>
-    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Feb 28 2018 18:30:49 GMT+0100 (Paris, Madrid)
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Mar 01 2018 15:55:14 GMT+0100 (Paris, Madrid)
 </footer>
 
 <script> prettyPrint(); </script>
diff --git a/doc/global.html b/doc/global.html
index f5578b0..6064377 100644
--- a/doc/global.html
+++ b/doc/global.html
@@ -154,7 +154,7 @@
     
     <dt class="tag-source">Source:</dt>
     <dd class="tag-source"><ul class="dummy"><li>
-        <a href="src_admin_view_admin_router.js.html">src/admin_view/admin_router.js</a>, <a href="src_admin_view_admin_router.js.html#line95">line 95</a>
+        <a href="src_admin_view_admin_router.js.html">src/admin_view/admin_router.js</a>, <a href="src_admin_view_admin_router.js.html#line93">line 93</a>
     </li></ul></dd>
     
 
@@ -238,7 +238,7 @@
     
     <dt class="tag-source">Source:</dt>
     <dd class="tag-source"><ul class="dummy"><li>
-        <a href="src_admin_view_admin_router.js.html">src/admin_view/admin_router.js</a>, <a href="src_admin_view_admin_router.js.html#line105">line 105</a>
+        <a href="src_admin_view_admin_router.js.html">src/admin_view/admin_router.js</a>, <a href="src_admin_view_admin_router.js.html#line103">line 103</a>
     </li></ul></dd>
     
 
@@ -268,6 +268,441 @@
 
         
             
+
+    
+
+    
+    <h4 class="name" id="idTOL"><span class="type-signature"></span>idTOL<span class="signature">(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12)</span><span class="type-signature"> &rarr; {Array.&lt;string>}</span></h4>
+    
+
+    
+    <p class="summary"><p>Fonction qui interroge le LDAP et retrouve juste les uid des paxs validant les critères de recherche. Première étape vers vrai TOL (Trombino On Line).</p></p>
+    
+
+
+
+<div class="description">
+    <p>Accepte des champs exacts ou incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma <code>TOL(uid).then((res) =&gt; { truc avec res });</code>. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.</p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>c0</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Prénom</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c1</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Nom</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c2</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Surnom</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c3</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Nationalité</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c4</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Ecole ou université d'origine</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c5</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Promotion</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c6</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Groupe</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c7</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Cours</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c8</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Sport pratiqué</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c9</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Numéro de téléphone</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c10</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Adresse courriel</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c11</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Adresse physique</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>c12</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Adresse ip</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line157">line 157</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <p>uids des profils qui &quot;match&quot; les critères proposés.</p>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">Array.&lt;string></span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
 
     
 
@@ -276,13 +711,786 @@
     
 
     
-    <p class="summary"><p>Effectue une requête pour une table dans la BDD</p></p>
+    <p class="summary"><p>Effectue une requête pour une table dans la BDD</p></p>
+    
+
+
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>table_name</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>La table voulue par l'utilisateur.</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="src_admin_view_admin_router.js.html">src/admin_view/admin_router.js</a>, <a href="src_admin_view_admin_router.js.html#line62">line 62</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="listAdmins"><span class="type-signature"></span>listAdmins<span class="signature">(gid)</span><span class="type-signature"> &rarr; {string}</span></h4>
+    
+
+    
+    <p class="summary"><p>Fonction qui interroge le LDAP et retrouve la liste des admins d'un groupe.</p></p>
+    
+
+
+
+<div class="description">
+    <p>Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma <code>listAdmins(...).then((res) =&gt; { truc avec res });</code></p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>gid</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule)</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line121">line 121</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <p>Liste des uid des membres où l'id fournie est membre (noms flat des groupes)</p>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">string</span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="listGroups"><span class="type-signature"></span>listGroups<span class="signature">(uid)</span><span class="type-signature"> &rarr; {string}</span></h4>
+    
+
+    
+    <p class="summary"><p>Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre.</p></p>
+    
+
+
+
+<div class="description">
+    <p>Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma <code>listGroups(...).then((res) =&gt; { truc avec res })</code>;</p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>uid</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Identifiant de l'individu à interroger (le plus souvent prenom.nom, parfois l'année, supposé valide)</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line85">line 85</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <p>Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre</p>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">string</span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="listGroups2"><span class="type-signature"></span>listGroups2<span class="signature">(uid)</span><span class="type-signature"> &rarr; {string}</span></h4>
+    
+
+    
+    <p class="summary"><p>Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre. Assez différente de la précédente en terme d'implémentation, plus lente mais renvoir moins de résultats plus pertinents, probablement plus pérenne.</p></p>
+    
+
+
+
+<div class="description">
+    <p>Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma <code>listGroups2(...).then((res) =&gt; { truc avec res });</code></p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>uid</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Identifiant de l'individu à interroger (le plus souvent prenom.nom, parfois l'année, supposé valide)</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line97">line 97</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <p>Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre</p>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">string</span>
+
+
+    </dd>
+</dl>
+
+    
+
+
+
+
+
+        
+            
+
+    
+
+    
+    <h4 class="name" id="listMembers"><span class="type-signature"></span>listMembers<span class="signature">(gid)</span><span class="type-signature"> &rarr; {string}</span></h4>
+    
+
+    
+    <p class="summary"><p>Fonction qui interroge le LDAP et retrouve la liste des membres d'un groupe.</p></p>
+    
+
+
+
+<div class="description">
+    <p>Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma <code>listMembers(...).then((res) =&gt; { truc avec res });</code></p>
+</div>
+
+
+
+
+
+
+
+
+
+    <h5>Parameters:</h5>
+    
+
+<table class="params">
+    <thead>
+    <tr>
+        
+        <th>Name</th>
+        
+
+        <th>Type</th>
+
+        
+
+        
+
+        <th class="last">Description</th>
+    </tr>
+    </thead>
+
+    <tbody>
+    
+
+        <tr>
+            
+                <td class="name"><code>gid</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule)</p></td>
+        </tr>
+
+    
+    </tbody>
+</table>
+
+
+
+
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line109">line 109</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <p>Liste des uid des membres où l'id fournie est membre (noms flat des groupes)</p>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">string</span>
+
+
+    </dd>
+</dl>
+
     
 
 
 
 
 
+        
+            
+
+    
+
+    
+    <h4 class="name" id="modifierLDAP"><span class="type-signature"></span>modifierLDAP<span class="signature">(name, op, mod)</span><span class="type-signature"> &rarr; {boolean}</span></h4>
+    
+
+    
+    <p class="summary"><p>Fonction qui va plonger dans le LDAP et modifier un certain jeu de valeur en argument.</p></p>
+    
+
+
+
+<div class="description">
+    <p>Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir <a href="http://ldapjs.org/client.html"><code>Client API</code></a> méthode search). Il faut l'appeler suivant un schéma <code>modifierLDAP(...).then((res) =&gt; { truc avec res });</code>. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans <code>dic</code> et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).</p>
+</div>
+
+
+
 
 
 
@@ -314,7 +1522,7 @@
 
         <tr>
             
-                <td class="name"><code>table_name</code></td>
+                <td class="name"><code>name</code></td>
             
 
             <td class="type">
@@ -330,7 +1538,53 @@
 
             
 
-            <td class="description last"><p>La table voulue par l'utilisateur.</p></td>
+            <td class="description last"><p>DN de l'emplacement de la requête</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>op</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Deux types ; &quot;replace&quot; ou &quot;add&quot;, &quot;add&quot; pouvant rajouter un champ, &quot;replace&quot; sans modification étant une suppression</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>mod</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">Object</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Dictionnaire contenant les attributs à modifier et les modifications</p></td>
         </tr>
 
     
@@ -371,7 +1625,7 @@
     
     <dt class="tag-source">Source:</dt>
     <dd class="tag-source"><ul class="dummy"><li>
-        <a href="src_admin_view_admin_router.js.html">src/admin_view/admin_router.js</a>, <a href="src_admin_view_admin_router.js.html#line64">line 64</a>
+        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line260">line 260</a>
     </li></ul></dd>
     
 
@@ -394,6 +1648,28 @@
 
 
 
+<h5>Returns:</h5>
+
+        
+<div class="param-desc">
+    <p><code>true</code> si la modification s'est bien déroulée, false sinon</p>
+</div>
+
+
+
+<dl>
+    <dt>
+        Type
+    </dt>
+    <dd>
+        
+<span class="param-type">boolean</span>
+
+
+    </dd>
+</dl>
+
+    
 
 
 
@@ -405,17 +1681,17 @@
     
 
     
-    <h4 class="name" id="listGroups"><span class="type-signature"></span>listGroups<span class="signature">(uid)</span><span class="type-signature"> &rarr; {string}</span></h4>
+    <h4 class="name" id="rechercheLDAP"><span class="type-signature"></span>rechercheLDAP<span class="signature">(base, filter, filter_dic, attributes)</span><span class="type-signature"> &rarr; {Array.&lt;string>}</span></h4>
     
 
     
-    <p class="summary"><p>Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre.</p></p>
+    <p class="summary"><p>Fonction qui interroge le LDAP selon un protocole spécifié en argument et renvoit les valeurs trouvées.</p></p>
     
 
 
 
 <div class="description">
-    <p>Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma listGroups(uid).then((res) =&gt; { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).</p>
+    <p>Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir <a href="http://ldapjs.org/client.html"><code>Client API</code></a> méthode search). Il faut l'appeler suivant un schéma <code>rechercheLDAP(...).then((res) =&gt; { truc avec res });</code>. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans <code>dic</code> et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).</p>
 </div>
 
 
@@ -451,13 +1727,82 @@
 
         <tr>
             
-                <td class="name"><code>uid</code></td>
+                <td class="name"><code>base</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>DN de l'emplacement de la requête</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>filter</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">string</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Filtre logique de la recherche (format RFC2254)</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>filter_dic</code></td>
+            
+
+            <td class="type">
+            
+                
+<span class="param-type">Object</span>
+
+
+            
+            </td>
+
+            
+
+            
+
+            <td class="description last"><p>Dictionnaire qui associe les faux champs dans filter aux vraies valeurs pertinentes de la recherche</p></td>
+        </tr>
+
+    
+
+        <tr>
+            
+                <td class="name"><code>attributes</code></td>
             
 
             <td class="type">
             
                 
-<span class="param-type">int</span>
+<span class="param-type">Array.&lt;string></span>
 
 
             
@@ -467,7 +1812,7 @@
 
             
 
-            <td class="description last"><p>Identifiant de l'individu à interroger</p></td>
+            <td class="description last"><p>Liste des attributs qui figureront dans le résultat final</p></td>
         </tr>
 
     
@@ -508,7 +1853,7 @@
     
     <dt class="tag-source">Source:</dt>
     <dd class="tag-source"><ul class="dummy"><li>
-        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line30">line 30</a>
+        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line40">line 40</a>
     </li></ul></dd>
     
 
@@ -535,7 +1880,7 @@
 
         
 <div class="param-desc">
-    <p>Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre</p>
+    <p>Résultats de la recherche</p>
 </div>
 
 
@@ -546,7 +1891,7 @@
     </dt>
     <dd>
         
-<span class="param-type">string</span>
+<span class="param-type">Array.&lt;string></span>
 
 
     </dd>
@@ -564,17 +1909,17 @@
     
 
     
-    <h4 class="name" id="listMembers"><span class="type-signature"></span>listMembers<span class="signature">(gid)</span><span class="type-signature"> &rarr; {string}</span></h4>
+    <h4 class="name" id="rens"><span class="type-signature"></span>rens<span class="signature">(uid)</span><span class="type-signature"> &rarr; {Array.&lt;string>}</span></h4>
     
 
     
-    <p class="summary"><p>Fonction qui interroge le LDAP et retrouve la liste des membres d'un groupe.</p></p>
+    <p class="summary"><p>Fonction qui interroge le LDAP au sujet d'un uid particulier et qui renvoit toutes ses infos.</p></p>
     
 
 
 
 <div class="description">
-    <p>Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma listMembers(uid).then((res) =&gt; { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).</p>
+    <p>Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma <code>rens(...).then((res) =&gt; { truc avec res });</code></p>
 </div>
 
 
@@ -610,13 +1955,13 @@
 
         <tr>
             
-                <td class="name"><code>gid</code></td>
+                <td class="name"><code>uid</code></td>
             
 
             <td class="type">
             
                 
-<span class="param-type">int</span>
+<span class="param-type">string</span>
 
 
             
@@ -626,7 +1971,7 @@
 
             
 
-            <td class="description last"><p>Identifiant du groupe à interroger</p></td>
+            <td class="description last"><p>Identifiant de l'utilisateur</p></td>
         </tr>
 
     
@@ -667,7 +2012,7 @@
     
     <dt class="tag-source">Source:</dt>
     <dd class="tag-source"><ul class="dummy"><li>
-        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line51">line 51</a>
+        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line133">line 133</a>
     </li></ul></dd>
     
 
@@ -694,7 +2039,7 @@
 
         
 <div class="param-desc">
-    <p>Liste des uid des membres où l'id fournie est membre (noms flat des groupes)</p>
+    <p>Informations recueillies ; même quand dans TOL voir config.json.</p>
 </div>
 
 
@@ -705,7 +2050,7 @@
     </dt>
     <dd>
         
-<span class="param-type">string</span>
+<span class="param-type">Array.&lt;string></span>
 
 
     </dd>
@@ -727,13 +2072,13 @@
     
 
     
-    <p class="summary"><p>Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche.</p></p>
+    <p class="summary"><p>Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche. Bien mais vite inutilisable car demande trop au LDAP et renvoie des erreurs de type size limit. Préférer idTOL puis stalk au cas par cas.</p></p>
     
 
 
 
 <div class="description">
-    <p>Accepte des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma TOL(uid).then((res) =&gt; { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).</p>
+    <p>Accepte des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma <code>TOL(uid).then((res) =&gt; { truc avec res });</code>. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.</p>
 </div>
 
 
@@ -890,7 +2235,7 @@
             <td class="type">
             
                 
-<span class="param-type">int</span>
+<span class="param-type">string</span>
 
 
             
@@ -982,7 +2327,7 @@
             <td class="type">
             
                 
-<span class="param-type">int</span>
+<span class="param-type">string</span>
 
 
             
@@ -1102,7 +2447,7 @@
     
     <dt class="tag-source">Source:</dt>
     <dd class="tag-source"><ul class="dummy"><li>
-        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line84">line 84</a>
+        <a href="src_ldap_ldap_data.js.html">src/ldap/ldap_data.js</a>, <a href="src_ldap_ldap_data.js.html#line196">line 196</a>
     </li></ul></dd>
     
 
@@ -1129,7 +2474,7 @@
 
         
 <div class="param-desc">
-    <p>Informations recueillies ; plusieurs fois une liste sur le format ci-dessus pour tous les résultats correspondants plus une photo en byttestring et date de naissance.</p>
+    <p>Informations recueillies ; voir config.json.</p>
 </div>
 
 
@@ -1168,13 +2513,13 @@
 </div>
 
 <nav>
-    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
+    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#idTOL">idTOL</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listAdmins">listAdmins</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listGroups2">listGroups2</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#modifierLDAP">modifierLDAP</a></li><li><a href="global.html#rechercheLDAP">rechercheLDAP</a></li><li><a href="global.html#rens">rens</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
 </nav>
 
 <br class="clear">
 
 <footer>
-    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Feb 28 2018 18:30:49 GMT+0100 (Paris, Madrid)
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Mar 01 2018 15:55:14 GMT+0100 (Paris, Madrid)
 </footer>
 
 <script> prettyPrint(); </script>
diff --git a/doc/index.html b/doc/index.html
index 04bfcdb..f363b33 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -44,10 +44,10 @@
 
     <section>
         <article><p><a href="https://gitlab.binets.fr/br/sigma-backend/commits/master"><img src="https://gitlab.binets.fr/br/sigma-backend/badges/master/pipeline.svg" alt="pipeline status"></a></p>
-<h2>Introduction</h2><p>Ce dépôt contient le <em>backend</em> de Sigma, le successeur de Frankiz, un site étudiant permettant de gérer les groupes et les étudiants du plateau de Saclay.</p>
+<h1>Introduction</h1><p>Ce dépôt contient le <em>backend</em> de Sigma, le successeur de Frankiz, un site étudiant permettant de gérer les groupes et les étudiants du plateau de Saclay.</p>
 <p>Pour obtenir une copie de ce dépôt, clonez-le avec</p>
 <pre class="prettyprint source"><code>git clone git@gitlab.binets.fr:br/sigma-backend.git</code></pre><p>ou <code>git clone https://gitlab.binets.fr/br/sigma-backend.git</code>, puis installez les dépendences JavaScript avec <code>npm install</code>.</p>
-<p>A terme, ce projet doit tourné sur un serveur de l'école polytechnique et fournir à un serveur front - au code séparé et documenté séparément - toute les données nécessaires à son bon fonctionnement (authentification, appartenance à un groupe, droits de visibilité...).</p>
+<p>A terme, ce projet doit tourné sur un serveur de l'école polytechnique et fournir à un serveur front <em>au code séparé et documenté séparément</em> toute les données nécessaires à son bon fonctionnement (authentification, appartenance à un groupe, droits de visibilité...).</p>
 <p>Ce document détaille les différentes dépendances du projet, sa structure générale, détaille un peu plus des éléments sur la base de données et la documentation ; le code est également commenté en détail.</p>
 <h2>Dépendances</h2><p>Une dépendance, c'est un librairie JavaScript dont dépend le code source, soit pour le faire tourner soit pour faire tourner les outils dévs. Les dépendances développeur servent à tester par exemple. On trouve la liste des dépendances dans <a href="./package.json"><code>package.json</code></a>. Express est un exemple de dépendance normale, nodemon et ESLint (voir infra) sont des dépendances dev (<code>devDependencies</code>).</p>
 <p>Les dépendances s'installent avec <code>npm install</code>. Par défaut, toutes les dépendances sont installées. Si la variable <code>NODE_ENV</code> est configurée (vérifier avec la commande <code>echo &quot;$NODE_ENV&quot;</code>),</p>
@@ -74,8 +74,8 @@ npm install -g eslint</code></pre><p>Les dépendances les plus importantes sont
 <li>bundle.js est un monstrueux fichier généré automatiquement qui gère nos dépendances.</li>
 </ul>
 </li>
-<li><a href="../db"><code>db</code></a> : base de donnée sigma ;<ul>
-<li>knex_router.js charge la configuration précisée dans knexfile.js,</li>
+<li><a href="../db"><code>db</code></a> : base de donnée sigma ;</li>
+<li>knex_router.js charge la configuration précisée dans knexfile.js,<ul>
 <li><a href="../db/migrations"><code>migrations</code></a> stocke l'ensemble des migrations knex ; c'est un équivalent d'un répertoire git pour la BDD sigma (du coup seulement les groupes pas les individus),</li>
 <li><a href="../db/seeds"><code>seeds</code></a> : stocke les éléments de générations des BDD ; c'est un ensemble de scripts.</li>
 </ul>
@@ -101,7 +101,7 @@ npm install -g eslint</code></pre><p>Les dépendances les plus importantes sont
 </ul>
 </li>
 <li>La BDD de sigma propre est en <a href="https://www.postgresql.fr/">PostgreSQL</a>, hébergée en propre BR, qui contient les groupes et leurs niveaux de visibilité mais peu d'information sur les utilisateurs (seulement son école).<ul>
-<li>Cette BDD est géré par <a href="http://knexjs.org">Knex</a>.</li>
+<li>Les requêtes à cette base de données sont gérées par <a href="http://knexjs.org">Knex.js</a>.</li>
 </ul>
 </li>
 </ul>
@@ -120,14 +120,18 @@ npm install -g eslint</code></pre><p>Les dépendances les plus importantes sont
 </li>
 </ul>
 <p>Les deux sections suivantes détaillent les opérations possibles grâce au back directement sur les bases de données via sigma.</p>
-<h3>Fonctions knexjs</h3><p>Quelques exemples de fonctions utiles de <code>knexjs</code> <a href="http://knexjs.org">Knex</a></p>
+<h3>Guide: Knex.js</h3><p>L'interface en ligne de commande de <a href="http://knexjs.org">Knex.js</a> contient les commandes suivantes :</p>
 <ul>
-<li><code>knex migrate:make migration_name</code> crée une migration dans <code>migrations/</code> : le nom du fichier est <code>migration_name.js</code> avec la date et l'heure en préfixe</li>
+<li><code>knex migrate:make migration_name</code> crée une migration dans <code>db/migrations/</code></li>
 <li><code>knex migrate:latest</code> met à jour le schéma de la BDD</li>
 <li><code>knex seed:make filename</code> crée un <em>seed</em> <code>seeds/filename</code></li>
 <li><code>knex seed:run</code> insère les <em>seeds</em> dans la BDD</li>
 </ul>
 <p>Un fichier <em>seed</em> permet d'insérer des données dans la BDD. Ils sont stockés dans <a href="../db/seeds"><code>seeds</code></a>.</p>
+<h4>Comment faire une migration</h4><p>On utilisera l'interface en ligne de commande de Knex.js.</p>
+<p>Les migrations servent à <strong>mettre à jour le schéma de la base de données</strong>. Pour créer une migration, on lance la commande <code>knex migrate:make &lt;nom_migration&gt;</code>, qui crée un fichier <code>db/migrations/[hash]_nom_migration.js</code> où le hash est la date et l'heure.</p>
+<p>Maintenant, on édite le fichier de migration. Il fait deux exports, <code>exports.up</code> et <code>exports.down</code>, qui définissent respectivement comment mettre à jour le schéma de la BDD et comment annuler la modification si <code>knex migrate:rollback</code> est invoqué.</p>
+<p>Il faut se référer à la documentation de Knex.js pour comprendre comment écrire les requêtes. Voici un <a href="https://devhints.io/knex">cheatsheet</a>.</p>
 <h3>Fonctions LDAP</h3><p>On peut facilement explorer et modifier des éléments du LDAP de l'école depuis le réseau de l'X avec <a href="http://jxplorer.org/">JXplorer</a> en entrant <code>frankiz</code> dans nouvelle connexion et en allant dans <code>net</code>.</p>
 <h2>Scripts</h2><p>Les scripts sont des instructions en ligne de commande que l'on peut faire tourner avec la commande <code>npm run</code>. Ce sont des raccourcis pour gagner du temps sur des opérations un peu longues. Ils sont définis dans <a href="../package.json"><code>package.json</code></a>.</p>
 <p>Les plus importants sont détaillées ci-dessous (ne pas oublier <code>npm install</code> déjà mentionné plus tôt) :</p>
@@ -142,7 +146,7 @@ npm install -g eslint</code></pre><p>Les dépendances les plus importantes sont
 <li><code>npm test</code> le démarre avec <a href="https://nodemon.io/">nodemon</a>, outil dév qui redémarre automatiquement le serveur dans <code>bundle.js</code> dès que celui-ci est modifié.</li>
 </ul>
 <p>Donc, lancer <code>npm run watch</code> dans un terminal et <code>npm test</code> dans un autre permet de recompiler le serveur <strong>et</strong> le redémarrer automatiquement dès qu'il y a une modification.</p>
-<p>Le script pour faire tourner <a href="http://usejsdoc.org/index.html">JSDoc</a> et régénérrer la documentation est : <code>npm run doc</code> </p>
+<p>Le script pour faire tourner <a href="http://usejsdoc.org/index.html">JSDoc</a> et régénérrer la documentation est : <code>npm run doc</code></p>
 <h2>Documentation</h2><p>La documentation détaillée du projet est <a href="./doc/index.html">ici</a>. Elle a été compilée avec <a href="http://usejsdoc.org/index.html">JSDoc</a> sous format hmtl selon le fichier de configuration <a href="../configfile_doc.json"><code>configfile_doc.json</code></a> à la racine du projet.</p>
 <p>Les fichiers compilés se situent dans <a href="."><code>doc</code></a> avec leurs fichiers image. Par nature de l'outil JSDoc il est facile de documenter en détail des fonctions .js mais plus compliqué de documenter un fichier.</p>
 <p>A la fin de ce fichier JSDoc rajjoute les commentaires placés dans chacun des fichiers et des hyperliens pour y accéder.</p>
@@ -435,6 +439,106 @@ npm install -g eslint</code></pre><p>Les dépendances les plus importantes sont
     
 
     
+</article>
+
+</section>
+
+
+
+
+
+
+
+<section>
+
+<header>
+    
+        <h2>src/graphql/schema.js</h2>
+        
+    
+</header>
+
+<article>
+    <div class="container-overview">
+    
+        
+            <div class="description"><p>Ce fichier genere le shema utilise par Apollo. C'est ici que les requetes GraphQl sont résolues.</p></div>
+        
+
+        
+
+
+<dl class="details">
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-author">Author:</dt>
+    <dd class="tag-author">
+        <ul>
+            <li>akka vodol</li>
+        </ul>
+    </dd>
+    
+
+    
+
+    
+
+    
+
+    
+    <dt class="tag-source">Source:</dt>
+    <dd class="tag-source"><ul class="dummy"><li>
+        <a href="src_graphql_schema.js.html">src/graphql/schema.js</a>, <a href="src_graphql_schema.js.html#line1">line 1</a>
+    </li></ul></dd>
+    
+
+    
+
+    
+
+    
+</dl>
+
+
+        
+    
+    </div>
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
 </article>
 
 </section>
@@ -651,7 +755,7 @@ npm install -g eslint</code></pre><p>Les dépendances les plus importantes sont
     <div class="container-overview">
     
         
-            <div class="description"><p>Ce fichier gère les requêtes LDAP de type données ; liste des groupe d'un individu=&quot;&quot;, liste des membres d'un groupe... A ne pas confondre avec ldap_auth qui lui gère l'authentification.</p></div>
+            <div class="description"><p>Ce fichier gère les requêtes LDAP de type données ; liste des groupe d'un individu, liste des membres d'un groupe... A ne pas confondre avec ldap_auth qui lui gère l'authentification. Il est à lire conjointement avec config.json qui détaille les pats et champs spécifique à un LDAP.</p></div>
         
 
         
@@ -831,13 +935,13 @@ npm install -g eslint</code></pre><p>Les dépendances les plus importantes sont
 </div>
 
 <nav>
-    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
+    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#idTOL">idTOL</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listAdmins">listAdmins</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listGroups2">listGroups2</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#modifierLDAP">modifierLDAP</a></li><li><a href="global.html#rechercheLDAP">rechercheLDAP</a></li><li><a href="global.html#rens">rens</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
 </nav>
 
 <br class="clear">
 
 <footer>
-    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Feb 28 2018 18:30:49 GMT+0100 (Paris, Madrid)
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Mar 01 2018 15:55:14 GMT+0100 (Paris, Madrid)
 </footer>
 
 <script> prettyPrint(); </script>
diff --git a/doc/knexfile.js.html b/doc/knexfile.js.html
index cf39b23..2d9141b 100644
--- a/doc/knexfile.js.html
+++ b/doc/knexfile.js.html
@@ -66,13 +66,13 @@ module.exports = {
 </div>
 
 <nav>
-    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
+    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#idTOL">idTOL</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listAdmins">listAdmins</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listGroups2">listGroups2</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#modifierLDAP">modifierLDAP</a></li><li><a href="global.html#rechercheLDAP">rechercheLDAP</a></li><li><a href="global.html#rens">rens</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
 </nav>
 
 <br class="clear">
 
 <footer>
-    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Feb 28 2018 18:30:49 GMT+0100 (Paris, Madrid)
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Mar 01 2018 15:55:14 GMT+0100 (Paris, Madrid)
 </footer>
 
 <script> prettyPrint(); </script>
diff --git a/doc/src_admin_view_admin_router.js.html b/doc/src_admin_view_admin_router.js.html
index eca8b45..a5a2691 100644
--- a/doc/src_admin_view_admin_router.js.html
+++ b/doc/src_admin_view_admin_router.js.html
@@ -46,7 +46,7 @@ router.get('/', function (req, res) {
 });
 
 router.get('/admin',
-    ensureLoggedIn('/'),
+    // ensureLoggedIn('/'),
     function (req, res) {
         console.log('Connecting to ' + req.url);
         res.render('home', { title: 'Home', port: port });
@@ -57,7 +57,6 @@ router.post('/login',
         successRedirect: '/admin',
         failureRedirect: '/',
         failureFlash: true
-    }),
     // on a besoin de faire un callback apres le passport.authenticate car
     // on souhaite garde l'information user.dn et body.password qq part.
     // TODO: essayer de garder ces informations plus proprement...
@@ -74,8 +73,7 @@ router.post('/login',
         }
     }
     */
-
-);
+    }));
 
 router.post('/logout', function (req, res) {
     req.logout();
@@ -156,13 +154,13 @@ export default router;
 </div>
 
 <nav>
-    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
+    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#idTOL">idTOL</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listAdmins">listAdmins</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listGroups2">listGroups2</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#modifierLDAP">modifierLDAP</a></li><li><a href="global.html#rechercheLDAP">rechercheLDAP</a></li><li><a href="global.html#rens">rens</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
 </nav>
 
 <br class="clear">
 
 <footer>
-    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Feb 28 2018 18:30:49 GMT+0100 (Paris, Madrid)
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Mar 01 2018 15:55:14 GMT+0100 (Paris, Madrid)
 </footer>
 
 <script> prettyPrint(); </script>
diff --git a/doc/src_graphql_schema.js.html b/doc/src_graphql_schema.js.html
new file mode 100644
index 0000000..074f99d
--- /dev/null
+++ b/doc/src_graphql_schema.js.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>JSDoc: Source: src/graphql/schema.js</title>
+
+    <script src="scripts/prettify/prettify.js"> </script>
+    <script src="scripts/prettify/lang-css.js"> </script>
+    <!--[if lt IE 9]>
+      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+    <![endif]-->
+    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
+    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
+</head>
+
+<body>
+
+<div id="main">
+
+    <h1 class="page-title">Source: src/graphql/schema.js</h1>
+
+    
+
+
+
+    
+    <section>
+        <article>
+            <pre class="prettyprint source linenums"><code>/**
+ * @file Ce fichier genere le shema utilise par Apollo. C'est ici que les requetes GraphQl sont résolues.
+ * @author akka vodol
+*/
+
+import knex from '../../db/knex_router';
+import { listGroups, listMembers } from '../ldap/ldap_data';
+import { makeExecutableSchema } from 'graphql-tools';
+import { request } from 'https';
+
+const typeDefs = `
+    type Query {
+        allGroups: [Group]
+        group(id: ID) : [Group]
+    }
+
+    type Group {
+        name: String!
+        id: ID!
+        website: String
+        updatedAt: String!
+        description: String
+        school: String!
+    }
+`;
+
+const getAllVisibleGroups = (user) => {
+    console.log("getAllVisibleGroups gets called");
+    // let group_ids = listGroups(user.id);
+    return knex.select().from('groups')/*.whereIn('id', group_ids)*/;
+};
+    
+const getGroupIfVisible = (user, id) => {
+    console.log("getGroupIfVisible gets called");
+    return getAllVisibleGroups(user).where('id', id)/*.then(function(table) {
+        console.log(JSON.stringify(table,null,2))*/;
+};
+
+const resolvers = {
+    Query: {
+        allGroups: (obj, args, context) => {
+            return getAllVisibleGroups(context.user);
+        },
+        group: (obj, args, context) => {
+            return getGroupIfVisible(context.user, args.id);
+        }
+    }
+};
+
+const schema = makeExecutableSchema({
+    typeDefs,
+    resolvers
+});
+
+export default schema;</code></pre>
+        </article>
+    </section>
+
+
+
+
+</div>
+
+<nav>
+    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#idTOL">idTOL</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listAdmins">listAdmins</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listGroups2">listGroups2</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#modifierLDAP">modifierLDAP</a></li><li><a href="global.html#rechercheLDAP">rechercheLDAP</a></li><li><a href="global.html#rens">rens</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
+</nav>
+
+<br class="clear">
+
+<footer>
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Mar 01 2018 15:55:14 GMT+0100 (Paris, Madrid)
+</footer>
+
+<script> prettyPrint(); </script>
+<script src="scripts/linenumber.js"> </script>
+</body>
+</html>
diff --git a/doc/src_index.js.html b/doc/src_index.js.html
index 5678fe8..5ba9274 100644
--- a/doc/src_index.js.html
+++ b/doc/src_index.js.html
@@ -55,13 +55,13 @@ server.listen(port, () => {
 </div>
 
 <nav>
-    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
+    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#idTOL">idTOL</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listAdmins">listAdmins</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listGroups2">listGroups2</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#modifierLDAP">modifierLDAP</a></li><li><a href="global.html#rechercheLDAP">rechercheLDAP</a></li><li><a href="global.html#rens">rens</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
 </nav>
 
 <br class="clear">
 
 <footer>
-    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Feb 28 2018 18:30:49 GMT+0100 (Paris, Madrid)
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Mar 01 2018 15:55:14 GMT+0100 (Paris, Madrid)
 </footer>
 
 <script> prettyPrint(); </script>
diff --git a/doc/src_ldap_ldap_auth.js.html b/doc/src_ldap_ldap_auth.js.html
index 4feb258..192b0c5 100644
--- a/doc/src_ldap_ldap_auth.js.html
+++ b/doc/src_ldap_ldap_auth.js.html
@@ -34,8 +34,10 @@ import passport from 'passport';
 import LdapStrategy from 'passport-ldapauth';
 import session from 'express-session';
 import fs from 'fs';
+import path from 'path';
 
-let config = JSON.parse(fs.readFileSync('config.json', 'utf8'));
+let configPath = path.resolve('./','ldap_config.json');
+let config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
 
 passport.use(new LdapStrategy({
     server: {
@@ -82,13 +84,13 @@ export default setupLdapAuth;
 </div>
 
 <nav>
-    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
+    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#idTOL">idTOL</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listAdmins">listAdmins</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listGroups2">listGroups2</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#modifierLDAP">modifierLDAP</a></li><li><a href="global.html#rechercheLDAP">rechercheLDAP</a></li><li><a href="global.html#rens">rens</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
 </nav>
 
 <br class="clear">
 
 <footer>
-    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Feb 28 2018 18:30:49 GMT+0100 (Paris, Madrid)
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Mar 01 2018 15:55:14 GMT+0100 (Paris, Madrid)
 </footer>
 
 <script> prettyPrint(); </script>
diff --git a/doc/src_ldap_ldap_data.js.html b/doc/src_ldap_ldap_data.js.html
index 943d24f..c164c01 100644
--- a/doc/src_ldap_ldap_data.js.html
+++ b/doc/src_ldap_ldap_data.js.html
@@ -27,114 +27,245 @@
     <section>
         <article>
             <pre class="prettyprint source linenums"><code>/**
- * @file Ce fichier gère les requêtes LDAP de type données ; liste des groupe d'un individu="", liste des membres d'un groupe... A ne pas confondre avec ldap_auth qui lui gère l'authentification.
+ * @file Ce fichier gère les requêtes LDAP de type données ; liste des groupe d'un individu, liste des membres d'un groupe... A ne pas confondre avec ldap_auth qui lui gère l'authentification. Il est à lire conjointement avec config.json qui détaille les pats et champs spécifique à un LDAP.
  * @author hawkspar
-*/
+ */
 
 /* Ne pas hésiter à repasser en synthaxe ES5... Plus simple pour tester en solo avec node directement
 import ldap  from 'ldapjs';
 import fs from 'fs';
-import ldapEscape from 'ldap-escape'; */
+import ldapEscape from 'ldap-escape';
+import path from 'path';*/
 
-var ldap = require('ldapjs');
+/**/var ldap = require('ldapjs');
 var fs = require('fs');
 var ldapEscape = require('ldap-escape');
+var path = require('path');
 
 // Important ; permet de vérifier que l'utilisateur reste connecté.
 var ensureLoggedin =  require('connect-ensure-login').ensureLoggedIn;
 
 // Point central ; tous les champs de la BDD sont 'cachés' dans config.json et pas visibles directement
-let config = JSON.parse(fs.readFileSync('../../config.json', 'utf8'));
+var configPath = path.resolve('./','ldap_config.json');
+var config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
 
 // Connection au serveur LDAP avec des temps de timeout arbitraires
-var client = ldap.createClient({ url: config.ldap.server, timeout: 10000, idleTimeout: 10000});
+var client = ldap.createClient({ url: config.ldap.server});
+
+//------------------------------------------------------------------------------------------------------------------------
+// Fonctions de recherche
+//------------------------------------------------------------------------------------------------------------------------
 
 /**
- * @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre.
- * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma listGroups(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
- * @arg {int} uid - Identifiant de l'individu à interroger
- * @return {string} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
+ * @summary Fonction qui interroge le LDAP selon un protocole spécifié en argument et renvoit les valeurs trouvées.
+ * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). Il faut l'appeler suivant un schéma `rechercheLDAP(...).then((res) => { truc avec res });`. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @arg {string} base - DN de l'emplacement de la requête
+ * @arg {string} filter - Filtre logique de la recherche (format RFC2254)
+ * @arg {Object} filter_dic - Dictionnaire qui associe les faux champs dans filter aux vraies valeurs pertinentes de la recherche
+ * @arg {string[]} attributes - Liste des attributs qui figureront dans le résultat final
+ * @return {string[]} Résultats de la recherche
  */
-function listGroups(uid) {
+function rechercheLDAP(base, filter, filter_dic, attributes) {
+    // Debug
+    //console.log(base);
+    //console.log(filter);
+    //console.log(filter_dic);
+    //console.log(attributes);
     return new Promise(function(resolve, reject) {
-        var groupsList=[];
-        
-        client.search(config.ldap_data_gl.searchBase, {scope: "sub", attributes: "uid", filter: ldapEscape.filter(config.ldap_data_gl.searchFilter, {id: uid})}, function(err, res) {
+        // A terme mettre id du type qui se connecte (permet de pas avoir trop de demandes trop rapides)
+        //client.bind(config.connexion.dn, config.connexion.passwd, (err, res) => {});
+
+        let vals=[];
+        // Interrogation LDAP selon configuration fournie en argument
+        client.search(base, {
+            "scope": "sub",
+            "filter": ldapEscape.filter(filter, filter_dic),
+            "attributes": attributes
+        }, function(err, res) {
+            // Gestion erreur
             if (err) {
                 reject(err);
             } else {
-                res.on('searchEntry', function(entry) { groupsList.push(entry.object.uid); });
-                res.on('end', function(res) { resolve(groupsList); });
+                // Dès que la recherche renvoit une entrée, on stocke les attributs qui nous intéresse
+                res.on('searchEntry', function(entry) {
+                    attributes.forEach((element) => {
+                        eval("vals.push(entry.object."+element+")");
+                    });
+                });
+                // Si la recherche est finie on se déconnecte et on renvoit la liste
+                res.on('end', function(res) {
+                    client.bind("", "", (err, res) => {});
+                    // Debug
+                    //console.log(vals);
+                    resolve(vals);
+                });
             }
         });
     });
 }
- 
+
+/**
+ * @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre.
+ * @desc Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma `listGroups(...).then((res) => { truc avec res })`;
+ * @arg {string} uid - Identifiant de l'individu à interroger (le plus souvent prenom.nom, parfois l'année, supposé valide)
+ * @return {string} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
+ */
+function listGroups(uid) {
+    return new Promise(function(resolve, reject) {
+        resolve(rechercheLDAP(config.dn_users, config.filter_id, { id : uid }, config.attributes_lg).then(res => res[0]));
+    });
+}
+
+/**
+ * @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre. Assez différente de la précédente en terme d'implémentation, plus lente mais renvoir moins de résultats plus pertinents, probablement plus pérenne.
+ * @desc Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma `listGroups2(...).then((res) => { truc avec res });`
+ * @arg {string} uid - Identifiant de l'individu à interroger (le plus souvent prenom.nom, parfois l'année, supposé valide)
+ * @return {string} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
+ */
+function listGroups2(uid) {
+    return new Promise(function(resolve, reject) {
+        resolve(rechercheLDAP(config.dn_groups, config.filter_lg, { id : uid }, config.attributes_id));
+    });
+}
+
 /**
  * @summary Fonction qui interroge le LDAP et retrouve la liste des membres d'un groupe.
- * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma listMembers(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
- * @arg {int} gid - Identifiant du groupe à interroger
+ * @desc Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma `listMembers(...).then((res) => { truc avec res });`
+ * @arg {string} gid - Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule)
  * @return {string} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
  */
 function listMembers(gid) {
     return new Promise(function(resolve, reject) {
-        var membersList=[];
-        
-        client.search(config.ldap_data_ml.searchBase="", {scope: "sub", attributes: "uid", filter: ldapEscape.filter(config.ldap_data_ml.searchFilter, {id: gid})}, function(err, res) {
-            if (err) {
-                reject(err);
-            } else {
-                res.on('searchEntry', function(entry) { membersList.push(entry.object.uid); });
-                res.on('end', function(res) { resolve(membersList); });
+        resolve(rechercheLDAP(config.dn_groups, config.filter_id, { id: gid }, config.attributes_lm).then(res => res[0]));
+    });
+}
+
+/**
+ * @summary Fonction qui interroge le LDAP et retrouve la liste des admins d'un groupe.
+ * @desc Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma `listAdmins(...).then((res) => { truc avec res });`
+ * @arg {string} gid - Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule)
+ * @return {string} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
+ */
+function listAdmins(gid) {
+    return new Promise(function(resolve, reject) {
+        resolve(rechercheLDAP(config.key_al+"="+gid+","+config.dn_groups, config.filter_id, { id: gid }, config.attributes_al).then(res => res[0]));
+    });
+}
+ 
+/**
+ * @summary Fonction qui interroge le LDAP au sujet d'un uid particulier et qui renvoit toutes ses infos.
+ * @desc Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma `rens(...).then((res) => { truc avec res });`
+ * @arg {string} uid - Identifiant de l'utilisateur
+ * @return {string[]} Informations recueillies ; même quand dans TOL voir config.json.
+ */
+function rens(uid) {
+    return new Promise(function(resolve, reject) {
+        resolve(rechercheLDAP(config.dn_users, config.filter_id, { id: uid }, config.attributes_all));
+    });
+}
+
+/**
+ * @summary Fonction qui interroge le LDAP et retrouve juste les uid des paxs validant les critères de recherche. Première étape vers vrai TOL (Trombino On Line).
+ * @desc Accepte des champs exacts ou incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma `TOL(uid).then((res) => { truc avec res });`. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.
+ * @arg {string} c0 - Prénom
+ * @arg {string} c1 - Nom
+ * @arg {string} c2 - Surnom
+ * @arg {string} c3 - Nationalité
+ * @arg {string} c4 - Ecole ou université d'origine
+ * @arg {string} c5 - Promotion
+ * @arg {string} c6 - Groupe
+ * @arg {string} c7 - Cours
+ * @arg {string} c8 - Sport pratiqué
+ * @arg {string} c9 - Numéro de téléphone
+ * @arg {string} c10 - Adresse courriel
+ * @arg {string} c11 - Adresse physique
+ * @arg {string} c12 - Adresse ip
+ * @return {string[]} uids des profils qui "match" les critères proposés.
+ */
+function idTOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="", c10="", c11="", c12="") {
+    return new Promise(function(resolve, reject) {
+        let filter="";
+        let filter_dic={};
+        // Iteration pour chaque champ, alourdissement du filtre selon des trucs prédéfini dans config.json encore
+        config.search_attributes_tol.forEach((element, index, list) => {
+            if (eval("c"+index) != '') {                                 // Si il y a qque chose à chercher pour ce filtre
+                filter="(&amp;"+filter+"(|("+element+"=${app_"+element+index+"})"+      // On cherche la valeur exacte
+                                   "(|("+element+"=*${app_"+element+index+"})"+     // La valeur finale avec des trucs avant ; wildcard *
+                                   "(|("+element+"=*${app_"+element+index+"}*)"+    // La valeur du milieu avec des trucs avant et après
+                                     "("+element+"=${app_"+element+index+"}*)))))"; // La valeur du début avec des trucs après
+                // Mise en relation de chaque valeur à la demande utilisateur dans un dico
+                filter_dic["app_"+element+index]=eval("c"+index);
             }
         });
+
+        // Appel rechercheLDAP avec filtre de l'espace 
+        resolve(rechercheLDAP(config.dn_users, filter, filter_dic, config.attributes_id));
     });
 }
- 
+
 /**
- * @summary Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche.
- * @desc Accepte des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma TOL(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @summary Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche. Bien mais vite inutilisable car demande trop au LDAP et renvoie des erreurs de type size limit. Préférer idTOL puis stalk au cas par cas.
+ * @desc Accepte des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma `TOL(uid).then((res) => { truc avec res });`. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.
  * @arg {string} c0 - Prénom
  * @arg {string} c1 - Nom
  * @arg {string} c2 - Surnom
  * @arg {string} c3 - Nationalité
  * @arg {string} c4 - Ecole ou université d'origine
- * @arg {int} c5 - Promotion
+ * @arg {string} c5 - Promotion
  * @arg {string} c6 - Groupe
  * @arg {string} c7 - Cours
  * @arg {string} c8 - Sport pratiqué
- * @arg {int} c9 - Numéro de téléphone
+ * @arg {string} c9 - Numéro de téléphone
  * @arg {string} c10 - Adresse courriel
  * @arg {string} c11 - Adresse physique
  * @arg {string} c12 - Adresse ip
- * @return {string[]} Informations recueillies ; plusieurs fois une liste sur le format ci-dessus pour tous les résultats correspondants plus une photo en byttestring et date de naissance.
+ * @return {string[]} Informations recueillies ; voir config.json.
  */
 function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="", c10="", c11="", c12="") {
     return new Promise(function(resolve, reject) {
-        var candidatesList=[];
+        // Pas nécessaire mais bien
+        client.bind(config.connexion.dn, config.connexion.passwd, (err, res) => {});
 
-        var filter="";
-        var dic={};
-
-        config.ldap_data_tol.searchFilterAttributes.forEach((element, index, list) => {
-            if (eval("c"+index.toString()) != '') {
-                filter="(&amp;"+filter+"(|("+element+"=*${app_"+element+index+"})"+
-                                "(|("+element+"=${app_"+element+index+"})"+
-                                "(|("+element+"=*${app_"+element+index+"}*)"+
-                                    "("+element+"=${app_"+element+index+"}*)))))";
+        let filter="";
+        let dic={};
+        // Iteration pour chaque champ, alourdissement du filtre selon des trucs prédéfini dans config.json encore
+        config.search_attributes_tol.forEach((element, index, list) => {
+            if (eval("c"+index.toString()) != '') {                                 // Si il y a qque chose à chercher pour ce filtre
+                filter="(&amp;"+filter+"(|("+element+"=${app_"+element+index+"})"+      // On cherche la valeur exacte
+                                   "(|("+element+"=*${app_"+element+index+"})"+     // La valeur finale avec des trucs avant ; wildcard *
+                                   "(|("+element+"=*${app_"+element+index+"}*)"+    // La valeur du milieu avec des trucs avant et après
+                                     "("+element+"=${app_"+element+index+"}*)))))"; // La valeur du début avec des trucs après
+                // Mise en relation de chaque valeur à la demande utilisateur dans un dico
                 dic["app_"+element+index]=eval("c"+index.toString());
             }
         });
+        // Debug
+        //console.log(filter);
+        console.log(dic);
+
+        var candidatesList=[];
 
-        client.search(config.ldap_data_tol.searchBase, {scope: "sub", attributes: config.ldap_data_tol.searchAttributes, filter: ldapEscape.filter(filter, dic)}, function(err, res) {
+        // Interrogation LDAP et filtre de malade
+        client.search(config.dn_users, { 
+            scope: "sub",
+            attributes: config.search_attributes_tol,
+            filter: ldapEscape.filter(filter, dic)
+        },
+        function(err, res) {
+            // Gestion erreur
             if (err) {
                 reject(err);
             } else {
+                // Toujours gestion différenciée début et fin
                 res.on('searchEntry', function(entry) {
-                    for (var i=0; i&lt;config.ldap_data_tol.searchAttributes.length; i++) {
-                        // Complicated, but hides searchAttributes
-                        eval("candidatesList.push(entry.object."+config.ldap_data_tol.searchAttributes[i]+")");
-                    }
+                    // De nouveau, iteration sur les valeurs recherchées et entrée dans la liste
+                    candidatesList.push([]);
+                    config.attributes_all.forEach((element) => {
+                        eval("candidatesList.slice(-1)[0].push(entry.object."+element+")");
+                    });
+                });
+                res.on('page', function(result, cb) {
+                    resolve(candidatesList);
                 });
                 res.on('end', function(res) { resolve(candidatesList); });
             }
@@ -142,14 +273,48 @@ function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="
     });
 }
 
-// Synthaxe d'utilisation
-//listGroups("quentin.louis").then((meList) => { console.log(meList); });
-TOL("","","","","","","faerix","","","","","","").then((meList) => { console.log(meList); });
+//------------------------------------------------------------------------------------------------------------------------
+// Fonctions de modification
+//------------------------------------------------------------------------------------------------------------------------
+
+/**
+ * @summary Fonction qui va plonger dans le LDAP et modifier un certain jeu de valeur en argument.
+ * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). Il faut l'appeler suivant un schéma `modifierLDAP(...).then((res) => { truc avec res });`. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @arg {string} name - DN de l'emplacement de la requête
+ * @arg {string} op - Deux types ; "replace" ou "add", "add" pouvant rajouter un champ, "replace" sans modification étant une suppression
+ * @arg {Object} mod - Dictionnaire contenant les attributs à modifier et les modifications
+ * @return {boolean} `true` si la modification s'est bien déroulée, false sinon
+ */
+function modifierLDAP(name, op, mod) {
+    // Debug
+    //console.log(base);
+    //console.log(operation);
+    //console.log(modification);
+    return new Promise(function(resolve, reject) {
+        // A terme mettre id du type qui se connecte (permet de pas avoir trop de demandes trop rapides et problème de permission)
+        client.bind(config.connexion.dn, config.connexion.passwd, (err, res) => {});
+
+        // Modification LDAP selon configuration en argument
+        client.modify(name, new ldap.Change({
+            operation: op,
+            modification: mod,
+        }), function(err) {
+            reject(err);
+        });
+        resolve(true);
+    });
+}
+
+//TOL("","","","","","2016","","","ultimate","","","","").then(res => console.log(res));
+
+//modifierLDAP("uid=quentin.chevalier,ou=eleves,dc=frankiz,dc=net","replace", {"displayName": ["hawkspar"]}).then(res => console.log(res));
+rechercheLDAP("ou=eleves,dc=frankiz,dc=net","(displayName=${cn})",{ cn: "Sire hawkspar" }, ["uid"]).then(res => console.log(res));
 
-/* Partage pour le reste du monde ; même remarque synthaxe  
-export { listGroups, listMembers, TOL }; */
+/* Partage pour le reste du monde ; même remarque synthaxe que pour l'import
+export { listGroups, listMembers, TOL };*/
 
-module.exports ={ listGroups, listMembers, TOL };</code></pre>
+/**/module.exports ={ listGroups, listMembers, TOL };
+</code></pre>
         </article>
     </section>
 
@@ -159,13 +324,13 @@ module.exports ={ listGroups, listMembers, TOL };</code></pre>
 </div>
 
 <nav>
-    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
+    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#idTOL">idTOL</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listAdmins">listAdmins</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listGroups2">listGroups2</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#modifierLDAP">modifierLDAP</a></li><li><a href="global.html#rechercheLDAP">rechercheLDAP</a></li><li><a href="global.html#rens">rens</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
 </nav>
 
 <br class="clear">
 
 <footer>
-    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Feb 28 2018 18:30:49 GMT+0100 (Paris, Madrid)
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Mar 01 2018 15:55:14 GMT+0100 (Paris, Madrid)
 </footer>
 
 <script> prettyPrint(); </script>
diff --git a/doc/src_server.js.html b/doc/src_server.js.html
index e4aac17..2693dae 100644
--- a/doc/src_server.js.html
+++ b/doc/src_server.js.html
@@ -34,6 +34,7 @@ import bodyParser from 'body-parser';
 import favicon from 'serve-favicon';
 import morgan from 'morgan';
 import path from 'path';
+import cors from 'cors';
 import schema from './graphql/schema';
 import { graphqlExpress, graphiqlExpress } from 'graphql-server-express';
 import flash from 'connect-flash';
@@ -43,7 +44,7 @@ const server = express();
 // on sait pas a quoi ca sert mais il parait que c'est utile
 server.use(bodyParser.json());
 server.use(bodyParser.urlencoded({
-    extended: false
+    extended: true
 }));
 
 // setting up view engine for pug
@@ -59,10 +60,24 @@ server.use(favicon(path.resolve('./','assets','favicon.ico')));
 server.use(morgan('dev'));
 
 // Charge le middleware express pour GraphQL
-server.use('/graphql', bodyParser.json(), graphqlExpress({schema}));
+server.use('/graphql', bodyParser.json(), cors(),
+    graphqlExpress(req => {
+        let uid;
+
+        try {
+            uid = req.session.id;
+        } catch (err) {
+            uid = "1";
+        }
+
+        return {
+            schema : schema,
+            context : {user : {id : uid}}
+        };
+    }));
 
 // GraphiQL est une console interactive pour faire des requêtes au schéma GraphQL
-server.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql'}));
+server.use('/graphiql', graphiqlExpress({endpointURL: '/graphql'}));
 
 // connect-flash is middleware for flashing messages
 server.use(flash());
@@ -78,13 +93,13 @@ export default server;
 </div>
 
 <nav>
-    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
+    <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#Error404catcher">Error 404 catcher</a></li><li><a href="global.html#Error404handler">Error 404 handler</a></li><li><a href="global.html#idTOL">idTOL</a></li><li><a href="global.html#KnexAPI:Gettable">Knex API: Get table</a></li><li><a href="global.html#listAdmins">listAdmins</a></li><li><a href="global.html#listGroups">listGroups</a></li><li><a href="global.html#listGroups2">listGroups2</a></li><li><a href="global.html#listMembers">listMembers</a></li><li><a href="global.html#modifierLDAP">modifierLDAP</a></li><li><a href="global.html#rechercheLDAP">rechercheLDAP</a></li><li><a href="global.html#rens">rens</a></li><li><a href="global.html#TOL">TOL</a></li></ul>
 </nav>
 
 <br class="clear">
 
 <footer>
-    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Feb 28 2018 18:30:49 GMT+0100 (Paris, Madrid)
+    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Thu Mar 01 2018 15:55:14 GMT+0100 (Paris, Madrid)
 </footer>
 
 <script> prettyPrint(); </script>
diff --git a/ldap_config.json b/ldap_config.json
index 34e97c9..c2070a2 100644
--- a/ldap_config.json
+++ b/ldap_config.json
@@ -10,14 +10,14 @@
 	},
 	"dn_groups":"ou=groups,dc=frankiz,dc=net",
 	"dn_users": "ou=eleves,dc=frankiz,dc=net",
-	"key_al": "uid",
+	"key_id": "uid",
 	"filter_id": "(uid=${id})",
 	"filter_lg": "(restrictedMemberUid=${id})",
 	"attributes_id": ["uid"],
 	"attributes_al": ["memberUid"],
 	"attributes_lm":["restrictedMemberUid"],
 	"attributes_lg":["brMemberOf"],
-	"attributes_all": ["jpegPhoto","givenName", "sn", "brBirthdate", "brPromo","telephoneNumber","mail","brRoom","brIP"],
+	"attributes_all": ["jpegPhoto","givenName", "sn", "brBirthdate", "brPromo","telephoneNumber","mail","brRoom","brIP","brMemberOf"],
 	"search_attributes_tol": ["givenName", "sn", "displayName", "country", "brMemberOf", "brPromo", "brMemberOf", "brMemberOf", "brMemberOf", "telephoneNumber","mail","brRoom","brIP"],
 	"sessionSecret":"change this"
 }
\ No newline at end of file
diff --git a/src/ldap/ldap_data.js b/src/ldap/ldap_data.js
index db964c5..75303a6 100644
--- a/src/ldap/ldap_data.js
+++ b/src/ldap/ldap_data.js
@@ -3,38 +3,41 @@
  * @author hawkspar
  */
 
-/* Ne pas hésiter à repasser en synthaxe ES5... Plus simple pour tester en solo avec node directement */
+/* Ne pas hésiter à repasser en synthaxe ES5... Plus simple pour tester en solo avec node directement
 import ldap  from 'ldapjs';
 import fs from 'fs';
 import ldapEscape from 'ldap-escape';
-import path from 'path';
+import path from 'path';*/
 
-/*var ldap = require('ldapjs');
+/**/var ldap = require('ldapjs');
 var fs = require('fs');
 var ldapEscape = require('ldap-escape');
-var path = require('path');*/
+var path = require('path');
 
 // Important ; permet de vérifier que l'utilisateur reste connecté.
 var ensureLoggedin =  require('connect-ensure-login').ensureLoggedIn;
 
 // Point central ; tous les champs de la BDD sont 'cachés' dans config.json et pas visibles directement
 var configPath = path.resolve('./','ldap_config.json');
-console.log('LDAP configuration loaded from',configPath);
 var config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
 
 // Connection au serveur LDAP avec des temps de timeout arbitraires
 var client = ldap.createClient({ url: config.ldap.server});
 
+//------------------------------------------------------------------------------------------------------------------------
+// Fonctions de recherche
+//------------------------------------------------------------------------------------------------------------------------
+
 /**
- * @summary Fonction qui interroge le LDAP selon un protocole bien précis et renvoit les valeurs trouvées.
- * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). Il faut l'appeler suivant un schéma requeteLDAP(...).then((res) => { truc avec res });. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @summary Fonction qui interroge le LDAP selon un protocole spécifié en argument et renvoit les valeurs trouvées.
+ * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). Il faut l'appeler suivant un schéma `rechercheLDAP(...).then((res) => { truc avec res });`. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
  * @arg {string} base - DN de l'emplacement de la requête
  * @arg {string} filter - Filtre logique de la recherche (format RFC2254)
- * @arg {{}} filter_dic - Dictionnaire qui associe les faux champs dans filter aux vraies valeurs pertinentes de la recherche
+ * @arg {Object} filter_dic - Dictionnaire qui associe les faux champs dans filter aux vraies valeurs pertinentes de la recherche
  * @arg {string[]} attributes - Liste des attributs qui figureront dans le résultat final
- * @return {string[]} Résultats de la recherche
+ * @return {Object} Résultats de la recherche ; soit une liste de valeurs d'attributs, soit une liste de dictionnaires si on veut plus d'un attribut (les clés du dictionnaire sont celles du LDAP) 
  */
-function requeteLDAP(base, filter, filter_dic, attributes) {
+function rechercheLDAP(base, filter, filter_dic, attributes) {
     // Debug
     //console.log(base);
     //console.log(filter);
@@ -42,10 +45,10 @@ function requeteLDAP(base, filter, filter_dic, attributes) {
     //console.log(attributes);
     return new Promise(function(resolve, reject) {
         // A terme mettre id du type qui se connecte (permet de pas avoir trop de demandes trop rapides)
-        client.bind(config.connexion.dn, config.connexion.passwd, (err, res) => {});
+        //client.bind(config.connexion.dn, config.connexion.passwd, (err, res) => {});
 
         let vals=[];
-        // Interrogation LDAP selon configuration du dic
+        // Interrogation LDAP selon configuration fournie en argument
         client.search(base, {
             "scope": "sub",
             "filter": ldapEscape.filter(filter, filter_dic),
@@ -57,9 +60,15 @@ function requeteLDAP(base, filter, filter_dic, attributes) {
             } else {
                 // Dès que la recherche renvoit une entrée, on stocke les attributs qui nous intéresse
                 res.on('searchEntry', function(entry) {
-                    attributes.forEach((element) => {
-                        eval("vals.push(entry.object."+element+")");
-                    });
+                    // Cas un seul attribut où le résultat est une liste
+                    if (attributes.length == 1) { eval("vals.push(entry.object."+attributes[0]+")"); }
+                    // Cas plusieurs attributs donc résultat dictionnaire
+                    else {
+                        vals.push({});
+                        attributes.forEach((element) => {
+                            vals.slice(-1)[0][element]=eval("entry.object."+element+";");
+                        });
+                    }
                 });
                 // Si la recherche est finie on se déconnecte et on renvoit la liste
                 res.on('end', function(res) {
@@ -75,66 +84,67 @@ function requeteLDAP(base, filter, filter_dic, attributes) {
 
 /**
  * @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre.
- * @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma listGroups(...).then((res) => { truc avec res });
+ * @desc Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma `listGroups(...).then((res) => { truc avec res })`;
  * @arg {string} uid - Identifiant de l'individu à interroger (le plus souvent prenom.nom, parfois l'année, supposé valide)
  * @return {string} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
  */
 function listGroups(uid) {
     return new Promise(function(resolve, reject) {
-        resolve(requeteLDAP(config.dn_users, config.filter_id, { id : uid }, config.attributes_lg).then(res => res[0]));
+        resolve(rechercheLDAP(config.dn_users, config.filter_id, { id : uid }, config.attributes_lg).then(res => res[0]));
     });
 }
 
 /**
  * @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre. Assez différente de la précédente en terme d'implémentation, plus lente mais renvoir moins de résultats plus pertinents, probablement plus pérenne.
- * @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma listGroups2(...).then((res) => { truc avec res });
+ * @desc Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma `listGroups2(...).then((res) => { truc avec res });`
  * @arg {string} uid - Identifiant de l'individu à interroger (le plus souvent prenom.nom, parfois l'année, supposé valide)
  * @return {string} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
  */
 function listGroups2(uid) {
     return new Promise(function(resolve, reject) {
-        resolve(requeteLDAP(config.dn_groups, config.filter_lg, { id : uid }, config.attributes_id));
+        resolve(rechercheLDAP(config.dn_groups, config.filter_lg, { id : uid }, config.attributes_id));
     });
 }
 
 /**
  * @summary Fonction qui interroge le LDAP et retrouve la liste des membres d'un groupe.
- * @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json.
+ * @desc Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma `listMembers(...).then((res) => { truc avec res });`
  * @arg {string} gid - Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule)
  * @return {string} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
  */
 function listMembers(gid) {
     return new Promise(function(resolve, reject) {
-        resolve(requeteLDAP(config.dn_groups, config.filter_id, { id: gid }, config.attributes_lm).then(res => res[0]));
+        resolve(rechercheLDAP(config.key_id+"="+gid+","+config.dn_groups, config.filter_id, { id: gid }, config.attributes_lm).then(res => res[0]));
     });
 }
 
 /**
  * @summary Fonction qui interroge le LDAP et retrouve la liste des admins d'un groupe.
- * @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json.
+ * @desc Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma `listAdmins(...).then((res) => { truc avec res });`
  * @arg {string} gid - Identifiant du groupe à interroger (le plus souvent nom du groupe en minuscule)
  * @return {string} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
  */
 function listAdmins(gid) {
     return new Promise(function(resolve, reject) {
-        resolve(requeteLDAP(config.key_al+"="+gid+","+config.dn_groups, config.filter_id, { id: gid }, config.attributes_al).then(res => res[0]));
+        resolve(rechercheLDAP(config.key_id+"="+gid+","+config.dn_groups, config.filter_id, { id: gid }, config.attributes_al).then(res => res[0]));
     });
 }
  
 /**
  * @summary Fonction qui interroge le LDAP au sujet d'un uid particulier et qui renvoit toutes ses infos.
+ * @desc Cette fonction utilise rechercheLDAP avec un dictionnaire prédéfini dans config.json. Il faut l'appeler selon un schéma `rens(...).then((res) => { truc avec res });`
  * @arg {string} uid - Identifiant de l'utilisateur
  * @return {string[]} Informations recueillies ; même quand dans TOL voir config.json.
  */
 function rens(uid) {
     return new Promise(function(resolve, reject) {
-        resolve(requeteLDAP(config.dn_users, config.filter_id, { id: uid }, config.attributes_all));
+        resolve(rechercheLDAP(config.dn_users, config.filter_id, { id: uid }, config.attributes_all));
     });
 }
 
 /**
  * @summary Fonction qui interroge le LDAP et retrouve juste les uid des paxs validant les critères de recherche. Première étape vers vrai TOL (Trombino On Line).
- * @desc Accepte des champs exacts ou incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma TOL(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.
+ * @desc Accepte des champs exacts ou incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma `TOL(uid).then((res) => { truc avec res });`. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.
  * @arg {string} c0 - Prénom
  * @arg {string} c1 - Nom
  * @arg {string} c2 - Surnom
@@ -166,14 +176,14 @@ function idTOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9
             }
         });
 
-        // Appel requeteLDAP avec filtre de l'espace 
-        resolve(requeteLDAP(config.dn_users, filter, filter_dic, config.attributes_id));
+        // Appel rechercheLDAP avec filtre de l'espace 
+        resolve(rechercheLDAP(config.dn_users, filter, filter_dic, config.attributes_id));
     });
 }
 
 /**
- * @summary Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche. Bien mais vite inutilisable car demande trop au LDAP.
- * @desc Accepte des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma TOL(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.
+ * @summary Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche. Bien mais vite inutilisable car demande trop au LDAP et renvoie des erreurs de type size limit. Préférer idTOL puis stalk au cas par cas.
+ * @desc Accepte des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma `TOL(uid).then((res) => { truc avec res });`. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.
  * @arg {string} c0 - Prénom
  * @arg {string} c1 - Nom
  * @arg {string} c2 - Surnom
@@ -197,7 +207,7 @@ function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="
         let filter="";
         let dic={};
         // Iteration pour chaque champ, alourdissement du filtre selon des trucs prédéfini dans config.json encore
-        config.ldap_data_tol.searchFilterAttributes.forEach((element, index, list) => {
+        config.search_attributes_tol.forEach((element, index, list) => {
             if (eval("c"+index.toString()) != '') {                                 // Si il y a qque chose à chercher pour ce filtre
                 filter="(&"+filter+"(|("+element+"=${app_"+element+index+"})"+      // On cherche la valeur exacte
                                    "(|("+element+"=*${app_"+element+index+"})"+     // La valeur finale avec des trucs avant ; wildcard *
@@ -214,9 +224,9 @@ function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="
         var candidatesList=[];
 
         // Interrogation LDAP et filtre de malade
-        client.search(config.ldap_data_tol.searchBase, { 
+        client.search(config.dn_users, { 
             scope: "sub",
-            attributes: config.ldap_data_tol.searchAttributes,
+            attributes: config.attributes_all,
             filter: ldapEscape.filter(filter, dic)
         },
         function(err, res) {
@@ -226,10 +236,10 @@ function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="
             } else {
                 // Toujours gestion différenciée début et fin
                 res.on('searchEntry', function(entry) {
-                    // De nouveau, iteration sur les valeurs recherchées et entrée dans la liste
-                    candidatesList.push([]);
-                    config.ldap_data_tol.searchAttributes.forEach((element) => {
-                        eval("candidatesList.slice(-1)[0].push(entry.object."+element+")");
+                    // De nouveau, iteration sur les valeurs recherchées et entrée dans la liste sous la forme d'un dictionnaire
+                    candidatesList.push({});
+                    config.attributes_all.forEach((element) => {
+                        candidatesList.slice(-1)[0][element]=eval("entry.object."+element+";");
                     });
                 });
                 res.on('page', function(result, cb) {
@@ -241,15 +251,42 @@ function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="
     });
 }
 
-//listMembers("drakkes").then((meList) => { console.log(meList); });
-//listAdmins("br").then((adList) => { console.log(adList); });
-//listGroups("agopia.1999").then((grList) => { console.log(grList); });
-//listGroups2("agopia.1999").then((grList) => { console.log(grList); });
-//rens("quentin.louis").then((profil) => { console.log(profil); });
-//idTOL("","","","","","","bda","","","","","","").then((caList) => { console.log(caList); });
-//TOL("","","","","","","faerix","","","","","","").then((caList) => { console.log(caList); });
+//------------------------------------------------------------------------------------------------------------------------
+// Fonctions de modification
+//------------------------------------------------------------------------------------------------------------------------
+
+/**
+ * @summary Fonction qui va plonger dans le LDAP et modifier un certain jeu de valeur en argument.
+ * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). Il faut l'appeler suivant un schéma `modifierLDAP(...).then((res) => { truc avec res });`. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @arg {string} name - DN de l'emplacement de la requête
+ * @arg {string} op - Deux types ; "replace" ou "add", "add" pouvant rajouter un champ, "replace" sans modification étant une suppression
+ * @arg {Object} mod - Dictionnaire contenant les attributs à modifier et les modifications
+ * @return {boolean} `true` si la modification s'est bien déroulée, false sinon
+ */
+function modifierLDAP(name, op, mod) {
+    // Debug TBM
+    //console.log(base);
+    //console.log(operation);
+    //console.log(modification);
+    return new Promise(function(resolve, reject) {
+        // A terme mettre id du type qui se connecte (permet de pas avoir trop de demandes trop rapides et problème de permission)
+        client.bind(config.connexion.dn, config.connexion.passwd, (err, res) => {});
+
+        // Modification LDAP selon configuration en argument
+        client.modify(name, new ldap.Change({
+            operation: op,
+            modification: mod,
+        }), function(err) {
+            reject(err);
+        });
+        resolve(true);
+    });
+}
+
+//modifierLDAP("uid=quentin.chevalier,ou=eleves,dc=frankiz,dc=net","replace", {"displayName": ["hawkspar"]}).then(res => console.log(res));
+//rechercheLDAP("uid=quentin.chevalier,ou=eleves,dc=frankiz,dc=net","(displayName=${cn})",{ cn: "Sire hawkspar" }, ["jpegPhoto"]).then(res => console.log(res));
 
-/* Partage pour le reste du monde ; même remarque synthaxe que pour l'import */
-export { listGroups, listMembers, TOL };
+/* Partage pour le reste du monde ; même remarque synthaxe que pour l'import
+export { listGroups, listMembers, TOL };*/
 
-/*module.exports ={ listGroups, listMembers, TOL };*/
+/**/module.exports ={ listGroups, listMembers, listAdmins, rens, idTOL, TOL };
-- 
GitLab