Commit 4f2027834110c14c1dfd3fe63a05f70e6bf8a39e

Authored by Etienne Pallier
1 parent 1f28d43a
Exists in master and in 2 other branches dev, dev-IRAP

bugfix ldap (again)

README.md
... ... @@ -54,7 +54,7 @@ Logiciel testé et validé sur les configurations suivantes :
54 54 VERSION ACTUELLE
55 55  
56 56 Date: 13/02/2019
57   -Version: 2.10.9
  57 +Version: 2.10.9.bugfix1
58 58 Author: EP
59 59 Bugfix LDAP anonyme et refactorisation
60 60  
... ...
src/Controller/MaterielsController.php
... ... @@ -804,14 +804,24 @@ class MaterielsController extends AppController
804 804 if ($domaineresp == null)
805 805 $domaineresp = false;
806 806 $utilisateurconnect = TableRegistry::get('Users')->find('all')->toArray();
  807 +
807 808 $users = TableRegistry::get('LdapConnections')->getListUsers();
  809 + //sort($users);
808 810  
  811 + //$users = TableRegistry::get('LdapConnections')->getUsersWithNameAndEmail();
  812 + //$user_names = array_keys($users);
  813 + //sort($user_names);
809 814 // tri des utilisateurs par nom
810   - sort($users);
  815 + //sort($users);
  816 + //debug($users);
  817 + $utilisateurs = $users;
  818 + /*
811 819 $utilisateurs = [];
812 820 for ($i = 0; $i < sizeof($users); $i ++) {
  821 + // $utilisateurs["Etienne Pallier"] = "Etienne Pallier"
813 822 $utilisateurs[$users[$i]] = $users[$i];
814 823 }
  824 + */
815 825  
816 826 // Ne pas commenter la ligne suivante, on en a besoin dans add.cpt
817 827 $mail_responsable = TableRegistry::get('Users')->find()
... ... @@ -827,7 +837,19 @@ class MaterielsController extends AppController
827 837 $this->set('cpMateriel', $cpMateriel);
828 838 }
829 839  
830   - $this->set(compact('designation', 'utilisateurconnect', 'users', 'materiel', 'surCategories', 'categories', 'sousCategories', 'groupesThematiques', 'groupesMetiers', 'organismes', 'sites', 'utilisateurs', 'mail_responsable', 'domaineresp', 'lieu_detail', 'fournisseurs'));
  840 + //$this->set(compact('designation', 'utilisateurconnect', 'users', 'materiel', 'surCategories', 'categories', 'sousCategories', 'groupesThematiques', 'groupesMetiers', 'organismes', 'sites', 'utilisateurs', 'mail_responsable', 'domaineresp', 'lieu_detail', 'fournisseurs'));
  841 + $this->set(compact(
  842 + 'materiel',
  843 + 'utilisateurconnect',
  844 + 'designation',
  845 + 'surCategories', 'categories', 'sousCategories',
  846 + 'groupesThematiques', 'groupesMetiers',
  847 + 'organismes', 'sites',
  848 + 'mail_responsable', 'domaineresp', 'lieu_detail', 'fournisseurs',
  849 + //'users',
  850 + //'user_names',
  851 + 'utilisateurs'
  852 + ));
831 853 $this->set('_serialize', [
832 854 'materiel'
833 855 ]);
... ...
src/Controller/UsersController.php
... ... @@ -214,6 +214,8 @@ class UsersController extends AppController
214 214 'keyField' => 'id',
215 215 'valueField' => 'nom'
216 216 ]);
  217 + // TODO: remplacer getListUsers() par getUsersWithNameAndEmail()
  218 + // TODO: idem pour add() et edit()
217 219 // On recup tous les users du LDAP (ou fakeLDAP si on n'est pas en mode LDAP)
218 220 $users = TableRegistry::get('LdapConnections')->getListUsers();
219 221 // Tri des utilisateurs par nom
... ... @@ -308,6 +310,7 @@ class UsersController extends AppController
308 310 ]);
309 311 }
310 312  
  313 + /* (EP) Il ne sert à rien de rechercher le login !!!
311 314 // called from Javascript (Ajax)
312 315 public function getLdapLogin($userName)
313 316 {
... ... @@ -319,6 +322,7 @@ class UsersController extends AppController
319 322  
320 323 $this->viewBuilder()->layout = 'ajax';
321 324 }
  325 + */
