From 02b7f0bea25e60a9da81eb4983b9e927f020c9bb Mon Sep 17 00:00:00 2001 From: Etienne Pallier Date: Wed, 29 Apr 2020 15:01:14 +0200 Subject: [PATCH] Diverses améliorations, simplifications, optimisations --- README.md | 19 ++++++++++++++----- src/Controller/AppController.php | 464 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/Controller/MaterielsController.php | 451 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- src/Controller/PagesController.php | 41 ++++++++++++++++++++++------------------- src/Controller/QrCodesController.php | 9 +++++++++ src/Controller/SuivisController.php | 15 +++++++++++---- src/Controller/UsersController.php | 7 +++++-- src/Model/Entity/User.php | 3 ++- src/Model/Table/UsersTable.php | 7 +++++++ src/Template/Layout/default.ctp | 5 ++++- src/Template/Materiels/add_edit.ctp | 25 +++++++++++++++++++++---- src/Template/Materiels/view.ctp | 2 ++ tests/TestCase/Controller/MaterielsControllerTest.php | 30 +++++++++++++++++++----------- 13 files changed, 622 insertions(+), 456 deletions(-) diff --git a/README.md b/README.md index 8897edc..7d2a6a6 100644 --- a/README.md +++ b/README.md @@ -55,13 +55,15 @@ VERSION ACTUELLE -Date: 24/04/2020 -Version: 3.7.9.20 +Date: 28/04/2020 +Version: 3.7.9.21 Author: EP Commentaire: - Améliorations diverses : - - Meilleure gestion des aspects authentification et authorization (car je comprends mieux maintenant) - - PagesController maintenant bien plus clean + Diverses améliorations, simplifications, optimisations : + - Ajout de $this->entity, $this->action et $this->action_id (...) dans beforeFilter() pour simplifier et optimiser la suite des traitements + - simplification du isAuthorizedAction() de Materiels + - Optimisations pour éviter trop de requetes en BD et simplification des tests acl + - Meilleure gestion des aspects authentification et authorization - mon 1er View Helper dans src/View/Helper (MyButtonHelper) pour créer plus facilement des boutons !! : - migration des fonctions getActionButton() et displayElement() dans MyButtonHelper et remplacement progressif dans les vues @@ -98,6 +100,13 @@ La liste ci-dessous n'est plus à jour, elle est désormais en ligne ici : https ----------------------------------------------------------------------------------------------------------- +24/04/2020 Version 3.7.9.20 (EP) + Améliorations diverses : + - Meilleure gestion des aspects authentification et authorization (car je comprends mieux maintenant) + - PagesController maintenant bien plus clean + - mon 1er View Helper dans src/View/Helper (MyButtonHelper) pour créer plus facilement des boutons !! : + - migration des fonctions getActionButton() et displayElement() dans MyButtonHelper et remplacement progressif dans les vues + 20/04/2020 Version 3.7.9.19 (EP) Améliorations EMPRUNT... : - Améliorations EMPRUNT diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index e762615..24d0b7a 100755 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -359,104 +359,50 @@ class AppController extends Controller return (int) $this->request->getParam('pass.0'); } - /** - * Initialization hook method. - * Use this method to add common initialization code like loading components. - * e.g. `$this->loadComponent('Security');` - * - * @return void + /* (EP 20200428) + * + * Méthode pour optimiser les accès à la BD. + * Retourne l'entité concernée par l'action. + * + * Cette méthode ne doit être appelée que lorsque c'est approprié + * (actions 'edit', 'view', ..., mais pas 'add', 'find', 'index', ...) + * sinon ça provoque une exception... + * + * Optimisation : l'entité n'est récupérée dans la BD qu'une seule fois pour toutes + * */ - public function initialize() - { - $this->myDebug("step 0B (general): AppController.initialize()"); - - parent::initialize(); - - $this->loadComponent('RequestHandler'); - $this->loadComponent('Flash'); - - // Composant en charge de l'authentification - - // - sans LDAP : + protected function getEntity($id=null) { + // Si pas d'id => exception (stop) + //assert($this->action_id>0); + if (!$this->action_id && !$id) throw new \Exception(__("cette methode doit etre appelée avec un id déjà positionné !!!")); + + // Si l'entité actuellement en mémoire n'est pas la bonne, la mettre à null pour obliger à la recharger + if ($id && $this->entity && $this->entity->id != $id) $this->entity = null; + + // Les 3 sont possibles + //$model = $this->request->getParam('controller'); // ex: Materiels + //$model = $this->name; // ex: Materiels + $model = $this->modelClass; // ex: Materiels + /* - $this->loadComponent('Auth', [ - 'authenticate' => [ - 'Form' => [ - 'fields' => [ - 'username' => 'email', - 'password' => 'password' - ] - ] - ], - 'loginAction' => [ - 'controller' => 'Users', - 'action' => 'login' - ], - // If unauthorized, return them to page they were just on - 'unauthorizedRedirect' => $this->referer() - ]); - // Allow the display action so our PagesController - // continues to work. Also enable the read only actions. - $this->Auth->allow(['display', 'view', 'index']); - // Les autres actions sont redirigées sur /users/login + debug("model2"); + $model = $this->$model; + debug($model); */ - - // - avec LDAP : - /* - * If none of your users have hashed passwords, comment this block and $this->Auth->allow() calls. - * (par exemple dans beforeFilter()) - * Then go and edit the user, saving a new password for them. - * After saving a new password for the user, - * make sure to uncomment the lines we just temporarily commented! - */ - $this->loadComponent('LdapAuth', [ - // Les AUTHORIZATIONS sont faites par Controleur - // (et non pas par un Component ou plugin) - // TODO: utiliser Authorization component plugin (cakephp v4) - //'authorize'=> 'Controller', - 'authorize' => ['Controller'], - /* - 'authenticate' => [ - 'Form' => [ - 'fields' => [ - 'username' => 'email', - 'password' => 'password' - ] - ] - ], - */ - 'loginRedirect' => [ - 'controller' => 'Pages', - //'action' => 'home' - 'action' => 'display', - 'home' - ], - 'logoutRedirect' => [ - 'controller' => 'Pages', - 'action' => 'home' - ] - ]); - // Actions autorisées SANS authentification - // Allow the display action so our PagesController continues to work. - // Also enable the read only actions. - // Déplacé dans beforeFilter() - //$this->LdapAuth->allow(['display', 'view', 'index']); - // Autoriser TOUTES les actions SANS authentification : - //$this->LdapAuth->allow(); - - // On charge la configuration + + //ex: if (! $this->entity) $this->entity = $this->Materiels->get($this->action_id); + if (! $this->entity) $this->entity = $this->$model->get($this->action_id); /* - $this->confLabinvent = TableRegistry::getTableLocator()->get('Configurations')->find() - ->where([ - 'id =' => 1 - ]) - ->first(); + * Avec les entités associées : + if (! $this->entity) $this->entity = $this->$model->get($this->action_id, [ + 'contain' => ['Comments'] + ]); */ - $this->confLabinvent = TableRegistry::getTableLocator()->get('Configurations')->find()->first(); - // (EP 23/5/19) Exception si la config est vide, inutile d'aller plus loin ! - if (is_null($this->confLabinvent)) throw new \Exception("EXCEPTION: La table 'configurations' de la base de données est vide"); + //debug($this->entity); + return $this->entity; } + /** * (EP) * Autorisations PAR DÉFAUT @@ -472,19 +418,16 @@ class AppController extends Controller // $role = $this->getUserRole($user); - // Seul Administration (et +) peut ajouter, supprimer ou modifier - if (in_array($action, ['add', 'edit', 'delete'])) { + // Seul Administration (et +) peut ajouter, supprimer ou modifier (pour la plupart des controleurs) + if (in_array($action, ['add', 'edit', 'delete'])) return ($this->USER_IS_ADMIN_AT_LEAST()); /* if ($this->USER_IS_ADMIN_AT_LEAST()) return true; // Les autres n'y ont pas accès return false; */ - } - - // By default - // return parent::isAuthorized($user); + // Sinon, on applique les règles générales par défaut // Ne pas faire ça car $this sera interprété comme le controleur SPECIFIQUE et non AppController : //return $this->isAuthorized($user); // Donc, il faut être explicite : @@ -498,16 +441,22 @@ class AppController extends Controller * Check whether a LOGGED in user has a set of permissions to perform a given action * Give authorization in general * - * Autorisations APRES connexion - * (AVANT, c'est initialize() et beforeFilter() qui s'en occupent) + * Autorisations APRES connexion, donc à partir d'ici le user est obligatoirement identifié + * (AVANT connexion, c'est initialize() et beforeFilter() qui gèrent) * * On tente d’autoriser ici les actions qui n’ont pas été autorisées * par la méthode isAuthorized du controleur spécifique * + * ref: https://book.cakephp.org/4/fr/controllers/components/authentication.html#autorisation + * + * $user est l'equivalent de $this->LdapAuth->user() + * */ public function isAuthorized($user) { $this->myDebug("step 2C (general): AppController.isAuthorized()"); + + // $user est l'equivalent de $this->LdapAuth->user() $this->myDebug("- user is:", $user); /* @@ -517,39 +466,54 @@ class AppController extends Controller * return true; * } */ - $configuration = $this->confLabinvent; - $role = $this->getUserRole($user); + //$configuration = $this->confLabinvent; + //$role = $this->getUserRole($user); + /* * $role = TableRegistry::getTableLocator()->get('Users')->find() * ->where(['username' => $user[$configuration->authentificationType_ldap][0]]) * ->first()['role']; */ - $this->myDebug("- role is " . $role); + $this->myDebug("- role is " . $this->userRole); + + /* + $prefix = $this->request->getParam('prefix'); + $this->myDebug("- prefix is $prefix"); + */ // BETTER: // $action = $this->request->getAttribute('params')['action']; // $action = $this->request->getParam('action'); - $action = $this->getActionPassed(); + //$action = $this->getActionPassed(); // error_log($action); - $this->myDebug("- action is $action"); - + //$this->myDebug("- action is $action"); + $this->myDebug("- action is $this->action"); + // On autorise ou pas l’action demandée : // - Super-Admin peut accéder à toutes les actions - if ($role == 'Super Administrateur') return true; - // - Actions accessibles à TOUS les roles (profils), quelque soit le controleur - if (in_array($action, [ + //if ($role == 'Super Administrateur') return true; + if ($this->USER_IS_SUPERADMIN) return true; + // - Actions générales accessibles à TOUS les roles (profils), pour TOUT controleur + if (in_array($this->action, [ 'index', 'view', 'add', 'find', + /* (EP sale ! => migré dans chaque controleur spécifique concerné) + // QrCode 'creer', + // Suivis 'getNextDate', + // Materiels 'getDateGarantie' + */ ])) return true; - // - Pour toutes les autres actions => accès refusé (denied) + + // - Pour toutes les autres actions, par défaut => accès refusé (denied) return false; - } + + } // isAuthorized() // (EP) Used by Materiels and Users Controllers @@ -663,6 +627,127 @@ class AppController extends Controller return $this->userHasRole('Utilisateur'); } + + + /** + * Initialization hook method. + * Use this method to add common initialization code like loading components. + * e.g. `$this->loadComponent('Security');` + * + * ref: https://book.cakephp.org/4/fr/controllers/components/authentication.html#id1 + * ref: https://book.cakephp.org/4/fr/controllers/components/authentication.html#configuration-des-gestionnaires-d-authentification + * + * @return void + */ + public function initialize() + { + $this->myDebug("step 0B (general): AppController.initialize()"); + + parent::initialize(); + + $this->loadComponent('RequestHandler'); + $this->loadComponent('Flash'); + + // Composant en charge de l'authentification + + // - sans LDAP : + /* + $this->loadComponent('Auth', [ + 'authenticate' => [ + 'Form' => [ + 'fields' => [ + 'username' => 'email', + 'password' => 'password' + ] + ] + // avec finder redéfini + 'Form' => [ + 'finder' => 'auth' // va utiliser une méthode findAuth() dans UsersTable + ] + ], + 'loginAction' => [ + 'controller' => 'Users', + 'action' => 'login' + ], + // If unauthorized, return them to page they were just on + 'unauthorizedRedirect' => $this->referer() + ]); + // Allow the display action so our PagesController + // continues to work. Also enable the read only actions. + $this->Auth->allow(['display', 'view', 'index']); + // Les autres actions sont redirigées sur /users/login + */ + + // - avec LDAP : + /* + * If none of your users have hashed passwords, comment this block and $this->Auth->allow() calls. + * (par exemple dans beforeFilter()) + * Then go and edit the user, saving a new password for them. + * After saving a new password for the user, + * make sure to uncomment the lines we just temporarily commented! + */ + $this->loadComponent('LdapAuth', [ + // Les AUTHORIZATIONS sont faites par Controleur + // (et non pas par un Component ou plugin) + // TODO: utiliser Authorization component plugin (cakephp v4) + //'authorize'=> 'Controller', + 'authorize' => ['Controller'], + /* pour Auth (au lieu de LdapAuth) on aurait aussi mis ceci : + 'authenticate' => [ + 'Form' => [ + 'fields' => [ + 'userna100000000000000000000000000000000me' => 'email', + 'password' => 'password' + ] + ] + ], + */ + // Redirection après login : + 'loginRedirect' => [ + 'controller' => 'Pages', + //'action' => 'home' + 'action' => 'display', + 'home' + ], + // Redirection après logout : + 'logoutRedirect' => [ + 'controller' => 'Pages', + 'action' => 'home' + ] + ]); + // On peut aussi configurer après : + // Message d'erreur en cas de refus de connexion + $this->LdapAuth->setConfig('authError', "Désolé, vous n'êtes pas autorisé à accéder à cette zone."); + /* Autres possibilités de config : + * $this->Auth->config('authenticate', [ + * 'Form' => ['userModel' => 'Members'] + * //'Basic' => ['userModel' => 'Members'], + * ]); + * $this->Auth->config('authorize', ['Controller']); + */ + // Actions autorisées SANS authentification + // Allow the display action so our PagesController continues to work. + // Also enable the read only actions. + // Déplacé dans beforeFilter() + //$this->LdapAuth->allow(['display', 'view', 'index']); + // Autoriser TOUTES les actions SANS authentification : + //$this->LdapAuth->allow(); + + // On charge la configuration + /* + $this->confLabinvent = TableRegistry::getTableLocator()->get('Configurations')->find() + ->where([ + 'id =' => 1 + ]) + ->first(); + */ + $this->confLabinvent = TableRegistry::getTableLocator()->get('Configurations')->find()->first(); + // (EP 23/5/19) Exception si la config est vide, inutile d'aller plus loin ! + if (is_null($this->confLabinvent)) throw new \Exception("EXCEPTION: La table 'configurations' de la base de données est vide"); + + } // initialize() + + /** * * {@inheritdoc} @@ -679,19 +764,28 @@ class AppController extends Controller */ public function beforeFilter(Event $event) { // Affichages pour debug + //pr($event); $this->myDebug("step 1B (general): AppController.beforeFilter()"); $controllerName = $this->request->getParam('controller'); $this->myDebug("- controller passed : $controllerName"); - $this->myDebug("- action passed : ".$this->getActionPassed()); $passedArgs = $this->request->getParam('pass'); $this->myDebug("- args passed : ", $passedArgs); $query = $this->request->getQueryParams(); $this->myDebug("- query passed : ", $query); - //pr($event); - - // !!! Ne jamais autoriser l'action 'login', sinon cela va créer des problèmes sur le fonctionnement normal de AuthComponent (cf doc) !!! + + // Initialisations pour la suite + // - L'entité concernée par l'action + // Par défaut null car certaines actions n'ont pas d'entité (ex : 'add', 'find', 'index', ...) + $this->entity = null; + // - L'action demandée et son id le cas échéant (nul par défaut, égal 0) + $this->action = $this->getActionPassed(); + $this->myDebug("- action passed : ".$this->action); + $this->action_id = $this->getIdPassed(); + $this->myDebug("- id passed : ".$this->action); + parent::beforeFilter($event); + // !!! Ne jamais autoriser l'action 'login', sinon cela va créer des problèmes sur le fonctionnement normal de AuthComponent (cf doc) !!! /* * EXEMPLES d'utilisation: * // to allow all access to all actions: @@ -713,72 +807,75 @@ class AppController extends Controller // TODO: (EP) A quoi ça sert ??? $this->request->getSession()->write("authType", $configuration->ldap_authenticationType); - // ATTENTION, $priviledgedUser = NULL si l'utilisateur courant n'est pas un utilisateur privilégié - // (c'est à dire s'il n'est pas dans la table "utilisateurs") - $this->priviledgedUser = $this->getTablePriviledgedUserFromCurrentSessionUserIfExists(); - //$role = $this->getUserRole(); - $this->userRole = $this->getUserRole(); - $profile = self::PROFILES["$this->userRole"]; - $this->myDebug("- userRole is {$this->getUserRole()}", "- profile is: $profile"); - - // Set General CONSTANTS for all CONTROLLERS - // (Before, they used to be in beforeFilter()) - // - Users constants - $this->userName = $this->LdapAuth->user('sn')[0] . ' ' . $this->LdapAuth->user('givenname')[0]; - //$this->set('username', $this->LdapAuth->user('sn')[0] . ' ' . $this->LdapAuth->user('givenname')[0]); - - $this->USER_IS_UTILISATEUR = ($profile == self::PROFILE_USER); - $this->USER_IS_RESPONSABLE = ($profile == self::PROFILE_RESPONSABLE); - $this->USER_IS_ADMIN = ($profile == self::PROFILE_ADMIN); - $this->USER_IS_ADMINPLUS = ($profile == self::PROFILE_ADMINPLUS); - $this->USER_IS_SUPERADMIN = ($profile == self::PROFILE_SUPERADMIN); - - $this->USER_IS_RESPONSABLE_OR_MORE = ($profile >= self::PROFILE_RESPONSABLE); - $this->USER_IS_ADMIN_OR_MORE = ($profile >= self::PROFILE_ADMIN); - $this->USER_IS_ADMINPLUS_OR_MORE = ($profile >= self::PROFILE_ADMINPLUS); - - - // - Misc constants - $this->idGmNa = TableRegistry::getTableLocator()->get('GroupesMetiers')->find() - ->where([ - 'nom =' => 'N/A' - ]) - ->first()['id']; - $this->idGtNa = TableRegistry::getTableLocator()->get('GroupesThematiques')->find() - ->where([ - 'nom =' => 'N/A' - ]) - ->first()['id']; + // Groupes métier et technique + // id du Groupe métier N/A + $this->idGmNa = TableRegistry::getTableLocator()->get('GroupesMetiers') + ->find()->where(['nom =' => 'N/A'])->first()['id']; + // id du Groupe technique N/A + $this->idGtNa = TableRegistry::getTableLocator()->get('GroupesThematiques') + ->find()->where(['nom =' => 'N/A'])->first()['id']; + + // Utilisateur connecté (identifié) ? + $this->myDebug("- Utilisateur connecté ? : ", $this->LdapAuth->user() ? "oui" : "non"); + $this->myDebug($this->LdapAuth->user()); + // Si le user est connecté (identifié), on positionne quelques variables utiles + // - pour le controleur spécifique, + // - et pour la vue + if ($this->LdapAuth->user()) { + // ATTENTION, $priviledgedUser = NULL si l'utilisateur courant n'est pas un utilisateur privilégié + // (c'est à dire s'il n'est pas dans la table "utilisateurs") + $this->priviledgedUser = $this->getTablePriviledgedUserFromCurrentSessionUserIfExists(); + //$role = $this->getUserRole(); + $this->userRole = $this->getUserRole(); + $profile = self::PROFILES["$this->userRole"]; + $this->myDebug("- priviledgedUser is {$this->priviledgedUser}"); + $this->myDebug("- userRole is {$this->getUserRole()}", "- profile is: $profile"); + // L'utilisateur connecté (return null si pas connecté) + // $this->Auth->user('id'); + $this->userName = $this->LdapAuth->user('sn')[0] . ' ' . $this->LdapAuth->user('givenname')[0]; + //$this->set('username', $this->LdapAuth->user('sn')[0] . ' ' . $this->LdapAuth->user('givenname')[0]); + $this->USER_IS_UTILISATEUR = ($profile == self::PROFILE_USER); + $this->USER_IS_RESPONSABLE = ($profile == self::PROFILE_RESPONSABLE); + $this->USER_IS_ADMIN = ($profile == self::PROFILE_ADMIN); + $this->USER_IS_ADMINPLUS = ($profile == self::PROFILE_ADMINPLUS); + $this->USER_IS_SUPERADMIN = ($profile == self::PROFILE_SUPERADMIN); + + $this->USER_IS_RESPONSABLE_OR_MORE = ($profile >= self::PROFILE_RESPONSABLE); + $this->USER_IS_ADMIN_OR_MORE = ($profile >= self::PROFILE_ADMIN); + $this->USER_IS_ADMINPLUS_OR_MORE = ($profile >= self::PROFILE_ADMINPLUS); + + // Positionne ces variables pour TOUTES les vues + $this->set('role', $this->userRole); + $this->set('profile', $profile); + $this->set('username', $this->userName); + $this->set('priviledgedUser', $this->priviledgedUser); + + $this->set('USER_IS_UTILISATEUR', $this->USER_IS_UTILISATEUR); + $this->set('USER_IS_ADMIN', $this->USER_IS_ADMIN); + $this->set('USER_IS_ADMINPLUS', $this->USER_IS_ADMINPLUS); + $this->set('USER_IS_SUPERADMIN', $this->USER_IS_SUPERADMIN); + $this->set('USER_IS_RESPONSABLE_OR_MORE', $this->USER_IS_RESPONSABLE_OR_MORE); + $this->set('USER_IS_RESPONSABLE', $this->USER_IS_RESPONSABLE); + //$this->set(compact('USER_IS_ADMIN_OR_MORE')); + $this->set('USER_IS_ADMIN_OR_MORE', $this->USER_IS_ADMIN_OR_MORE); + $this->set('USER_IS_ADMINPLUS_OR_MORE', $this->USER_IS_ADMINPLUS_OR_MORE); + + // (EP) TODO: vraiment utile ??? A virer, non ? + $this->set('PROFILE_USER', self::PROFILE_USER); + $this->set('PROFILE_ADMIN', self::PROFILE_ADMIN); + $this->set('PROFILE_RESPONSABLE', self::PROFILE_RESPONSABLE); + $this->set('PROFILE_ADMINPLUS', self::PROFILE_ADMINPLUS); + $this->set('PROFILE_SUPERADMIN', self::PROFILE_SUPERADMIN); + // $this->set('allProfiles', $this->allProfiles); + $this->set('allProfiles', self::PROFILES); + } // Now, set these constants for all VIEWS - $this->set(compact('configuration')); $this->set(compact('D')); - $this->set('role', $this->userRole); - $this->set('profile', $profile); - $this->set('username', $this->userName); - $this->set('priviledgedUser', $this->priviledgedUser); $this->set('idGmNa', $this->idGmNa); $this->set('idGtNa', $this->idGtNa); - $this->set('USER_IS_UTILISATEUR', $this->USER_IS_UTILISATEUR); - $this->set('USER_IS_ADMIN', $this->USER_IS_ADMIN); - $this->set('USER_IS_ADMINPLUS', $this->USER_IS_ADMINPLUS); - $this->set('USER_IS_SUPERADMIN', $this->USER_IS_SUPERADMIN); - $this->set('USER_IS_RESPONSABLE_OR_MORE', $this->USER_IS_RESPONSABLE_OR_MORE); - $this->set('USER_IS_RESPONSABLE', $this->USER_IS_RESPONSABLE); - //$this->set(compact('USER_IS_ADMIN_OR_MORE')); - $this->set('USER_IS_ADMIN_OR_MORE', $this->USER_IS_ADMIN_OR_MORE); - $this->set('USER_IS_ADMINPLUS_OR_MORE', $this->USER_IS_ADMINPLUS_OR_MORE); - - // (EP) TODO: vraiment utile ??? A virer, non ? - $this->set('PROFILE_USER', self::PROFILE_USER); - $this->set('PROFILE_ADMIN', self::PROFILE_ADMIN); - $this->set('PROFILE_RESPONSABLE', self::PROFILE_RESPONSABLE); - $this->set('PROFILE_ADMINPLUS', self::PROFILE_ADMINPLUS); - $this->set('PROFILE_SUPERADMIN', self::PROFILE_SUPERADMIN); - // $this->set('allProfiles', $this->allProfiles); - $this->set('allProfiles', self::PROFILES); // On autorise certaines actions SANS connexion (ces actions sont donc publiques) // - pour le mode spécial “installation” => on autorise pleins d’actions sans login @@ -796,11 +893,12 @@ class AppController extends Controller // Autoriser TOUTES les actions SANS authentification //$this->LdapAuth->allow(); - $allowed_actions = $this->LdapAuth->allowedActions; - $this->myDebug("- Actions allowed are: ", $allowed_actions); + $this->myDebug("- Actions allowed are: ", $this->LdapAuth->allowedActions); + /* (EP 20200427 migré dans initialize()) + // Message d'erreur en cas de refus de connexion $this->LdapAuth->setConfig('authError', "Désolé, vous n'êtes pas autorisé à accéder à cette zone."); - //exit; + */ } // beforeFilter() @@ -914,25 +1012,25 @@ class AppController extends Controller /* * @todo EP 08/2017 Nouvelle organisation des ACL avec $easyACL */ - $action = $this->getActionPassed(); - if (in_array($action, array( + //$action = $this->getActionPassed(); + if (in_array($this->action, array( 'add', 'edit', 'view', 'index' ))) { - $hiddenFields = $this->getHiddenFieldsForAction($action); + $hiddenFields = $this->getHiddenFieldsForAction($this->action); $this->set('hiddenFields', $hiddenFields); $this->myDebug(compact("hiddenFields")); - if (in_array($action, array( + if (in_array($this->action, array( 'add', 'edit' ))) { - $mandatoryFields = $this->getMandatoryFieldsForAction($action); + $mandatoryFields = $this->getMandatoryFieldsForAction($this->action); $this->set('mandatoryFields', $mandatoryFields); - $readOnlyFields = $this->getReadOnlyFieldsForAction($action); + $readOnlyFields = $this->getReadOnlyFieldsForAction($this->action); $this->set('readOnlyFields', $readOnlyFields); - $haveDefaultValueFields = $this->getDefaultValueFieldsForAction($action); + $haveDefaultValueFields = $this->getDefaultValueFieldsForAction($this->action); // only for DEBUG : //$this->myDebug("mandat, ro, default fields=", $mandatoryFields, $readOnlyFields, $haveDefaultValueFields); diff --git a/src/Controller/MaterielsController.php b/src/Controller/MaterielsController.php index 353dd97..52f2423 100755 --- a/src/Controller/MaterielsController.php +++ b/src/Controller/MaterielsController.php @@ -152,6 +152,7 @@ class MaterielsController extends AppController { $this->myDebug("step 0A (specific): MaterielsController.initialize()"); parent::initialize(); + // On autorise l'action add SANS authentification (unauthenticated) //$this->Auth->allow(['add']); } @@ -169,14 +170,11 @@ class MaterielsController extends AppController public function beforeFilter(\Cake\Event\Event $event) { $this->myDebug("step 1A (specific): MaterielsController.beforeFilter()"); + parent::beforeFilter($event); - // ICI CEST OK - /* - $toto="tititoto"; - $this->set(compact('toto')); - */ + // Si on veut autoriser des actions SANS connexion, suffit de décommenter cette ligne + //$this->LdapAuth->allow([ 'view', 'index' ]); - parent::beforeFilter($event); } @@ -240,7 +238,7 @@ class MaterielsController extends AppController } */ - } + } // beforeRender() @@ -248,7 +246,7 @@ class MaterielsController extends AppController /** * * //param $user - * @param $userFromSession + * @param $user * @return boolean Give authorization for materiels * * On définit ici les actions autorisées ou pas par ce contrôleur spécifique @@ -256,19 +254,25 @@ class MaterielsController extends AppController * CAKEPHP function * */ - public function isAuthorized($userFromSession) { + //public function isAuthorized($userFromSession) { + public function isAuthorized($user) { //if (parent::isAuthorized($userFromSession)) return TRUE; $this->myDebug("step 2A (specific): MaterielsController.isAuthorized(user)"); - $this->myDebug("- user is:", $userFromSession); + $this->myDebug("- user is:", $user); /* ICI C'EST OK $toto="tititoto"; $this->set(compact('toto')); */ - $this->userFromSession = $userFromSession; - $configuration = $this->confLabinvent; + /* + $prefix = $this->request->getParam('prefix'); + $this->myDebug("- prefix is $prefix"); + */ + + $this->userFromSession = $user; + //$configuration = $this->confLabinvent; // ex: 'uid' - $this->userCname = $userFromSession[$configuration->ldap_authenticationType][0]; + $this->userCname = $user[$this->confLabinvent->ldap_authenticationType][0]; /* * $role = TableRegistry::get('Users')->find() * ->where(['username' => $user[$configuration->authentificationType_ldap][0]]) @@ -280,12 +284,15 @@ class MaterielsController extends AppController // $this->myDebug("role is ".$role); // debug("role is ".$role); + // BETTER: // $action = $this->request->getAttribute('params')['action']; // $action = $this->request->getParam('action'); - $action = $this->getActionPassed(); + //$action = $this->getActionPassed(); + // $id = (int) $this->request->getParam('pass.0'); - $id = $this->getIdPassed(); + //$id = $this->getIdPassed(); + ///$this->action_id = $this->getIdPassed(); //debug($id); // ACTIONS QUI SONT TOUJOURS AUTORISÉES QUELQUE SOIT LE PROFIL @@ -307,11 +314,20 @@ class MaterielsController extends AppController return $article->user_id === $user['id']; */ + $id = $this->action_id; + // On autorise ou pas l’action demandée : - // - SUPERADMIN : par défaut il a tous les droits, non mais ! - // (sauf 'edit' si matos validé, pour faire comme pour admin) - if ( $this->userRole=='Super Administrateur' && $action!='edit' ) return true; - /* - Autres cas : on return isAuthorizedAction() + // - SUPERADMIN : par défaut il a TOUS les droits + // (sauf certaines actions afin de lui donner un comportement proche de ADMIN) + if ($this->USER_IS_SUPERADMIN) { + // edit ou add by copy => ssi CREATED + if ( $this->action =='edit' || ($this->action=='add' && $id>0) ) return $this->isCreated($id); + // archivage => admin only + //if ($this->action == 'statusArchived') return false; + // tout le reste => ok + return true; + } + /* - Autres users : on return isAuthorizedAction() * * C’est une fonction interne développée pour labinvent * Elle return true ou false selon que l’action est autorisée ou pas. @@ -323,13 +339,16 @@ class MaterielsController extends AppController * //return $this->isAuthorizedAction($this, $user, $role, $action, $id); * Tout le reste en dessous de cette ligne devient inutile !!! */ - $this->myDebug("isAuthorizedAction ? " . $this->isAuthorizedAction2($this, $this->userRole, $action, $id, $userFromSession)); + $this->myDebug("isAuthorizedAction ? " . $this->isAuthorizedAction2($this, $this->userRole, $this->action, $id, $user)); + return $this->isAuthorizedAction(); + /* return $this->isAuthorizedAction( $this->userRole, - $action, $id, - $userFromSession, + $this->action, $id, + $user, $this->userCname ); + */ } // isAuthorized @@ -340,7 +359,18 @@ class MaterielsController extends AppController * Les 3 niveaux successifs parcourus par cakephp (isAuthorized() puis beforeRender() puis la VUE) font tous appels à cette MEME fonction * On ne définit et modifie les droits qu'ici et nulle part ailleurs, surtout pas dans les vues !!! */ - private function isAuthorizedAction($role, $action, $id, $user, $userCname) { + private function isAuthorizedAction($action = null) { + if (!$action) $action = $this->action; + //$id = $this->getIdPassed(); + //debug("action $action, id $this->action_id"); + //return $this->isAuthorizedActionFor($action, $this->getIdPassed(), $this->userRole, $this->userFromSession, $this->userCname); + return $this->isAuthorizedActionFor( + $action?$action:$this->action, $this->action_id, + $this->userRole, + $this->userFromSession, $this->userCname + ); + } + private function isAuthorizedActionFor($action, $id, $role, $user, $userCname) { /* * Structure mise en place: @@ -365,43 +395,82 @@ class MaterielsController extends AppController // (EP 17/5/19) CREATE (add) BY COPY (add/id) case 'add': + //debug("this is"); debug($this); //debug($id); // add by COPY (il y a un id) => on traite if ($id > 0) { + // ON AUTORISE SEULEMENT LA COPIE D'UN MATOS "CREATED" // not CREATED => pas le droit de copier un materiel pas CREATED if (! $this->isCreated($id)) return FALSE; // CREATED => ok, sous conditions - else { - //debug("copie created"); - //if ($this->isCreated($id) || $this->isValidated($id)) { - /* - * if ($role == 'Utilisateur' && $this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0])) { - * return true; - * } else if ($role == 'Responsable' && $this->isRespGroup($id, $user[$configuration->authentificationType_ldap][0])) { - * return true; - * } else if ($this->userHasRoleAtLeast('Administration')) { - * return true; - * } - */ - switch ($role) { - case 'Utilisateur': - //return $this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0]); - return $this->isHis($id, $user); - break; - case 'Responsable': - return ( $this->isHis($id, $user) || $this->isRespGroup($id, $userCname) ); - default: // All other roles (Admin and more) => OK - return TRUE; - break; - } - } // CREATED + //debug("copie created"); + //if ($this->isCreated($id) || $this->isValidated($id)) { + /* + * if ($role == 'Utilisateur' && $this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0])) { + * return true; + * } else if ($role == 'Responsable' && $this->isRespGroup($id, $user[$configuration->authentificationType_ldap][0])) { + * return true; + * } else if ($this->userHasRoleAtLeast('Administration')) { + * return true; + * } + */ + switch ($role) { + case 'Utilisateur': + //return $this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0]); + return $this->isHis($id, $user); + case 'Responsable': + return ( $this->isHis($id, $user) || $this->isRespGroup($id, $userCname) ); + } + // All other roles (Admin and more) => OK + return TRUE; } // ADD by COPIE break; // ADD - + + // DELETE + case 'delete': + + /* + * (EP) ACL: + * SSi materiel CREATED, autoriser : + * - user : si createur de la fiche ou owner du materiel + * - resp : si responsable du groupe thematique ou metier de ce materiel + * - admin et + : toujours + */ + if ($this->isCreated($id)) { + /* + * if ($role == 'Utilisateur' && $this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0])) { + * return true; + * } else if ($role == 'Responsable' && $this->isRespGroup($id, $user[$configuration->authentificationType_ldap][0])) { + * return true; + * } else if ($this->userHasRoleAtLeast('Administration')) { + * return true; + * } + */ + switch ($role) { + case 'Utilisateur': + //return ($this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0])); + return $this->isHis($id, $user); + break; + case 'Responsable': + return ($this->isRespGroup($id, $userCname)); + break; + // All other roles : Admin and more + default: + return true; + break; + } + } + break; + // UPDATE (edit) // if ($action == 'edit') { case 'edit': + /* + debug("entity is"); debug($this->entity); + $this->getEntity(); + debug("entity is"); debug($this->entity); + */ // BETTER: // $id = (int) $this->request->getAttribute('params')['pass'][0]; // /$id = (int) $this->request->getParam('pass.0'); @@ -424,18 +493,19 @@ class MaterielsController extends AppController */ // (EP 23/5/19) NEW optimization - $materiel = $this->Materiels->get($id, ['contain' => [ - 'SurCategories', - 'Categories', - 'SousCategories', - 'GroupesThematiques', - 'GroupesMetiers', - 'Organismes', - 'Sites', - 'Documents', - 'Emprunts', - 'Suivis', - 'Fournisseurs' + $materiel = $this->Materiels->get($id, [ + 'contain' => [ + 'SurCategories', + 'Categories', + 'SousCategories', + 'GroupesThematiques', + 'GroupesMetiers', + 'Organismes', + 'Sites', + 'Documents', + 'Emprunts', + 'Suivis', + 'Fournisseurs' ] ]); @@ -458,82 +528,16 @@ class MaterielsController extends AppController ($this->USER_IS_RESPONSABLE && $USER_IS_SAME_GROUP_AS_MATERIEL) ); return $CAN_EDIT; + // edit + - // (EP 23/5/19) OLD METHOD - /* - // (EP 17/5/19) ON AUTORISE SEULEMENT LA MODIF D'UN MATOS CREATED - // UN user Admin ou plus ne pourra le modifier qu'à condition de le "dé-valider" avant - if ($this->isCreated($id)) { - //if ($this->isCreated($id) || $this->isValidated($id)) { - /STAR - * if ($role == 'Utilisateur' && $this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0])) { - * return true; - * } else if ($role == 'Responsable' && $this->isRespGroup($id, $user[$configuration->authentificationType_ldap][0])) { - * return true; - * } else if ($this->userHasRoleAtLeast('Administration')) { - * return true; - * } - STAR/ - switch ($role) { - case 'Utilisateur': - //return $this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0]); - return $this->isHis($id, $user); - break; - case 'Responsable': - // return ($this->isRespGroup($id, $user[$configuration->authentificationType_ldap][0])); - //return ($this->isRespGroup($id, $userCname)); - //return ($this->isRespGroup($id, $userCname) || $this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0])); - return ( $this->isHis($id, $user) || $this->isRespGroup($id, $userCname) ); - default: // All other roles (Admin and more) => OK - return TRUE; - break; - } - } - /STAR - (EP 17/5/19) : Ben non, pas le droit, faudra dé-valider avant, non mais !!! - if ($this->userHasRoleAtLeast('Administration Plus')) { - return true; - } - STAR/ - break; // EDIT - */ - - // DELETE - case 'delete': - - /* - * (EP) ACL: - * SSi materiel CREATED, autoriser : - * - user : si createur de la fiche ou owner du materiel - * - resp : si responsable du groupe thematique ou metier de ce materiel - * - admin et + : toujours - */ - if ($this->isCreated($id)) { - /* - * if ($role == 'Utilisateur' && $this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0])) { - * return true; - * } else if ($role == 'Responsable' && $this->isRespGroup($id, $user[$configuration->authentificationType_ldap][0])) { - * return true; - * } else if ($this->userHasRoleAtLeast('Administration')) { - * return true; - * } - */ - switch ($role) { - case 'Utilisateur': - //return ($this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0])); - return $this->isHis($id, $user); - break; - case 'Responsable': - return ($this->isRespGroup($id, $userCname)); - break; - // All other roles : Admin and more - default: - return true; - break; - } - } - break; + case 'export': + // if ($this->userHasRoleAtLeast('Responsable')) { + return $this->USER_IS_RESP_AT_LEAST(); + case 'getDateGarantie': + return true; + case 'statusCreated': // de-validation d'un materiel (repasse à CREATED) // /$id = (int) $this->request->getParam('pass.0'); // Admin + ok @@ -574,21 +578,17 @@ class MaterielsController extends AppController break; case 'statusArchived': + return $this->isToBeArchived($id) && $this->USER_IS_ADMIN_AT_LEAST(); // /$id = (int) $this->request->getAttribute('params')['pass'][0]; // if ($this->userHasRoleAtLeast('Administration')) { // if ($role == 'Super Administrateur') { + /* if ( $this->isToBeArchived($id) && $this->USER_IS_ADMIN_AT_LEAST() ) { if ($this->USER_IS_SUPERADMIN()) return false; return true; } break; - - case 'export': - // if ($this->userHasRoleAtLeast('Responsable')) { - if ($this->USER_IS_RESP_AT_LEAST()) { - return true; - } - break; + */ /* * if (in_array($action, [ @@ -603,11 +603,17 @@ class MaterielsController extends AppController case 'setLabelIsPlaced': case 'setLabelIsPlacedOrNotPlaced': case 'setLabelIsNotPlaced': - case 'printLabelRuban': + return $this->USER_IS_ADMIN_AT_LEAST(); + /* // if ($this->userHasRoleAtLeast('Administration')) { - if ($this->USER_IS_ADMIN_AT_LEAST()) - return true; + if ($this->USER_IS_ADMIN_AT_LEAST()) return true; break; + */ + + case 'printLabelRuban': + $materiel = $this->Materiels->get($id); + $IS_VALIDATED = ($materiel->status == 'VALIDATED'); + return $IS_VALIDATED && $this->confLabinvent->hasPrinter && $this->USER_IS_ADMIN_OR_MORE; /* * // Autorisations par defaut: @@ -621,8 +627,10 @@ class MaterielsController extends AppController // => DEFAULT PARENT RULE // (on appelle la méthode isAuthorized() de AppController) return parent::isAuthorized($user); + } // isAuthorizedAction() + /* * @todo A déplacer dans Model/Table/TableMateriels * cf https://book.cakephp.org/3.0/fr/tutorials-and-examples/blog-auth-example/auth.html @@ -630,6 +638,9 @@ class MaterielsController extends AppController // True if materiel with id $id is owned by $nomCreateur public function isOwnedBy($id, $nomCreateur) { + $entity = $this->getEntity($id); + return in_array($nomCreateur, [$entity->nom_createur, $entity->nom_responsable]); + /* return ($this->Materiels->exists([ 'id' => $id, 'nom_createur' => $nomCreateur @@ -637,6 +648,7 @@ class MaterielsController extends AppController 'id' => $id, 'nom_responsable' => $nomCreateur ])); + */ } // True if materiel with id $id is owned by current user @@ -646,69 +658,69 @@ class MaterielsController extends AppController public function isRespGroup($id, $loginResponsable) { - $userFromTable = TableRegistry::get('Users')->find() - ->where([ - 'username' => $loginResponsable - ]) + // Get user + $u = TableRegistry::getTableLocator()->get('Users') + ->find() + ->where(['username' => $loginResponsable]) ->first(); - $u = $userFromTable; - if ($u['groupes_metier_id'] !== null && $u['groupes_metier_id'] != TableRegistry::get('GroupesMetiers')->find() - ->where([ - 'nom =' => 'N/A' - ]) - ->first()['id']) { - return ($this->Materiels->exists([ - 'id' => $id, - 'groupes_metier_id' => $u['groupes_metier_id'] - ])); - } else if ($u['groupe_thematique_id'] !== null && $u['groupe_thematique_id'] != TableRegistry::get('GroupesThematiques')->find() - ->where([ - 'nom =' => 'N/A' - ]) - ->first()['id']) { - // BETTER: - return ($this->Materiels->exists([ - 'id' => $id, - 'groupes_thematique_id' => $u['groupe_thematique_id'] - ])); - } else { - return false; - } - } - - public function isCreated($id) - { - return $this->Materiels->exists([ - 'id' => $id, - 'status' => 'CREATED' - ]); - } - - public function isValidated($id) - { - return $this->Materiels->exists([ - 'id' => $id, - 'status' => 'VALIDATED' - ]); - } - - public function isToBeArchived($id) - { - return $this->Materiels->exists([ - 'id' => $id, - 'status' => 'TOBEARCHIVED' - ]); - } + // Responsable groupe métier ? + $group = 'groupes_metier'; + $group_fk = $group.'_id'; + if ( + $u[$group_fk] !== null + && + $u[$group_fk] != TableRegistry::getTableLocator()->get('GroupesMetiers') + ->find() + ->where(['nom =' => 'N/A']) + ->first()['id'] + ) return $this->getEntity($id)->$group_fk == $u[$group_fk]; + /* + return $this->Materiels->exists([ + 'id' => $id, + 'groupes_metier_id' => $u['groupes_metier_id'] + ]); + */ + + // Responsable groupe thématique ? + $group = 'groupe_thematique'; + $group_fk = $group.'_id'; + if ( + $u[$group_fk] !== null + && + $u[$group_fk] != TableRegistry::getTableLocator()->get('GroupesThematiques') + ->find() + ->where(['nom =' => 'N/A']) + ->first()['id'] + ) return $this->getEntity($id)->$group_fk == $u[$group_fk]; + /* + return $this->Materiels->exists([ + 'id' => $id, + 'groupes_thematique_id' => $u['groupe_thematique_id'] + ]); + */ + + // sinon, pas responsable de groupe + return false; + + } // isRespGroup + - public function isArchived($id) - { + public function hasStatus($id, $status) { + return $this->getEntity($id)->status == $status; + /* return $this->Materiels->exists([ 'id' => $id, - 'status' => 'ARCHIVED' + 'status' => $status ]); + */ } + public function isCreated($id) { return $this->hasStatus($id, 'CREATED'); } + public function isValidated($id) { return $this->hasStatus($id, 'VALIDATED'); } + public function isToBeArchived($id) { return $this->hasStatus($id, 'TOBEARCHIVED'); } + public function isArchived($id) { return $this->hasStatus($id, 'ARCHIVED'); } + /** * Index method * @@ -924,46 +936,31 @@ class MaterielsController extends AppController $CAN_INVALIDATE = !$IS_CREATED && $CAN_VALIDATE_OR_INVALIDATE; $CAN_TBA = $IS_VALIDATED && $CONTEXT1; $CAN_ARCHIVE = $IS_TOBEARCHIVED && $this->USER_IS_ADMIN_OR_MORE; - $this->set(compact('CAN_VALIDATE')); - $this->set(compact('CAN_INVALIDATE')); - $this->set(compact('CAN_TBA')); - $this->set(compact('CAN_ARCHIVE')); + $this->set(compact('CAN_VALIDATE', 'CAN_INVALIDATE', 'CAN_TBA', 'CAN_ARCHIVE')); $CAN_ATTACH_A_DOC = $CONTEXT1; - $this->set(compact('CAN_ATTACH_A_DOC')); - $CAN_MANAGE_SUIVIS = $CONTEXT1; - $this->set(compact('CAN_MANAGE_SUIVIS')); - $CAN_MANAGE_EMPRUNTS = $CONTEXT1; - $this->set(compact('CAN_MANAGE_EMPRUNTS')); - $CAN_MANAGE_FILES = $CONTEXT1; - $this->set(compact('CAN_MANAGE_FILES')); + $this->set(compact('CAN_ATTACH_A_DOC', 'CAN_MANAGE_SUIVIS', 'CAN_MANAGE_EMPRUNTS', 'CAN_MANAGE_FILES')); // NEW - //TODO: faire la meme chose pour tous les autres $CAN_ - $CAN_EDIT = $this->isAuthorizedAction($this->userRole, 'edit', $id, $this->userFromSession, $this->userCname); + //TODO: faire la meme chose pour tous les $CAN_* + //$CAN_EDIT = $this->isAuthorizedAction($this->userRole, 'edit', $id, $this->userFromSession, $this->userCname); + $CAN_EDIT = $this->isAuthorizedAction('edit'); // OLD //$CAN_EDIT = $IS_CREATED && $CAN_ATTACH_A_DOC; - $this->set(compact('CAN_EDIT')); - $CAN_COPY = $CAN_EDIT; - $this->set(compact('CAN_COPY')); - - $configuration = $this->confLabinvent; - $CAN_PRINT_LABEL = $IS_VALIDATED && $configuration->hasPrinter && $this->USER_IS_ADMIN_OR_MORE; - $this->set(compact('CAN_PRINT_LABEL')); + //$CAN_PRINT_LABEL = $IS_VALIDATED && $this->confLabinvent->hasPrinter && $this->USER_IS_ADMIN_OR_MORE; + //$CAN_PRINT_LABEL = $this->isAuthorizedAction($this->userRole, 'printLabelRuban', $id, $this->userFromSession, $this->userCname); + $CAN_PRINT_LABEL = $this->isAuthorizedAction('printLabelRuban'); + $this->set(compact('CAN_EDIT', 'CAN_COPY', 'CAN_PRINT_LABEL')); // $status = $this->allStatus[$materiel->status]; $status = self::allStatus[$materiel->status]; - $this->set('IS_CREATED', $IS_CREATED); - $this->set('IS_VALIDATED', $IS_VALIDATED); - $this->set('IS_TOBEARCHIVED', $IS_TOBEARCHIVED); - $this->set('IS_ARCHIVED', $IS_ARCHIVED); - $this->set('status', $status); + $this->set(compact('status', 'IS_CREATED', 'IS_VALIDATED', 'IS_TOBEARCHIVED', 'IS_ARCHIVED')); $sites = TableRegistry::getTableLocator()->get('Sites'); //$sites = TableLocator::get('Sites'); @@ -1071,6 +1068,7 @@ class MaterielsController extends AppController //$this->myDebug($materiel); } + /* SI POST * Les données ont été saisies et postées * On va donc les sauvegarder @@ -1227,7 +1225,7 @@ class MaterielsController extends AppController 'valueField' => 'nom', 'order' => 'Sites.nom' ]); - $designation = $this->Materiels->find('list', [ + $designations = $this->Materiels->find('list', [ 'keyField' => 'designation', 'valueField' => 'designation', 'conditions' => array( @@ -1440,7 +1438,7 @@ class MaterielsController extends AppController 'groupesThematiques', 'groupesMetiers', 'organismes', 'sites', 'domaineresp', - 'designation', + //'designations', 'lieu_detail', 'fournisseurs', //'utilisateurs', @@ -1454,6 +1452,7 @@ class MaterielsController extends AppController 'materiel', ]); */ + } //add_or_edit() diff --git a/src/Controller/PagesController.php b/src/Controller/PagesController.php index 6dbd43c..195b96a 100755 --- a/src/Controller/PagesController.php +++ b/src/Controller/PagesController.php @@ -78,44 +78,46 @@ class PagesController extends AppController // (20200424 EP) public function beforeFilter(\Cake\Event\Event $event) { $this->myDebug("step 1A (specific): PagesController.beforeFilter()"); + // On donne d'abord les autorisations par défaut de AppController + parent::beforeFilter($event); + // Puis on ajoute les autorisations spécifiques /* $path = func_get_args(); pr($path); $page = null; if (! empty($path[0])) $page = $path[0]; */ - $page = $this->request->getParam('pass.0'); - - // On autorise l'action display SANS connexion - // mais seulement pour la page 'about' - //if (in_array($path[0], ['about', 'tools'])) echo "yes"; else echo "no"; - if ( $page == 'about' ) $this->LdapAuth->allow(['display']); - //if ( in_array($page, ['about', 'tools']) ) $this->LdapAuth->allow(['display']); + $this->action = $this->getActionPassed(); + if ($this->action == "display") { + $this->page = $this->request->getParam('pass.0'); + + // On autorise l'action display SANS connexion + // mais seulement pour la page 'about' + //if (in_array($path[0], ['about', 'tools'])) echo "yes"; else echo "no"; + if ( $this->page == 'about' ) $this->LdapAuth->allow(['display']); + //if ( in_array($page, ['about', 'tools']) ) $this->LdapAuth->allow(['display']); + } - // Pour le reste, on donne les droits par défaut de AppController - parent::beforeFilter($event); } public function isAuthorized($user) { $this->myDebug("step 2A (specific): PagesController.isAuthorized(user)"); $this->myDebug("- user is:", $user); - $action = $this->getActionPassed(); - - if ($action == 'display') { + if ($this->action == 'display') { - $page = $this->request->getParam('pass.0'); + //$page = $this->request->getParam('pass.0'); // Action display SANS nom de page => on redirige sur '/' // (c'est à dire sur /pages/home, c'est à dire /pages/display/home) // cf config/routes.php qui définit l'action "display" par défaut pour tout ce qui commence par pages/ - if (! $page) { + if (! $this->page) { $this->redirect('/'); return false; } - switch ($page) { + switch ($this->page) { // Page d'accueil autorisée à tous les profils (roles) case 'home': return true; @@ -160,7 +162,7 @@ class PagesController extends AppController // Action display SANS nom de page => on redirige sur '/' // (c'est à dire sur /pages/home, c'est à dire /pages/display/home) // cf config/routes.php qui définit l'action "display" par défaut pour tout ce qui commence par pages/ - $page = $this->request->getParam('pass.0'); + ///$page = $this->request->getParam('pass.0'); /* if (! $page) $this->redirect('/'); */ @@ -177,7 +179,7 @@ class PagesController extends AppController if (! empty($path[1])) $subpage = $path[1]; */ $this->myDebug("- page is:"); - $this->myDebug($page); + $this->myDebug($this->page); $this->myDebug("- subpage is:"); $this->myDebug($subpage); @@ -220,13 +222,14 @@ class PagesController extends AppController */ // Finalement, on affiche la $page demandée (avec render()) - $this->set(compact('page', 'subpage')); + $this->set('page', $this->page); + $this->set(compact('subpage')); //debug(implode('/', $path)); //debug(implode('/', array($page,$subpage))); try { //$this->render(implode('/', $path)); //$this->render("$page/$subpage"); - $this->render($subpage ? "$page/$subpage" : $page); + $this->render($subpage ? $this->page.'/'.$subpage : $this->page); //$this->render(implode('/', array($page,$subpage))); } catch (MissingTemplateException $e) { if (Configure::read('debug')) throw $e; diff --git a/src/Controller/QrCodesController.php b/src/Controller/QrCodesController.php index 2a96751..66d7331 100644 --- a/src/Controller/QrCodesController.php +++ b/src/Controller/QrCodesController.php @@ -7,6 +7,15 @@ use \PHPQRCode\QRcode; class QrCodesController extends AppController { + public function isAuthorized($user) { + return ($this->action == 'creer'); + // Si aucune règle ci-dessus n'a return true (ou false) + // => DEFAULT PARENT RULE + // (on appelle la méthode isAuthorized() de AppController) + //return parent::isAuthorized($user); + } // isAuthorizedAction() + + // @todo Autoriser "creer" dans isAuthorized de ce controleur, et non pas dans celui de AppController !!! public function creer($message = null) { diff --git a/src/Controller/SuivisController.php b/src/Controller/SuivisController.php index 04a7029..5d825c5 100755 --- a/src/Controller/SuivisController.php +++ b/src/Controller/SuivisController.php @@ -29,15 +29,18 @@ class SuivisController extends AppController * ->first()['role']; * $action = $this->request->getAttribute('params')['action']; */ + /* $action = $this->getActionPassed(); $role = $this->getUserRole($user); + */ // if ($this->userHasRoleAtLeast('Administration')) - if ($this->USER_IS_ADMIN_AT_LEAST()) - return true; + if ($this->USER_IS_ADMIN_AT_LEAST()) return true; + + if ($this->action == 'getNextDate') return true; // Pour un "utilisateur" - if (in_array($action, [ + if (in_array($this->action, [ 'edit', 'delete' ])) { @@ -45,9 +48,13 @@ class SuivisController extends AppController $id = $this->getIdPassed(); if ($this->isOwnedBy($id, $user['sn'][0] . ' ' . $user['givenname'][0])) return true; - if ($role == 'Responsable' && $this->isRespGroup($id, $user[$configuration->ldap_authenticationType][0])) + + //if ($role == 'Responsable' && $this->isRespGroup($id, $user[$configuration->ldap_authenticationType][0])) + if ($this->userRole == 'Responsable' && $this->isRespGroup($id, $user[$configuration->ldap_authenticationType][0])) return true; } + + // par défaut : return parent::isAuthorized($user); } diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index ceaf13c..c6f62c3 100755 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -84,12 +84,14 @@ class UsersController extends AppController return parent::isAuthorized($user); } + // ref: https://book.cakephp.org/4/fr/controllers/components/authentication.html#identifier-les-utilisateurs-et-les-connecter public function login() { $this->myDebug("step 2: UsersController.login()"); // Un utilisateur a essayé de se loguer if ($this->request->is('post')) { + // Identification du user en utilisant les données POST // sans LDAP //$user = $this->Auth->identify(); // avec LDAP @@ -100,9 +102,10 @@ class UsersController extends AppController // Le login a été accepté //if ($user != FALSE) { if ($user) { + // Sauvegarde le user dans la session //$this->Auth->setUser($user); - $this->LdapAuth->setUser($user); - // On va maintenant à la page qui etait demandee + $this->LdapAuth->setUser($user); + // On va maintenant à la page qui etait demandée //return $this->redirect($this->Auth->redirectUrl()); return $this->redirect($this->LdapAuth->redirectUrl()); } diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 0ac02b8..1bc8cf0 100755 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -50,7 +50,8 @@ class User extends Entity protected function _setPassword($password) { //return (new DefaultPasswordHasher())->hash($password); - if (strlen($password)) { + //if (strlen($password)) { + if (strlen($password)>0) { $hasher = new DefaultPasswordHasher(); return $hasher->hash($password); } diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 5df180c..68177f6 100755 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -131,6 +131,13 @@ class UsersTable extends AppTable function beforeSave($event, $entity, $options) { + /* + $entity = $event->getData('entity'); + if ($entity->isNew()) { + $hasher = new DefaultPasswordHasher(); + ... + } + */ if (! empty($entity->get('newname')) && ! empty($entity->get('newgivenname'))) { $entity->set('nom', $entity->get('newname') . ' ' . $entity->get('newgivenname')); } diff --git a/src/Template/Layout/default.ctp b/src/Template/Layout/default.ctp index b423dd0..a16811f 100755 --- a/src/Template/Layout/default.ctp +++ b/src/Template/Layout/default.ctp @@ -156,7 +156,10 @@ $this->append('script', $this->Html->script(['script', 'DatepickerConfig', 'onTa Flash->render() ?> - Flash->render('auth') ?> + + + + "; ?> + + + 'Choisir un domaine', //'default' => $Sur_categ_id // ADD only - 'default' => $materiel->sur_categorie_id, + //'default' => $materiel->sur_categorie_id, // EDIT only 'readonly' => $IS_ADD ? false : $isReadonlyField('sur_categorie_id', $myReadonlyFields), 'disabled' => $IS_ADD ? false : $isReadonlyField('sur_categorie_id', $myReadonlyFields) diff --git a/src/Template/Materiels/view.ctp b/src/Template/Materiels/view.ctp index d1e84af..17d6369 100755 --- a/src/Template/Materiels/view.ctp +++ b/src/Template/Materiels/view.ctp @@ -70,6 +70,8 @@ $echoActionButton = $echoActionButton; // Documents attachés photo $photo_formats = ['png','jpg','jpeg']; + + /* (EP) moved to controller function $echoActionButton($html, $icon_class, $title, $action, $id, $tip='', $controller='materiels', $mat=NULL, $photo=NULL) { echo $html->link( diff --git a/tests/TestCase/Controller/MaterielsControllerTest.php b/tests/TestCase/Controller/MaterielsControllerTest.php index e052179..6a0f355 100755 --- a/tests/TestCase/Controller/MaterielsControllerTest.php +++ b/tests/TestCase/Controller/MaterielsControllerTest.php @@ -20,7 +20,8 @@ class MaterielsControllerTest extends General { //class MaterielsControllerTest extends IntegrationTestCase { // Si DEBUG, affiche plus d'infos - private $DEBUG=FALSE; + //private $DEBUG=false; + private $DEBUG=true; /** * Fixtures @@ -142,11 +143,11 @@ class MaterielsControllerTest extends General { $this->get('/materiels/index'); if (! $COPIED) $this->assertResponseNotContains("Liste des matériels (".$nbmat.")", $role); - else { - $this->assertResponseContains("Liste des matériels (".$nbmat.")", $role); - if (isset($designation)) $this->assertResponseContains($designation, "Le matériel ne s'ajoute pas correctement."); - if (isset($num_inventaire)) $this->assertResponseContains($num_inventaire, "La génération du n°de labo n'est pas bonne."); - } + else { + $this->assertResponseContains("Liste des matériels (".$nbmat.")", $role); + if (isset($designation)) $this->assertResponseContains($designation, "Le matériel ne s'ajoute pas correctement."); + if (isset($num_inventaire)) $this->assertResponseContains($num_inventaire, "La génération du n°de labo n'est pas bonne."); + } } @@ -654,10 +655,15 @@ class MaterielsControllerTest extends General { // On doit pouvoir accéder à la page une fois authentifié $this->authAs($role); + $do1=1; + $do2=1; + $do3=1; + $do4=1; + // 1) RULE MATERIEL.COPY.1 : // Copie d'un matos (CREATED) à l'IDENTIQUE (tel quel sans rien changer, // sauf ce qui changera automatiquement: id, numlab) - $this->_testMatCopy(1, true, $role, 1, [], 'TEST-2014-0001'); + if ($do1) $this->_testMatCopy(1, true, $role, 1, [], 'TEST-2014-0001'); // 2) RULE MATERIEL.COPY.2 : // Copie d'un matos (CREATED) en changeant quelques données @@ -676,17 +682,19 @@ class MaterielsControllerTest extends General { //'email_responsable' => 'Jacques.Utilisateur@irap.omp.eu', //'fournisseur_id' => 2 ]; - $this->_testMatCopy(2, true, $role, 1, $modified_data, 'TEST-2016-0015'); + if ($do2) $this->_testMatCopy(2, true, $role, 1, $modified_data, 'TEST-2016-0015'); // 3) RULE MATERIEL.COPY.3 : + // Impossible de copier un matos de statut superieur à CREATED (même pas pour SUPERADMIN) + $do3 && $this->_testMatCopy(3, false, $role, 3); // Impossible de copier un matos de statut superieur à CREATED (sauf pour SUPERADMIN) - $this->_testMatCopy(3, $role=="SUPER", $role, 3); + //if ($do3) $this->_testMatCopy(3, $role=="SUPER", $role, 3); // 4) RULE MATERIEL.COPY.4 : // Pour un USER: Impossible de copier un matos CREATED dont je ne suis pas propriétaire // Pour les autres, c'est ok //$this->_testMatCopy(4, !in_array($role, ["USER", "USER_from_ldap"]), $role, 2); - $this->_testMatCopy(4, !$this->USER_IS_USER(), $role, 2); + if ($do4) $this->_testMatCopy(4, !$this->USER_IS_USER(), $role, 2); } @@ -714,7 +722,7 @@ class MaterielsControllerTest extends General { // APRES add $this->_checkNbMaterielInIndexViewIs($COPIED, $role, $nbmat, $designation, $num_inventaire); - /* +/* $this->get('/materiels/index'); // VOIR LE HTML DE LA PAGE WEB //var_dump($this->_getBodyAsString()); -- libgit2 0.21.2