self::PROFILE_USER, 'Responsable' => self::PROFILE_RESPONSABLE, 'Administration' => self::PROFILE_ADMIN, 'Administration Plus' => self::PROFILE_ADMINPLUS, 'Super Administrateur' => self::PROFILE_SUPERADMIN ]; // Current priviledged USER (if so, otherwise = NULL) private $CURRENT_PRIVILEDGED_USER = null; // Current ROLE (by default = "Utilisateur") private $CURRENT_ROLE = null; // EP 08/2017 // protected $easyACL = array( const easyACL = array( /** * Default ACL for ALL (logged) users * * Les actions non mentionnées sont accessibles à tous (par défaut), * exemple 'find', 'index'... * Ces default ACL peuvent être surchargées pour un profil précis * (par exemple pour 'USER' qui est plus restreint) */ // 'ALL' => array ( 'DEFAULT' => array( // 'action' => 'condition for execution' (= 'Y', 'N', or ''), // with like "'field name' == 'value'" // !!! Used for test, DO NOT REMOVE : !!! 'action_CAS4_Y' => 'Y', 'action_CAS4_N' => 'N' // YOUR RULES : // CRUD actions : // 'edit' => 'N', // update // 'delete' => 'N', ), // Ajoute des ACL plus spécifiques (ci-dessus) pour le profil USER qui est plus restreint // Les actions absentes ne sont pas surchargées (elles sont exécutées selon les conditions définies pour 'ALL') 'USER' => array( // !!! Used for test, DO NOT REMOVE : !!! 'action_CAS3_Y' => 'Y', 'action_CAS3_N' => 'N', // YOUR RULES : // CRUD actions 'add' => 'Y', // C 'index' => 'Y', // R all 'view' => 'Y', // R one // 'edit' => 'N', // U 'edit' => 'is_creator', // is_creator = (nom_createur == CURRENT_USER_NAME) 'delete' => 'N', // D // OTHER actions 'find' => 'Y' // create /* * ceci n'a aucun sens car l'action sur le modèle "Pages" s'appelle toujours "display" (et non pas tools, infos, ou printers...) * 'tools' => 'N', * 'infos' => 'N', * 'printers' => 'N', */ ), // Surcharge des ACL par défaut (ci-dessus) pour le profil RESPONSABLE qui est plus restreint // Les actions absentes ne sont pas surchargées (elles sont exécutées selon les conditions définies pour 'ALL') 'RESPONSABLE' => array(), // Surcharge des ACL par défaut (ci-dessus) pour le profil ADMIN 'ADMIN' => array( // 'add' => 'Y', // create 'edit' => 'Y' // update // 'delete' => 'Y', // update ), // Surcharge des ACL par défaut (ci-dessus) pour le profil ADMINPLUS 'ADMINPLUS' => array( // 'edit' => 'Y', // update ), // Surcharge des ACL par défaut (ci-dessus) pour le profil SUPERADMIN 'SUPERADMIN' => array( // 'add' => 'Y', // create // 'edit' => 'Y', // update 'delete' => 'Y' ) ); // $easyACL // if (isset($this->easyACL['DEFAULT'][$action])) { public function hasACLRule($easyACL, $role, $action) { // return isset($this->easyACL[$role][$action]); // return (null !== self::easyACL[$role][$action]); // return array_key_exists($role, self::easyACL) && array_key_exists($action, self::easyACL[$role]); return array_key_exists($role, $easyACL) && array_key_exists($action, $easyACL[$role]); } // @todo public function startsWith($haystack, $needle) { return strpos($haystack, $needle) === 0; } /* * //@todo * public function endsWith($haystack, $needle) { * return strpos($haystack, $needle, strlen($haystack)-1) === 0; * } */ public function evalACL($condition) { return $condition; // Simple case if ($condition == 'Y') return true; if ($condition == 'F') return false; // Complex case // @todo return true; } public function evalSpecificRule($condition, AppController $controller, $user, $role, $action, $id = null) { // if starts with "&&" eval DEFAULT rule && specific rule if ($this->startsWith($condition, '&&')) { //debug($condition); //if (! isset($controller::easyACL['DEFAULT'][$action])) return new \Exception('bad rule'); if (! array_key_exists($action, $controller::easyACL['DEFAULT']) ) return new \Exception('bad rule'); //return $this->evalACL($controller->easyACL['DEFAULT'][$action]) && $this->evalACL($condition); return $this->evalACL($controller::easyACL['DEFAULT'][$action]).' ' . $this->evalACL($condition); } // otherwise, eval only specific rule return $this->evalACL($condition); } /** * * @param AppController $controller * // a subclass of AppController (MaterielsController or any other) * @param array $user * @param string $role * @param string $action * @param string $id */ // public function isAuthorizedAction(AppController $controller, $roleLong, $action, $id=null, $user=null) { public function isAuthorizedAction2($controller, $roleLong, $action, $id = null, $user = null) { /* Cette fonction n'est pas encore appelée pour de vrai, juste pour test, donc inutile d'afficher ça : $this->myDebug("step 2B (intermediaire general): AppController.isAuthorizedAction2(controller, $roleLong, $action, $id, user)"); $this->myDebug("- controller name is {$controller->name}"); */ //$this->myDebug("- user is ", $user); $doDEBUG = true; $doDEBUG = false; switch ($roleLong) { case 'Utilisateur': $role = 'USER'; break; case 'Responsable': $role = 'RESPONSABLE'; break; case 'Administration': $role = 'ADMIN'; break; case 'Administration Plus': $role = 'ADMINPLUS'; break; case 'Super Administrateur': $role = 'SUPERADMIN'; break; } if ($doDEBUG) debug("role is $role"); // 1) SPECIFIC controller SPECIFIC (role) rule for action // if (isset($controller->easyACL[$role][$action])) { if (self::hasACLRule($controller::easyACL, $role, $action)) { if ($doDEBUG) debug("CAS1"); return $this->evalSpecificRule($controller::easyACL[$role][$action], $controller, $user, $role, $action); } // 2) SPECIFIC controller DEFAULT rule for action // if (null !== $controller::easyACL['DEFAULT'][$action]) { if (self::hasACLRule($controller::easyACL, 'DEFAULT', $action)) { if ($doDEBUG) debug("CAS2"); return $this->evalACL($controller::easyACL['DEFAULT'][$action]); } // 3) ALL controllers (AppController) SPECIFIC (role) rule for action // if (isset($this->easyACL[$role][$action])) { if (self::hasACLRule(self::easyACL, $role, $action)) { if ($doDEBUG) debug("CAS3"); return $this->evalSpecificRule(self::easyACL[$role][$action], $this, $user, $role, $action); } // 4) ALL controllers (AppController) DEFAULT rule for action // if (isset($this->easyACL['DEFAULT'][$action])) { // if (self::hasACLRule('DEFAULT',$action)) { if (self::hasACLRule(self::easyACL, 'DEFAULT', $action)) { if ($doDEBUG) debug("CAS4"); return $this->evalACL(self::easyACL['DEFAULT'][$action]); // return $this->evalACL(parent::getACLRule('DEFAULT',$action)); } /* * (RECURSIVE CALL) * 5) SPECIFIC controller PREVIOUS SPECIFIC (role) rule for action * ex: if role is 'SUPER', use 'ADMIN' rule * ex: if role is 'ADMIN', use 'RESP' rule * ex: if role is 'RESP', use 'USER' rule * ex: if role is 'USER', stop recursive call * Stop recursive call if role is 'USER' => no rule found, so DEFAULT IS AUTHORIZE (Y) !!! => permissive ACL */ // if ($role == 'USER') return true; if ($role == 'USER') { if ($doDEBUG) debug("CAS5"); return 'Y'; } if ($doDEBUG) debug("CAS6"); return $this->isAuthorizedAction2($controller, $this->getPreviousRole($role), $action, $id, $user); } // @todo public function getMandatoryFieldsForAction($action) { $fields = []; // meme fonctionnement recursif que isAuthorizedAction() ci-dessus return $fields; } // @todo public function getHiddenFieldsForAction($action) { $fields = []; // meme fonctionnement recursif que isAuthorizedAction() ci-dessus return $fields; } // @todo public function getReadOnlyFieldsForAction($action) { $fields = []; // meme fonctionnement recursif que isAuthorizedAction() ci-dessus return $fields; } // @todo public function getDefaultValueFieldsForAction($action) { $fields = []; // meme fonctionnement recursif que isAuthorizedAction() ci-dessus return $fields; } public static function getRoleLevel($role) { // return $this->allProfiles[$role]; // debug("role is" .$role); return self::PROFILES[$role]; } public static function getPreviousRole($role) { switch ($role) { /* * case 'RESPONSABLE': $rolePrev='USER'; break; * case 'ADMIN': $rolePrev='RESPONSABLE'; break; * case 'ADMINPLUS': $rolePrev='ADMIN'; break; * case 'SUPERADMIN': $rolePrev='ADMINPLUS'; break; */ case 'RESPONSABLE': $rolePrev = 'Utilisateur'; break; case 'ADMIN': $rolePrev = 'Responsable'; break; case 'ADMINPLUS': $rolePrev = 'Administration'; break; case 'SUPERADMIN': $rolePrev = 'Administration Plus'; break; } return $rolePrev; } public function getActionPassed() { // BETTER: // return $this->request->getAttribute('params')['action']; return $this->request->getParam('action'); } public function getIdPassed() { // return (int) $this->request->getAttribute('params')['pass'][0]; return (int) $this->request->getParam('pass.0'); } /* (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 * */ 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 /* debug("model2"); $model = $this->$model; debug($model); */ //ex: if (! $this->entity) $this->entity = $this->Materiels->get($this->action_id); if (! $this->entity) $this->entity = $this->$model->get($this->action_id); /* * Avec les entités associées : if (! $this->entity) $this->entity = $this->$model->get($this->action_id, [ 'contain' => ['Comments'] ]); */ //debug($this->entity); return $this->entity; } /** * (EP) * Autorisations PAR DÉFAUT * Appelé à la fin de isAuthorized() de chaque controller si cette fonction n'a pas return true */ public function isAuthorizedCommons($user) { $this->myDebug("step 2B (intermediaire general): AppController.isAuthorizedCommons(user)"); $action = $this->getActionPassed(); //$this->myDebug("action iss: $action", null, true); $this->myDebug("- action is: $action"); // $role = $this->getUserRole($user); // 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; */ // 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 : return AppController::isAuthorized($user); } /** * * @param $user * @return boolean isAuthorized is located in the Auth component * Check whether a LOGGED in user has a set of permissions to perform a given action * Give authorization in general * * 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); /* * // ATTENTION, normalement, on devrait tester si role est défini..., mais c'est sans doute pas utile * // cf https://book.cakephp.org/3.0/fr/tutorials-and-examples/blog-auth-example/auth.html * if (isset($user['role']) && $user['role'] === 'admin') { * return true; * } */ //$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 " . $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(); // error_log($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; 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, par défaut => accès refusé (denied) return false; } // isAuthorized() // (EP) Used by Materiels and Users Controllers protected function setUsersLists() { // On recup tous les users du LDAP (ou fakeLDAP si on n'est pas en mode LDAP) //$users = TableRegistry::get('LdapConnections')->getListUsers(); //sort($users); $users_login_and_email = TableRegistry::getTableLocator()->get('LdapConnections')->getUsersLoginAndEmail(); $users_name = array_keys($users_login_and_email); // Formatage en $users_option_list["Etienne Pallier"] = "Etienne Pallier" ... $users_option_list = []; for ($i = 0; $i < sizeof($users_name); $i ++) $users_option_list[$users_name[$i]] = $users_name[$i]; $this->set(compact( 'users_option_list', 'users_login_and_email' )); return $users_name; } public function getTablePriviledgedUserFromCurrentSessionUserIfExists($user = null) { if (! $this->CURRENT_PRIVILEDGED_USER) { $configuration = $this->confLabinvent; $username = $user ? $user[$configuration->ldap_authenticationType][0] : $this->LdapAuth->user($configuration->ldap_authenticationType)[0]; $priviledgedUser = TableRegistry::getTableLocator()->get('Users')->find() ->where([ 'username' => $username ]) -> // ->where(['username' => $this->LdapAuth->user('cn')[0]]) first(); // if (! $priviledgedUser) $priviledgedUser = "Unpriviledged User (not in table utilisateurs)"; $this->CURRENT_PRIVILEDGED_USER = $priviledgedUser; } return $this->CURRENT_PRIVILEDGED_USER; } public function getUserRole($user = null) { if (! $this->CURRENT_ROLE) { $priviledgedUser = $this->getTablePriviledgedUserFromCurrentSessionUserIfExists($user); // default role is "Utilisateur" (for people who are not in the table utilisateurs) $this->CURRENT_ROLE = ($priviledgedUser) ? $priviledgedUser['role'] : 'Utilisateur'; } return $this->CURRENT_ROLE; } private function userHasRole($expectedRole, $ORMORE = false) { $role = $this->getUserRole(); if (! $ORMORE) return ($role == $expectedRole); return ($this->getRoleLevel($role) >= $this->getRoleLevel($expectedRole)); /* * //$hasRole = false; * switch ($expectedRole) { * case 'Super Administrateur' : * return (in_array($role, ['Super Administrateur'])); * break; * case 'Administration Plus' : * return (in_array($role, ['Administration Plus', 'Super Administrateur'])); * break; * case 'Administration' : * return (in_array($role, ['Administration', 'Administration Plus', 'Super Administrateur' ])); * break; * case 'Responsable' : * return (in_array($role, ['Responsable', 'Administration', 'Administration Plus', 'Super Administrateur'])); * break; * case 'Utilisateur' : * return (in_array($role, ['Utilisateur', 'Responsable', 'Administration', 'Administration Plus', 'Super Administrateur'])); * break; * } * return $false; */ } public function userHasRoleAtLeast($expectedRole) { return $this->userHasRole($expectedRole, true); } public function USER_IS_ADMIN_AT_LEAST() { return $this->userHasRoleAtLeast('Administration'); } public function USER_IS_RESP_AT_LEAST() { return $this->userHasRoleAtLeast('Responsable'); } public function USER_IS_SUPERADMIN() { return $this->userHasRole('Super Administrateur'); } public function USER_IS_ADMIN() { return $this->userHasRole('Administration'); } public function USER_IS_RESP() { return $this->userHasRole('Responsable'); } public function USER_IS_USER() { 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} * * @see \Cake\Controller\Controller::beforeFilter() * 1) Autorisations SANS (ou AVANT) connexion * 2) Ensuite, c'est isAuthorized qui gère * * Cette méthode est appelée pendant l’event Controller.initialize qui se produit * AVANT chaque action du controller. * C’est un endroit pratique pour vérifier le statut d’une session ou les permissions d’un utilisateur. * ATTENTION: cette méthode sera appelée pour les actions manquantes. * */ 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"); $passedArgs = $this->request->getParam('pass'); $this->myDebug("- args passed : ", $passedArgs); $query = $this->request->getQueryParams(); $this->myDebug("- query passed : ", $query); // 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: * if (isset($this->Auth)) { * $this->Auth->allow('*'); * } * // Allow access to index & view actions: * if (isset($this->Auth)) { * $this->Auth->allowedActions = array('index', 'view'); * } */ // (EP 21/5/19) NEW $configuration = $this->confLabinvent; $D = $configuration->mode_debug; //$this->myDebug($configuration); // TODO: (EP) A quoi ça sert ??? $this->request->getSession()->write("authType", $configuration->ldap_authenticationType); // 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('idGmNa', $this->idGmNa); $this->set('idGtNa', $this->idGtNa); // On autorise certaines actions SANS connexion (ces actions sont donc publiques) // - pour le mode spécial “installation” => on autorise pleins d’actions sans login // - pour le mode normal habituel => on autorise seulement l’action “display” pour quelques pages publiques (comme la page “about”) //$configuration = $this->confLabinvent; if ($configuration->mode_install) $this->LdapAuth->allow([ 'display', 'add', 'edit', 'installOff' ]); /* // Seule l'action display() est autorisée SANS authentification // (mais PagesController.display() va restreindre ça seulement à la page about) else $this->LdapAuth->allow(['display']); */ // Autoriser TOUTES les actions SANS authentification //$this->LdapAuth->allow(); $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."); */ } // beforeFilter() public function afterFilter(Event $event) { $this->myDebug("step ?? (general): AppController.afterFilter()"); if (in_array($this->request->getAttribute('params')['action'], [ 'edit', 'add' ])) $this->request->getSession()->write("retourForm1", true); else if ($this->request->getAttribute('params')['action'] != 'creer') $this->request->getSession()->write("retourForm1", false); //exit; } /** * Before render callback. * * @param \Cake\Event\Event $event * The beforeRender event * @return void */ public function beforeRender(Event $event) { // TODO: ? // cf https://book.cakephp.org/4/en/views/themes.html //$this->viewBuilder()->setTheme('Modern'); // this theme would be found in plugins/Modern/templates $this->myDebug("step 4B (general) : AppController.beforeRender() - [step 3 = action() si existe]"); // (EP 23/5/19) moved to beforeFilter() /* $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); */ // Ca sert à quoi ??? if (! array_key_exists('_serialize', $this->viewVars) && in_array($this->response->type(), [ 'application/json', 'application/xml' ])) $this->set('_serialize', true); // (EP 21/5/19) moved to beforeFilter() //$this->set('username', $this->LdapAuth->user('sn')[0] . ' ' . $this->LdapAuth->user('givenname')[0]); // moved to beforeFilter() // TODO: (EP) A quoi ça sert ??? /* $configuration = $this->confLabinvent; $this->set('configuration', $configuration); $this->request->getSession()->write("authType", $configuration->ldap_authenticationType); */ // moved to beforeFilter() //$priviledgedUser = $this->getTablePriviledgedUserFromCurrentSessionUserIfExists(); /* * $user = TableRegistry::getTableLocator()->get('Users')->find() * ->where(['username' => $this->LdapAuth->user($configuration->authentificationType_ldap)[0]]) * ->first(); * $role = $user['role']; * if ($role == null) * $role = 'Utilisateur'; */ // Role = 'Utilisateur', 'Responsable", ... // (EP 21/5/19) moved to beforeFilter() /* $role = $this->getUserRole(); $this->set('role', $role); */ // Profile = PROFILE_USER (=1), PROFILE_RESPONSABLE (=2), ... // $profile = $this->allProfiles["$role"]; // (EP 21/5/19) moved to beforeFilter() /* $profile = self::PROFILES["$role"]; $this->set('profile', $profile); */ // (EP 21/5/19) moved to beforeFilter() /* $USER_IS_UTILISATEUR = ($profile == self::PROFILE_USER); $USER_IS_ADMIN = ($profile == self::PROFILE_ADMIN); $USER_IS_ADMINPLUS = ($profile == self::PROFILE_ADMINPLUS); $USER_IS_SUPERADMIN = ($profile == self::PROFILE_SUPERADMIN); $USER_IS_RESPONSABLE_OR_MORE = ($profile >= self::PROFILE_RESPONSABLE); $USER_IS_RESPONSABLE = ($profile == self::PROFILE_RESPONSABLE); $USER_IS_ADMIN_OR_MORE = ($profile >= self::PROFILE_ADMIN); $USER_IS_ADMINPLUS_OR_MORE = ($profile >= self::PROFILE_ADMINPLUS); $this->set('USER_IS_UTILISATEUR', $USER_IS_UTILISATEUR); $this->set('USER_IS_ADMIN', $USER_IS_ADMIN); $this->set('USER_IS_ADMINPLUS', $USER_IS_ADMINPLUS); $this->set('USER_IS_SUPERADMIN', $USER_IS_SUPERADMIN); $this->set('USER_IS_RESPONSABLE_OR_MORE', $USER_IS_RESPONSABLE_OR_MORE); $this->set('USER_IS_RESPONSABLE', $USER_IS_RESPONSABLE); $this->set(compact('USER_IS_ADMIN_OR_MORE')); $this->set('USER_IS_ADMINPLUS_OR_MORE', $USER_IS_ADMINPLUS_OR_MORE); $this->set('priviledgedUser', $priviledgedUser); */ /* * @todo EP 08/2017 Nouvelle organisation des ACL avec $easyACL */ //$action = $this->getActionPassed(); if (in_array($this->action, array( 'add', 'edit', 'view', 'index' ))) { $hiddenFields = $this->getHiddenFieldsForAction($this->action); $this->set('hiddenFields', $hiddenFields); $this->myDebug(compact("hiddenFields")); if (in_array($this->action, array( 'add', 'edit' ))) { $mandatoryFields = $this->getMandatoryFieldsForAction($this->action); $this->set('mandatoryFields', $mandatoryFields); $readOnlyFields = $this->getReadOnlyFieldsForAction($this->action); $this->set('readOnlyFields', $readOnlyFields); $haveDefaultValueFields = $this->getDefaultValueFieldsForAction($this->action); // only for DEBUG : //$this->myDebug("mandat, ro, default fields=", $mandatoryFields, $readOnlyFields, $haveDefaultValueFields); $this->set(compact('haveDefaultValueFields')); //$mandatoryFields = array("un"=>"mand", "deux"=>"alkjl"); $this->myDebug(compact("mandatoryFields")); $this->myDebug(compact("readOnlyFields")); $this->myDebug(compact("haveDefaultValueFields")); } } // Moved to beforeFilter() /* $this->set('idGmNa', TableRegistry::getTableLocator()->get('GroupesMetiers')->find() ->where([ 'nom =' => 'N/A' ]) ->first()['id']); $this->set('idGtNa', TableRegistry::getTableLocator()->get('GroupesThematiques')->find() ->where([ 'nom =' => 'N/A' ]) ->first()['id']); */ // Pass this function to all views $mydebug = function($debugmode, $arg, $stop=false) { if ($debugmode) { // Absolument nécessaire sur inventirap (à cause de php 5 ?) // car sinon, aucun vardump() ou debug() ne s'affiche, why ???... //Configure::write('debug', true); debug($arg); if ($stop) exit(); } }; $this->set(compact('mydebug')); // Pass this function to all views $displayElement = function ($nom, $valeur, $params = "") { $TD = ($params=="") ? 'TD' : "TD $params"; //$TD = ($params=="") ? '' : ''; //$tdstyle = $params!="" ? $params : ''; // Ca c'est parce que sinon y'a au moins deux tests qui passent pas, a cause de l'espace dans la balise ... //if ($valeur != "") echo ' '.$nom.' ' . $TD.$valeur.''; //if ($valeur != "") echo '' . $nom . ' ' . $balise . $valeur . ''; if ($valeur!="") echo " $nom <$TD>$valeur "; }; $printTableRow = $displayElement; $this->set(compact('printTableRow')); //@deprecated $this->set('displayElement', $displayElement); // Pass this function to all views // @todo : Si cette fonction ne concerne que SuivisController, il faut la déplacer dans ce controleur $dateProchainControleVerif = function ($t) { $time = Time::now(); // On récupère la date et l'heure actuelles $today = new \DateTime((new date("$time->year-$time->month-$time->day"))->format('Y-m-d')); $time1 = new time($t); $dateTime1 = new \DateTime((new date("$time1->year-$time1->month-$time1->day"))->format('y-m-d')); $interval = ($today->diff($dateTime1)); $strInterval = $interval->format('%a'); return (int) $strInterval; }; $this->set('dateProchainControleVerif', $dateProchainControleVerif); // Pass this function to all views //function echoActionButton($html, $icon_class, $title, $action, $id, $tip='', $controller='materiels', $mat=NULL, $photo=NULL) { //$echoActionButton = function($html, $icon_class, $buttonStyle='', $title, $controller='', $action, $id, $other_args=[], $tip='', $confirmMessage='') { $getActionButton = function($html, $icon_class, $buttonStyle, $title, $controller, $action, $id, $other_args=[], $tip='', $confirmMessage='', $moreButtonStyle='') { if ($controller=='') $controller='materiels'; $controllerArgs = []; $controllerArgs['controller'] = $controller; $controllerArgs['action'] = $action; $controllerArgs[] = $id; foreach ($other_args as $other_arg) $controllerArgs[] = $other_arg; return $html->link( __("$title"), $controllerArgs, /* [ 'controller' => $controller, 'action' => $action, $id, $other_args ], */ [ 'title' => $tip, 'escape' => false, 'onclick' => 'return true;', //'style' => 'margin-right: 10px'.$moreButtonStyle, 'style' => $buttonStyle, 'confirm' => $confirmMessage ] ); }; $echoActionButton = function($html, $icon_class, $buttonStyle, $title, $controller, $action, $id, $other_args=[], $tip='', $confirmMessage='', $moreButtonStyle='') { if ($controller=='') $controller='materiels'; $controllerArgs = []; $controllerArgs['controller'] = $controller; $controllerArgs['action'] = $action; $controllerArgs[] = $id; foreach ($other_args as $other_arg) $controllerArgs[] = $other_arg; echo $html->link( __("$title"), $controllerArgs, /* [ 'controller' => $controller, 'action' => $action, $id, $other_args ], */ [ 'title' => $tip, 'escape' => false, 'onclick' => 'return true;', //'style' => 'margin-right: 10px'.$moreButtonStyle, 'style' => $buttonStyle, 'confirm' => $confirmMessage ] ); }; $this->set(compact('getActionButton', 'echoActionButton')); // Pass this function to all views (en fait, seulement add.ctp et edit.ctp) //function echoSubmitButtons($context, $matos_id) { // $action : 'view' or 'index' //$echoSubmitButtons = function($context, $action, $matos_id=null, $controller=null) { $echoSubmitButtons = function($context, $action, $matos_id=null, $controller=null) { // - Bouton Enregistrer echo '
'; //echo '
'; echo "\n"; echo $context->Form->input('Enregistrer', ['type'=>'submit', 'value'=>'Submit', 'class'=>'btn btn-primary']); //echo $context->Form->button(('Annuler'), ['action' => 'view', $matos_id], ['escape' => false,'onclick' => 'return true;','style' => 'margin-right: 10px']); //echo $context->Html->link(__('Annuler'), ['action' => 'view', $matos_id], ['class' => 'btn btn-info ', 'escape' => false]); echo "\n"; //echo '
'; $action_params = ['action'=>$action, $matos_id]; if ($controller) $action_params['controller'] = $controller; //echo $context->Html->link(__('Annuler'), [$controller, 'action'=>$action, $matos_id], ['class'=>'btn btn-outline-dark btn-sm', 'style'=>"text-decoration:none;", 'escape'=>false]); echo $context->Html->link(__('Annuler'), $action_params, ['class'=>'btn btn-outline-dark btn-sm', 'style'=>"text-decoration:none;", 'escape'=>false]); //echo '
'; echo "\n"; echo '
'; /* //echo $this->Form->submit(__('Enregistrer')); echo $context->Form->button('Enregistrer', ['class'=>'btn btn-outline-success', 'type'=>'submit']); // - Bouton Cancel //echo $this->Html->link(__(' Annuler'), ['action' => 'view', $materiel->id], ['escape' => false,'onclick' => 'return true;','style' => 'margin-right: 10px']); echo $context->Form->button(('Annuler'), ['action' => 'view', $matos_id], ['escape' => false,'onclick' => 'return true;','style' => 'margin-right: 10px']); //echo ''; //echo 'Cancel'; */ //} }; $this->set(compact('echoSubmitButtons')); } // beforeRender() // "le materiel", "le suivi"... protected function getArticle() { return "Le "; } static function isLabinventDebugMode() { return TableRegistry::getTableLocator()->get('Configurations')->find()->first()->mode_debug; /* return TableRegistry::getTableLocator()->get('Configurations')->find() ->where([ 'id =' => 1 ]) ->first()->mode_debug; */ } function myDebug($arg1, $arg2=null, $stop=false) { if ($this->isLabinventDebugMode()) { // Absolument nécessaire sur inventirap (à cause de php 5 ?) // car sinon, aucun vardump() ou debug() ne s'affiche, why ???... Configure::write('debug', true); debug($arg1); if ($arg2) debug($arg2); if ($stop) exit(); } } /** * Envoi un mail avec un sujet, contenant un message à destination d'une liste de mails, selon l'action effectuée. * * @param $entity : * L'entité concernée (principalement un Matériel, mais ça peut aussi etre un Document) * @param $subject : * Sujet du message à envoyer. Si $subject n'est pas renseigné, un sujet par défaut sera généré. * @param $msg : * Message à envoyer. Si $msg n'est pas renseigné, un message par défaut sera généré. */ public function sendEmail($entity, $subject=null, $msg=null) { /* * $_SESSION['Auth']['User'] pour retrouver TOUTES les infos de la session courante (tout est du string) : * nom $_SESSION['Auth']['User']['sn'][0] * prenom $_SESSION['Auth']['User']['givenname'][0] * mail $_SESSION['Auth']['User']['mail'][0] * login $_SESSION['Auth']['User']['xxx'][0] /!\ Ce champ est suceptible de changer de nom, dans les tests ce champ est ['cn'][0] * mdp $_SESSION['Auth']['User']['userpassword'][0] */ $configuration = $this->confLabinvent; $action = $this->request->getAttribute('params')['action']; // add or edit or delete or ... // Si les deux cases "Activer l'envoi des mails.." sont décochées, on se fatigue pas à exécuter la fonction if (! $configuration->envoi_mail && ! $configuration->envoi_mail_guests) return null; $mailList = array(); // On détermine le message et le sujet du mail en fonction de l'action effectuee $acteur = $_SESSION['Auth']['User']['givenname'][0] . ' ' . $_SESSION['Auth']['User']['sn'][0]; // if ($entity != null) { if ($entity instanceof Materiel) { $materiel = $entity; $nom_materiel = $materiel->designation; if ($subject==null && $msg==null) { $msgMore = ''; Switch ($action) { case 'add': $subject = "Ajout d'un matériel"; $msg = "$acteur a ajouté le matériel \"$nom_materiel\""; break; // case 'edit': //$subject = "Modification d'un matériel"; //$msg = "$acteur a modifié le matériel \"$nom_materiel\""; // break; case 'delete': $subject = "Suppression d'un matériel"; $msg = "$acteur a supprimé le matériel \"$nom_materiel\""; // @todo: mettre le nom des domaine, categ, et sous-categ, et non pas l'id if ($materiel->sur_categorie_id != "") $msgMore .= "\n\nDomaine : " . $materiel->sur_categorie_id; if ($materiel->categorie_id != "") $msgMore .= "\n\nCatégorie : " . $materiel->categorie_id; if ($materiel->sous_categorie_id != "") $msgMore .= "\n\nSous-catégorie : " . $materiel->sous_categorie_id; if ($materiel->description != "") $msgMore .= "\n\nDescription :\n" . $materiel->description; break; //case 'statusCreated': //$subject = "Dé-validation d'un matériel"; //$msg = "$acteur a dé-validé le matériel \"$nom_materiel\""; // break; //case 'statusValidated': //$subject = "Validation d'un matériel"; //$msg = "$acteur a validé le matériel \"$nom_materiel\""; // break; case 'statusToBeArchived': $subject = "Demande d'archivage d'un matériel"; $msg = "$acteur a demandé l'archivage du matériel \"$nom_materiel\""; break; case 'statusArchived': $subject = "Archivage d'un matériel"; $msg = "$acteur a archivé le matériel \"$nom_materiel\""; break; case 'setLabelIsPlaced': $subject = "Etiquette posée sur un matériel"; $msg = "Etiquette posée sur le matériel \"$nom_materiel\""; break; case 'printLabelRuban': $subject = "Etiquette imprimée"; $msg = "L'étiquette concerant votre matériel \"$nom_materiel\" a été imprimée"; $mailList[0] = $materiel->email_responsable; default: $subject = "Action \"$action\" sur un matériel"; $msg = "$acteur a effectué l'action \"$action\" sur le matériel \"$nom_materiel\""; break; } // end switch // (EP) Ajout de l'ID du materiel !!! $msg .= " (id=" . $materiel->id . ")."; // Only for "delete" action (for the moment...) if ($msgMore) $msg .= $msgMore; // $msg .= "\n\n"; } // subject is null // Et maintenant on construit la liste de mails... // Si l'envoi général est activé (et que l'action ne correspond pas à 'printLabelRuban'): if ($configuration->envoi_mail && $action != 'printLabelRuban') { // owner's mail (utilisateur du matériel) $mailList[0] = $materiel->email_responsable; // resp's mail $mailsRespMetier = null; $mailRespThematique = null; if ($materiel->groupes_metier_id != null && $materiel->groupes_metier_id != 1) { // Le ..!= 1 c'est parce que le groupe métier/thématique d'id 1 correspond au groupe N/A, soit aucun groupe $mailsRespMetier = TableRegistry::getTableLocator()->get('Users')->find() ->select('email') ->where([ 'role =' => 'Responsable', 'groupes_metier_id =' => $materiel->groupes_metier_id ]) ->toArray(); $mailRespThematique = TableRegistry::getTableLocator()->get('Users')->find() ->select('email') ->where([ 'role =' => 'Responsable', 'groupe_thematique_id =' => $materiel->groupes_thematique_id ]) ->toArray(); } if ($mailsRespMetier != null || $mailRespThematique != null) { $mailsResp = array_unique(array_merge($mailsRespMetier, $mailRespThematique)); for ($i = 0; $i < sizeof($mailsResp); $i ++) { $mailList[] = $mailsResp[$i]['email']; // $mailList[sizeof($mailList)] = $mailsResp[$i]['email']; } } // mail admin de reference (ici appele gestionnaire) -> Partie administration // Cela a été mis en commentaire car de toute façon l'utilisateur va voir un administratif pour faire valider sa fiche, // Pas la peine de spam l'administration de mails non plus hein ! /* * if ($action != 'statusValidated' && $action != 'statusArchived') { * $mailsAdmin = TableRegistry::getTableLocator()->get('Users')->find()->select('email') * ->where(['role =' => 'Administration']) * ->toArray(); * for ($i = 0; $i < sizeof($mailsAdmin); $i ++) { * $mailList[sizeof($mailList)] = $mailsAdmin[$i]['email']; * } * } */ } } // Materiel // @todo: ajouter quelques infos dans ces cas : else if ($entity instanceof Document) { ; } else if ($entity instanceof Suivi) { ; } else if ($entity instanceof Emprunt) { ; } /* * @todo: * else if ($entity instanceof Configuration) { * ; * } * ... etc ... (il faut qu'on soit plus précis) */ // Si l'envoi à la liste spécifiée est activé (et que l'action ne correspond pas à 'printLabelRuban'): $specificUsers = []; if ($configuration->envoi_mail_guests && $action != 'printLabelRuban') { // mail aux adresses specifiees dans la config for ($i = 0; $i < 11; $i ++) { $specificUser = $configuration['emailGuest' . $i]; if ($specificUser) $specificUsers[] = $specificUser; // $mailList[sizeof($mailList)] = $configuration['emailGuest' . $i]; $mailList[] = $specificUser; // Le if vérifie que la ligne soit pas null } } // On dedoublonne la liste des mails, c'pas tres cool de se faire spam 2-3 fois pour la meme action sur le meme materiel, non mais ! $mailList = array_unique($mailList); // ... Pour envoyer les mails aux personnes concernees foreach ($mailList as $mail) { // On envoi des mails à toute la liste, sauf pour "l'acteur", il sait ce qu'il a fait, pas besoin de le spam non plus hein if ($mail == $_SESSION['Auth']['User']['mail'][0]) continue; $message = $msg; // Sisi, cette variable $message est utile, m'enfin vous pouvez toujours essayer de la supprimer ..... Et pensez à regarder le contenu de vos mails !!! Sinon ca fait une tumeur // Génération du message "Vous recevez ce message en tant que $role" // Si $role inexistant (lorsque c'est un mail de la liste entrée en configuration), le message est plutot "Vous recevez ce message car vous avez demandé à le recevoir. [...]" if ($specificUsers) $role = "car vous etes dans la liste spécifique des emails de LabInvent. \n\nPour faire retirer votre mail de cette liste, veuillez contacter un SuperAdmin."; else { $role = TableRegistry::getTableLocator()->get('Users')->find() ->select('role') ->where([ 'email =' => $mail ]) ->first()['role']; // Default role is Utilisateur (for people in LDAP but without priviledge, not in the users table) if (is_null($role)) $role = 'Utilisateur'; $role = 'en tant que ' . $role; } if ($entity != null && ! in_array($action, [ 'delete', 'statusValidated', 'statusCreated' ])) $message .= "\n\nVeuillez vérifier et compléter si besoin la fiche correspondante."; $message .= "\n\nVous recevez ce message " . $role; $this->sendEmailTo("$subject", $message, $mail, $configuration); } return $mailList; } // Fonction d'envoi de mails private function sendEmailTo($subject, $msg, $mail, $config) { if ($mail != null && ! $config->test) { if (filter_var($mail, FILTER_VALIDATE_EMAIL)) { $email = new Email(); $etiquetteFrom = explode("@", $config->sender_mail); $email->transport('default') ->from([ $config->sender_mail => $etiquetteFrom[0] ]) ->to($mail) ->subject("[LabInvent] " . $subject) ->send($msg); } } } // Fonction d'envoi de mails avec photo jointe private function sendEmailImgTo($subject, $msg, $mail, $config, $nomImg) { if ($mail != null && ! $config->test) { if (filter_var($mail, FILTER_VALIDATE_EMAIL)) { $email = new Email(); $etiquetteFrom = explode("@", $config->sender_mail); // (EP) Je vais tuer le stagiaire qui a fait ça : //$email->attachments(["/var/www/html/labinvent/webroot/img/photos/$nomImg"]); // Il fallait plutot faire ça : $wwwroot_dir = new \Cake\Filesystem\Folder(WWW_ROOT); $absFileName = $wwwroot_dir->pwd() . DS . 'img' . DS . 'photos' . DS . $nomImg; $email->attachments([$absFileName]); $email->transport('default') ->from([ $config->sender_mail => $etiquetteFrom[0] ]) ->to($mail) ->subject("[LabInvent] " . $subject) ->send($msg); } } } // MI Fonction d'envoi de mails avec pièce jointe private function sendEmailPJTo($subject, $msg, $mail, $config, $nomDoc) { if ($mail!=null && !$config->test) { if (filter_var($mail, FILTER_VALIDATE_EMAIL)) { $email = new Email(); $etiquetteFrom = explode("@", $config->sender_mail); // (EP) Je vais tuer le stagiaire qui a fait ça : //$email->attachments(["/var/www/html/labinvent/webroot/files/$nomDoc"]); // Il fallait plutot faire ça : $wwwroot_dir = new \Cake\Filesystem\Folder(WWW_ROOT); //$absFileName = $wwwroot_dir->pwd() . DS . 'files' . DS . $nomDoc; $extension = explode(".", $nomDoc)[1]; // Photo ou doc ? $path_to_doc = in_array($extension, ['png','jpg','jpeg']) ? 'img'.DS.'photos' : 'files'; $absFileName = $wwwroot_dir->pwd().$path_to_doc.DS.$nomDoc; $email->attachments([$absFileName]); /* debug($mail); debug($etiquetteFrom); debug($absFileName); debug($email); exit; */ $email->transport('default') ->from([ $config->sender_mail => $etiquetteFrom[0] ]) ->to($mail) ->subject("[LabInvent] " . $subject) ->send($msg); } } } /**Version MI - version modifiée de la fonction sendEmail par malik du 18 juin au 24 août * * Envoi un mail avec un sujet, contenant un message à destination d'un email, selon l'action effectuée. * * @param $entity : * L'entité concernée (principalement un Matériel, mais ça peut aussi etre un Document) * @param $subject : * Sujet du message à envoyer. Si $subject n'est pas renseigné, un sujet par défaut sera généré. * @param $msg : * Message à envoyer. Si $msg n'est pas renseigné, un message par défaut sera généré. */ public function sendmail($entity, $mode, $subject = null, $msg = null) { //$this->myDebug("photo send mail"); //debug("photo send mail"); //exit; /* * $_SESSION['Auth']['User'] pour retrouver TOUTES les infos de la session courante (tout est du string) : * nom $_SESSION['Auth']['User']['sn'][0] * prenom $_SESSION['Auth']['User']['givenname'][0] * mail $_SESSION['Auth']['User']['mail'][0] * login $_SESSION['Auth']['User']['xxx'][0] /!\ Ce champ est suceptible de changer de nom, dans les tests ce champ est ['cn'][0] * mdp $_SESSION['Auth']['User']['userpassword'][0] */ $configuration = $this->confLabinvent; $action = $this->request->getAttribute('params')['action']; // add or edit or delete or ... // Si les deux cases "Activer l'envoi des mails.." sont décochées, on se fatigue pas à exécuter la fonction if (!$configuration->envoi_mail && !$configuration->envoi_mail_guests) return null; $mailList = []; // On détermine le message et le sujet du mail en fonction de l'action effectuee // on bloque l'envoi de mail à l'edition et à la validation pour eviter trop d'envoi de mail // le temps que soit trouvé une autre solution $acteur = $_SESSION['Auth']['User']['givenname'][0] . ' ' . $_SESSION['Auth']['User']['sn'][0]; /* * - mail pour un MATERIEL */ // if ($entity != null) { if ($entity instanceof Materiel) { $materiel = $entity; $nom_materiel = $materiel->designation; if ($subject == null && $msg == null) { $msgMore = ''; Switch ($action) { case 'add': $subject = "Ajout d'un matériel"; $msg = "$acteur a ajouté le matériel \"$nom_materiel\""; break; case 'edit': $subject = "Modification d'un matériel"; $msg = "$acteur a modifié le matériel \"$nom_materiel\""; break; case 'delete': $subject = "Suppression d'un matériel"; $msg = "$acteur a supprimé le matériel \"$nom_materiel\""; // @todo: mettre le nom des domaine, categ, et sous-categ, et non pas l'id if ($materiel->sur_categorie_id != "") $msgMore .= "\n\nDomaine : " . $materiel->sur_categorie_id; if ($materiel->categorie_id != "") $msgMore .= "\n\nCatégorie : " . $materiel->categorie_id; if ($materiel->sous_categorie_id != "") $msgMore .= "\n\nSous-catégorie : " . $materiel->sous_categorie_id; if ($materiel->description != "") $msgMore .= "\n\nDescription :\n" . $materiel->description; break; case 'statusCreated': $subject = "Dé-validation d'un matériel"; $msg = "$acteur a dé-validé le matériel \"$nom_materiel\""; break; case 'statusValidated': $subject = "Validation d'un matériel"; $msg = "$acteur a validé le matériel \"$nom_materiel\""; break; case 'statusToBeArchived': $subject = "Demande d'archivage d'un matériel"; $msg = "$acteur a demandé l'archivage du matériel \"$nom_materiel\""; break; case 'statusArchived': $subject = "Archivage d'un matériel"; $msg = "$acteur a archivé le matériel \"$nom_materiel\""; break; case 'setLabelIsPlaced': $subject = "Etiquette posée sur un matériel"; $msg = "Etiquette posée sur le matériel \"$nom_materiel\""; break; case 'printLabelRuban': $subject = "Etiquette imprimée"; $msg = "L'étiquette concerant votre matériel \"$nom_materiel\" a été imprimée"; $mailList[0] = $materiel->email_responsable; default: $subject = "Action \"$action\" sur un matériel"; $msg = "$acteur a effectué l'action \"$action\" sur le matériel \"$nom_materiel\""; break; } // end switch // (EP) Ajout de l'ID du materiel !!! $msg .= " (id=" . $materiel->id . ")."; // Only for "delete" action (for the moment...) if ($msgMore) $msg .= $msgMore; // $msg .= "\n\n"; } // subject is null // Et maintenant on construit la liste de mails... // Si l'envoi général est activé (et que l'action ne correspond pas à 'printLabelRuban'): if ($configuration->envoi_mail && $action != 'printLabelRuban') { // owner's mail (utilisateur du matériel) $mailList[0] = $materiel->email_responsable; // resp's mail $mailsRespMetier = []; $mailRespThematique = []; //TODO: changer ça car c'est pas forcément id=1 if ($materiel->groupes_metier_id != null && $materiel->groupes_metier_id != 1) { // Le ..!= 1 c'est parce que le groupe métier/thématique d'id 1 correspond au groupe N/A, soit aucun groupe $mailsRespMetier = TableRegistry::getTableLocator()->get('Users')->find() ->select('email') ->where([ 'role =' => 'Responsable', 'groupes_metier_id =' => $materiel->groupes_metier_id ]) ->toArray(); } //TODO: changer ça car c'est pas forcément id=1 if ($materiel->groupes_thematique_id != null && $materiel->groupes_thematique_id != 1) { // Le ..!= 1 c'est parce que le groupe métier/thématique d'id 1 correspond au groupe N/A, soit aucun groupe $mailRespThematique = TableRegistry::getTableLocator()->get('Users')->find() ->select('email') ->where([ 'role =' => 'Responsable', 'groupe_thematique_id =' => $materiel->groupes_thematique_id ]) ->toArray(); } if ($mailsRespMetier != [] || $mailRespThematique != []) { $mailsResp = array_unique(array_merge($mailsRespMetier, $mailRespThematique)); /* for ($i = 0; $i < sizeof($mailsResp); $i ++) { $mailList[] = $mailsResp[$i]['email']; // $mailList[sizeof($mailList)] = $mailsResp[$i]['email']; } */ foreach ($mailsResp as $mailResp) $mailList[] = $mailResp['email']; $mailList = array_unique($mailList); } //debug($mailList);exit(); // mail admin de reference (ici appele gestionnaire) -> Partie administration // Cela a été mis en commentaire car de toute façon l'utilisateur va voir un administratif pour faire valider sa fiche, // Pas la peine de spam l'administration de mails non plus hein ! /* * if ($action != 'statusValidated' && $action != 'statusArchived') { * $mailsAdmin = TableRegistry::getTableLocator()->get('Users')->find()->select('email') * ->where(['role =' => 'Administration']) * ->toArray(); * for ($i = 0; $i < sizeof($mailsAdmin); $i ++) { * $mailList[sizeof($mailList)] = $mailsAdmin[$i]['email']; * } * } */ } } // Materiel /* * - mail pour un DOCUMENT LIÉ */ // @todo: ajouter quelques infos dans ces cas : else if ($entity instanceof Document) { //debug("doc"); exit; $doc = $entity; $nom_doc = $doc->nom; $id_doc = $doc->id; $type_doc = $doc->type_doc; $id_mat = $doc->materiel_id; $id_suiv = $doc->suivi_id; if ($subject == null && $msg == null) { $msgMore = ''; Switch ($action) { case 'add': $subject = "Ajout d'un document"; $msg = "$acteur a ajouté le document \"$nom_doc\" au format \"$type_doc\""; break; //ajoutons un contenu de message plus clair pour l'envoi de document case 'mailDevis': $subject = "$acteur a partagé un document avec vous"; $msg = "$acteur après avoir ajouté le document \"$nom_doc\", a voulu le partager avec vous, c'est un document ayant le format \"$type_doc\" ."; $msg .="\n\n Le document est en pièce jointe."; break; //L'edition //comme il n'étais pas actuellement activé, on le laisse en commentaire //case 'edit': //$subject = "Modification d'un document"; //$msg = "$acteur a modifié le matériel \"$nom_doc\""; //break; //La suppression //comme il n'étais pas actuellement activé, on le laisse en commentaire //case 'delete': //$subject = "Suppression d'un document"; //$msg = "$acteur a supprimé le document\"$nom_doc\""; //break; default: $subject = "Action \"$action\" sur un matériel"; $msg = "$acteur a effectué l'action \"$action\" sur le document \"$nom_doc\" au format \"$type_doc\""; break; } // end switch // (EP) Ajout de l'ID du document, et de l'id du materiel associé !!! //On change le contenu en fonction de si le document a été lié à un matériel, ou a un suivi if (!$id_mat == Null) { $msg .= "\n\n (id doc=".$doc->id.", Materiel associé d'id=\"$id_mat\")"; $nomFic =$id_mat."_".$nom_doc."_".$id_doc.".".$type_doc; } else { $msg .= "\n\n (id doc=".$doc->id.", Materiel associé d'id=\"$id_suiv\")"; $nomFic =$id_suiv."_".$nom_doc."_".$id_doc.".".$type_doc; } } // Si le doc est lié à un matos, on ajoute le mail du gestionnaire du matos // (ssi l'envoi général est activé et que l'action ne correspond pas à 'printLabelRuban') if ( !$id_mat == Null && $configuration->envoi_mail && $action!='printLabelRuban' ) { // (EP) Recup du materiel associé /* $materiel = TableRegistry::getTableLocator()->get('Materiels')->find() ->where([ 'id =' => $doc->materiel_id ])->first(); */ $materiel = TableRegistry::getTableLocator()->get('Materiels')->get($doc->materiel_id); //debug("envoi"); //debug("matos = ".$materiel); //exit; // owner's mail (utilisateur du matériel associé ) //$mailList[0] = $entity->materiel->email_responsable; // (MI) - gestionaire ratachée au matériel //$mailList[1]= TableRegistry::getTableLocator()->get('Users')->find() $mailList[]= TableRegistry::getTableLocator()->get('Users')->find() ->select('email') ->where([ 'role =' => 'Administration', 'id =' => $materiel->gestionnaire_id ]); } // if matos } // DOC lié else if ($entity instanceof Suivi) { ; } else if ($entity instanceof Emprunt) { ; } /* * @todo: * else if ($entity instanceof Configuration) { * ; * } * ... etc ... (il faut qu'on soit plus précis) */ // Et maintenant on construit la liste de mails... // Si l'envoi à la liste spécifiée est activé (et que l'action ne correspond pas à 'printLabelRuban'): $specificUsers = []; if ($configuration->envoi_mail_guests && $action != 'printLabelRuban') { // mail aux adresses specifiees dans la config for ($i = 0; $i < 11; $i ++) { $specificUser = $configuration['emailGuest' . $i]; if ($specificUser) $specificUsers[] = $specificUser; // $mailList[sizeof($mailList)] = $configuration['emailGuest' . $i]; $mailList[] = $specificUser; // Le if vérifie que la ligne soit pas null } } // On dedoublonne la liste des mails, c'pas tres cool de se faire spam 2-3 fois pour la meme action sur le meme materiel, non mais ! // Ca supprime aussi les lignes vides $mailList = array_unique($mailList); // ... Pour envoyer les mails aux personnes concernees foreach ($mailList as $mail) { // On envoi des mails à toute la liste, sauf pour "l'acteur", il sait ce qu'il a fait, pas besoin de le spam non plus hein //if ($mail == $_SESSION['Auth']['User']['mail'][0]) //continue; $message = $msg; // Sisi, cette variable $message est utile, m'enfin vous pouvez toujours essayer de la supprimer ..... Et pensez à regarder le contenu de vos mails !!! Sinon ca fait une tumeur // Génération du message "Vous recevez ce message en tant que $role" // Si $role inexistant (lorsque c'est un mail de la liste entrée en configuration), le message est plutot "Vous recevez ce message car vous avez demandé à le recevoir. [...]" //if ($specificUsers) $role = "car vous etes dans la liste spécifique des emails de LabInvent. \n\nPour faire retirer votre mail de cette liste, veuillez contacter un super-administrateur."; /* (EP 13/319) : à quoi sert toute cette suite du texte du mail ??? * Ca sent le bon vieux copier-coller sans réfléchir... //else { //$role = $role. TableRegistry::get('Users')->find() $role = $role. TableRegistry::getTableLocator()->get('Users')->find() ->select('role') ->where([ 'email =' => $mail ]) ->first()['role'].' + '; // Default role is Utilisateur (for people in LDAP but without priviledge, not in the users table) // if (is_null($role)) $role =$role .'en tant que ' .'Utilisateur'; //} */ if ($entity != null && !in_array($action, ['delete','statusValidated','statusCreated'])) { $message .= "\n\nVeuillez vérifier et compléter si besoin la fiche correspondante."; $message .= "\n\nVous recevez ce message " . $role; //en fonction du mode à l'appel, on utilise un envoi de mail différent switch($mode) { //si le mode 1 est sélectionné c'est un envoi de mail avec ajout d'une photo //explique le document qui a été ajouté, et le met en pièce jointe case 1 : $this->sendEmailImgTo("$subject", $message, $mail, $configuration, $nomFic); break; //si le mode 2 est sélectionné c'est un envoi de mail avec ajout d'un document //à personnaliser case 2 : $this->sendEmailPJTo("$subject", $message, $mail, $configuration, $nomFic); break; //si le mode defaut est sélectionné c'est un simple envoi de mail //récapitule une action (mieux pour les add...) default : $this->sendEmailTo("$subject", $message, $mail, $configuration); break; } // switch } } //foreach ($mailList as $mail) return $mailList; } // function sendmail } // class AppController