322 326  
323 327 // called from Javascript (Ajax)
324 328 public function getLdapEmail($userName)
... ...
src/Model/Table/LdapConnectionsTable.php
... ... @@ -173,6 +173,42 @@ class LdapConnectionsTable extends AppTable
173 173 </ul>');
174 174 }
175 175  
  176 +
  177 +
  178 + // REAL LDAP only
  179 + /**
  180 + * @return array or boolean : all users from DB (CACHE of the LDAP) or FALSE (if table emtpy or expired data)
  181 + */
  182 + private function fetchAllUsersFromDB() {
  183 + // On remet à jour tous les 7 jours
  184 + $PEREMPTION_NB_DAYS = 7;
  185 +
  186 + // Doit aussi retourner FALSE si la ligne FAKE de la table users
  187 + // (celle qui contient le user_name "FAKE_USER")
  188 + // a une date "updated" périmée (now - updated > $PEREMPTION_NB_DAYS)
  189 + // (update automatique de tous les users, chaque semaine, pour rester synced avec le LDAP)
  190 + // By default, no user in CACHE
  191 + return FALSE;
  192 + }
  193 +
  194 + // REAL LDAP only
  195 + // Sauvegarde de tous les users du LDAP en BD (avec un rythme de mise à jour hebdo)
  196 + // Seulement les champs: nom, pnom, login, pass, email, create, updated, profile
  197 + private function saveAllUsersInDB($users_fetched) {
  198 +
  199 + // START TRANSACTION
  200 + // 1) Update (ou création) de la ligne FAKE (contient le user_name "FAKE_USER") => avec une date "updated"
  201 + // 2) Update (ou création) de chaque user contenu dans $users_fetched
  202 + // Attention à ne pas perdre l'attribut "profile", surtout pour les users privilégiés!!! (les autres ont un profile = "Utilisateur")
  203 + // END TRANSACTION (COMMIT)
  204 +
  205 + // SAVE s'est bien passé
  206 + return TRUE;
  207 + }
  208 +
  209 + /**
  210 + * @return $users_fetched or FALSE
  211 + */
176 212 // REAL or FAKE LDAP
177 213 public function getAllLdapUsers()
178 214 {
... ... @@ -181,7 +217,16 @@ class LdapConnectionsTable extends AppTable
181 217  
182 218 // REAL LDAP
183 219 if ($this->LDAP_USED) {
184   - $res = $this->searchLdap($this->filter, []);
  220 +
  221 + // 1) Search users in CACHE (DB)
  222 + $users_fetched = $this->fetchAllUsersFromDB();
  223 +
  224 + // 2) Not found in CACHE, so search users in LDAP
  225 + if ($users_fetched === FALSE) {
  226 + $users_fetched = $this->searchLdap($this->filter, []);
  227 + // CACHE the new user in DB for next time
  228 + if ($users_fetched != FALSE) $this->saveAllUsersInDB($users_fetched);
  229 + }
185 230 /*
186 231 $ldapConnection = ldap_connect($this->host, $this->port);
187 232 ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
... ... @@ -198,15 +243,43 @@ class LdapConnectionsTable extends AppTable
198 243  
199 244 // FAKE LDAP
200 245 else {
201   - $res = $this->fakeLDAPUsers;
  246 + $users_fetched = $this->fakeLDAPUsers;
202 247 }
203   - return $res;
  248 +
  249 + // Noter que $user_fetched peut etre egal a FALSE (si rien trouvé)
  250 + return $users_fetched;
204 251 }
205 252 } catch (Exception $e) {}
206   - return false;
  253 +
  254 + // Pb, rien trouvé
  255 + return FALSE;
207 256 }
208 257  
209 258  
  259 +
  260 + // $userName = login
  261 + public function getUserAttributes($userName)
  262 + {
  263 + try {
  264 +
  265 + if ($this->checkConfiguration()) {
  266 + if ($this->USE_LDAP) {
  267 + $ldapConnection = ldap_connect($this->host, $this->port);
  268 + ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
  269 + $results = ldap_search($ldapConnection, $this->baseDn, '(' . $this->authenticationType . '=' . $userName . ')');
  270 + return ldap_get_entries($ldapConnection, $results);
  271 + } else
  272 + return array(
  273 + $this->getFakeLdapUser($userName)
  274 + );
  275 + }
  276 + } catch (Exception $e) {}
  277 +
  278 + return false;
  279 + }
  280 +
  281 +
  282 +
210 283 // REAL LDAP only
211 284 /*
212 285 * @param string $ldapConnection
... ... @@ -281,19 +354,43 @@ class LdapConnectionsTable extends AppTable
281 354 return FALSE;
282 355 }
283 356  
  357 + // TODO: à implémenter
  358 + public function getUsersWithNameAndEmail() {
  359 + $usersWithNameAndEmail = [];
  360 + // Get all users (with ALL their attributes)
  361 + $u = $this->getAllLdapUsers();
  362 + // Sort users
  363 + //sort($u);
  364 + //debug($u);
  365 + // (EP) Refactorisation pour éviter code redondant ci-dessous, c'était pourtant pas compliqué, poil dans la main...
  366 + $nb_users = $this->LDAP_USED ? $u['count'] : sizeof($u)-1;
  367 + for ($i = 0; $i < $nb_users; $i ++)
  368 + // $utilisateurs["Pallier Etienne"] = ["email"]
  369 + $usersWithNameAndEmail[ $u[$i]['sn'][0].' '.$u[$i]['givenname'][0] ] = $u[$i]['mail'][0];
  370 + //debug($usersWithNameAndEmail);
  371 + // Sort users (without modifying the keys, don't use sort() but asort() !!!!!!!!!!!!!)
  372 + asort($usersWithNameAndEmail);
  373 + return $usersWithNameAndEmail;
  374 + }
  375 +
  376 +
284 377 /**
285 378 * Return a list of Users with key = username & value = username
286 379 */
287 380 public function getListUsers()
288 381 {
  382 + $utilisateurs = [];
  383 +
  384 + // Get all users (with ALL their attributes)
289 385 $u = $this->getAllLdapUsers();
  386 + // Sort users
  387 + //sort($u);
290 388 //debug($u);
291   - $utilisateurs = [];
292 389  
293 390 // (EP) Refactorisation pour éviter code redondant ci-dessous, c'était pourtant pas compliqué, poil dans la main...
294 391 $nb_users = $this->LDAP_USED ? $u['count'] : sizeof($u)-1;
295 392 for ($i = 0; $i < $nb_users; $i ++)
296   - // $utilisateurs["Pallier Etienne"] = "Pallier Etienne"
  393 + // $utilisateurs["Pallier Etienne"] = "Pallier Etienne"
297 394 $utilisateurs[ $u[$i]['sn'][0].' '.$u[$i]['givenname'][0] ] = $u[$i]['sn'][0].' '.$u[$i]['givenname'][0];
298 395 /*
299 396 if ($this->LDAP_USED) {
... ... @@ -307,6 +404,9 @@ class LdapConnectionsTable extends AppTable
307 404 }
308 405 */
309 406 //debug($utilisateurs);
  407 + // Sort users (without modifying the keys, don't use sort() but asort() !!!!!!!!!!!!!)
  408 + asort($utilisateurs);
  409 + //debug($utilisateurs);
310 410 return $utilisateurs;
311 411 }
312 412  
... ... @@ -386,6 +486,8 @@ class LdapConnectionsTable extends AppTable
386 486 // TODO: implement
387 487 // REAL LDAP only
388 488 private function checkAndFetchUserFromDB($user_login, $user_password) {
  489 + // Doit aussi return false si ce user_login est "périmé" (sa date "created" est > 2 mois par exemple),
  490 + // ce qui obligera à relire ses données dans le LDAP et donc se mettre à jour
389 491 // By default, user is not in DB
390 492 return FALSE;
391 493 }
... ... @@ -394,44 +496,44 @@ class LdapConnectionsTable extends AppTable
394 496 // REAL LDAP only
395 497 private function searchLdap($filter, $just_these, $user_login=NULL, $user_password=NULL) {
396 498  
397   - // CONNEXION
398   - $ldapConnection = ldap_connect($this->host, $this->port)
399   - or die("Could not connect to $this->host (port $this->port)");
400   -
401   - if ($ldapConnection) {
  499 + // CONNEXION
  500 + $ldapConnection = ldap_connect($this->host, $this->port)
  501 + or die("Could not connect to $this->host (port $this->port)");
  502 +
  503 + if ($ldapConnection) {
  504 +
  505 + // OPTIONS
  506 + ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
402 507  
403   - // OPTIONS
404   - ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
405   -
406   - // BINDING
407   -
408   - // - Authentified
409   - if ($this->ldap_authentified)
410   - $ldapbind = ldap_bind($ldapConnection, $this->bindDn, $this->bindPass); // or die("Could not bind to LDAP server.". ldap_error($ldapConnection) );
411   -
412   - // - Anonymous
413   - // En cas de LDAP anonyme, binding quand même pour vérifier le mot de passe de l'utilisateur.
414   - // Sans cette ligne, on passe avec n'importe quel password !!!
415   - else {
416   - $ldapbind = TRUE;
417   - debug("log, pass= " . $user_login . ' ' . $user_password);
418   - if ($user_login && $user_password) $ldapbind = ldap_bind($ldapConnection, $this->authenticationType.'='.$user_login, $user_password);
419   - debug("ldapbind " . $ldapbind);
420   - }
421   -
422   - // SEARCH
423   - if ($ldapbind) {
424   - //$search = $this->getLdapUserAttributes($ldapConnection, $filter, $just_these, $user_login);
425   - $search = $this->getLdapUsersAttributes($ldapConnection, $filter, $just_these);
426   - if ($search === false) die("Could not get user attributes from LDAP server, response was: " . ldap_error($ldapConnection) );
427   - //return $search[0];
428   - return $search;
429   - }
  508 + // BINDING
430 509  
  510 + // - Authentified
  511 + if ($this->ldap_authentified)
  512 + $ldapbind = ldap_bind($ldapConnection, $this->bindDn, $this->bindPass); // or die("Could not bind to LDAP server.". ldap_error($ldapConnection) );
  513 +
  514 + // - Anonymous
  515 + // En cas de LDAP anonyme, binding quand même pour vérifier le mot de passe de l'utilisateur.
  516 + // Sans cette ligne, on passe avec n'importe quel password !!!
  517 + else {
  518 + $ldapbind = TRUE;
  519 + debug("log, pass= " . $user_login . ' ' . $user_password);
  520 + if ($user_login && $user_password) $ldapbind = ldap_bind($ldapConnection, $this->authenticationType.'='.$user_login, $user_password);
  521 + debug("ldapbind " . $ldapbind);
431 522 }
432 523  
433   - // Il y a eu un pb, utilisateur non reconnu
434   - return FALSE;
  524 + // SEARCH
  525 + if ($ldapbind) {
  526 + //$search = $this->getLdapUserAttributes($ldapConnection, $filter, $just_these, $user_login);
  527 + $search = $this->getLdapUsersAttributes($ldapConnection, $filter, $just_these);
  528 + if ($search === false) die("Could not get user attributes from LDAP server, response was: " . ldap_error($ldapConnection) );
  529 + //return $search[0];
  530 + return $search;
  531 + }
  532 +
  533 + }
  534 +
  535 + // Il y a eu un pb, utilisateur non reconnu
  536 + return FALSE;
435 537  
436 538 }
437 539  
... ... @@ -518,23 +620,38 @@ class LdapConnectionsTable extends AppTable
518 620 try {
519 621 if ($this->checkConfiguration()) {
520 622  
521   - // We are using LDAP
522   - if ($this->LDAP_USED) {
  623 + // REAL LDAP
  624 + if ($this->LDAP_USED) {
  625 +
523 626 // No connexion allowed without password
524 627 if (strlen(trim($user_password)) == 0) return FALSE;
  628 +
  629 + // VIEUX CODE QUI MARCHE !!!
  630 + $ldapConnection = ldap_connect($this->host, $this->port);
  631 + ldap_set_option($ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3);
  632 + if (@ldap_bind($ldapConnection, $this->authenticationType . '=' . $user_login . ',' . $this->baseDn, $user_password)) {
  633 + return $this->getUserAttributes($login)[0];
  634 + /*
  635 + * } else {
  636 + * return false;
  637 + */
  638 + }
525 639  
  640 + /* NEW CODE QUI MARCHE PAS
  641 + // TODO: optimisation possible
526 642 // 1) Search user in CACHE (DB)
527 643 $user_fetched = $this->checkAndFetchUserFromDB($user_login, $user_password);
528   - if ($user_fetched === FALSE) {
529 644 // 2) If not CACHED, search user in LDAP
  645 + if ($user_fetched === FALSE) {
530 646 $user_fetched = $this->checkAndFetchUserFromLdap($user_login, $user_password);
531 647 // CACHE the new user in DB for next time
532 648 if ($user_fetched != FALSE) $this->saveNewUserInDB($user_fetched);
533 649 }
534 650 return $user_fetched; // Noter que $user_fetched peut etre egal a FALSE (si pas trouvé)
  651 + */
535 652 }
536 653  
537   - // We are not using LDAP (so, use FAKE LDAP instead)
  654 + // FAKE LDAP
538 655 else {
539 656 $user = $this->getFakeLdapUser($user_login);
540 657 // debug($user);
... ...
src/Template/Materiels/add.ctp
1 1 <?php
  2 +
  3 +//debug($utilisateurs);
  4 +
  5 +//debug($users);
  6 +//$user_names= array_keys($users);
  7 +//debug($username);
  8 +//debug($user_names);
  9 +
2 10 use Cake\ORM\TableRegistry;
3 11 if (isset($cpMateriel)) {
4 12 $Designation = $cpMateriel->designation;
... ... @@ -201,26 +209,31 @@ if (isset($cpMateriel)) {
201 209 'empty' => 'Choisir un utilisateur',
202 210 'default' => $username,
203 211 'options' => $utilisateurs
  212 + //'options' => $user_names
204 213 ]);
205 214 echo $this->Form->control('email_responsable', [
206 215 'label' => 'Email de l\'utilisateur',
207 216 'readonly' => true,
208 217 'default' => $mail_responsable
209 218 ]);
  219 +
  220 + /*
210 221 $res = TableRegistry::get('Users')->find()
211 222 ->where([
212 223 'username' => $username,
213 224 'role' => 'Administration'
214 225 ])
215   - ->first();
  226 + ->first();
  227 + */
216 228 $administrateurs = TableRegistry::get('Users')->find('list', [
217 229 'keyField' => 'id',
218 230 'valueField' => 'nom'
219 231 ])
220   - ->where([
  232 + ->where([
221 233 'role =' => 'Administration'
222 234 ])
223   - ->toArray();
  235 + ->toArray();
  236 +
224 237 echo $this->Form->control('gestionnaire_id', [
225 238 'label' => 'Nom du gestionnaire de référence du matériel',
226 239 'empty' => 'Choisir un gestionnaire',
... ...
src/Template/Users/add.ctp
... ... @@ -103,12 +103,14 @@ $(document).ready(function () {
103 103 }).done(function(data) {
104 104 $("#email").val(data)
105 105 });
  106 + /* (EP) il ne sert à rien de rechercher le login !!!
106 107 var loginUrl = url.replace("add", "getLdapLogin/");
107 108 $.ajax({
108 109 url: loginUrl + $("#nom").val()
109 110 }).done(function(data) {
110 111 $("#username").val(data)
111 112 });
  113 + */
112 114 });
113 115 });
114 116  
... ...