access.class.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. <?php
  2. /**
  3. * Classe `access`
  4. *
  5. * Cette classe gère les droits d'accès des utilisateurs dans le système. Elle inclut des fonctionnalités pour :
  6. * - Vérifier si un utilisateur a accès à une ressource spécifique.
  7. * - Gérer les listes blanches et les accès hors ligne.
  8. * - Récupérer et manipuler les types d'accès et les rôles des utilisateurs.
  9. * - Enregistrer et mettre à jour les droits d'accès dans la base de données.
  10. * - Générer des menus déroulants et des tableaux pour la gestion des accès.
  11. */
  12. class access
  13. {
  14. /**
  15. * Vérifie si un élément est accessible.
  16. *
  17. * @param string $_element L'élément à vérifier.
  18. * @return bool TRUE si l'accès est autorisé, FALSE sinon.
  19. */
  20. public static function check(string $_element)
  21. {
  22. // Eléments autorisé sans authentification
  23. if (self::checkAccessWhite($_element)) {
  24. return TRUE;
  25. } else {
  26. if (session::isConnect("salarie") and session::isEspaceSalaries()) { // Espaces spécifiques aux Salariés
  27. return TRUE;
  28. } elseif (session::isConnect() and session::getType() == 2 and session::isEspaceControleurs()) { // Espaces spécifiques aux Contrôleurs
  29. return TRUE;
  30. } else {
  31. return self::ifAccesss($_element);
  32. }
  33. }
  34. }
  35. /**
  36. * Vérifie si un élément est accessible hors ligne.
  37. *
  38. * @param string $_string L'élément à vérifier.
  39. * @return bool TRUE si l'accès est autorisé hors ligne, FALSE sinon.
  40. */
  41. public static function checkAccessOffLine(string $_string)
  42. {
  43. return in_array($_string, OFF_LINE);
  44. }
  45. /**
  46. * Vérifie si un élément est dans la liste blanche.
  47. *
  48. * @param string $_string L'élément à vérifier.
  49. * @return bool TRUE si l'élément est dans la liste blanche, FALSE sinon.
  50. */
  51. public static function checkAccessWhite(string $_string)
  52. {
  53. return in_array($_string, WHITE_ACCESS);
  54. }
  55. /**
  56. * Récupère la liste des accès pour un type d'utilisateur donné.
  57. *
  58. * @param int|null $_idType L'ID du type d'utilisateur (optionnel).
  59. * @return array|bool La liste des accès ou FALSE en cas d'erreur.
  60. */
  61. public static function getAccessList(?int $_idType = NULL)
  62. {
  63. ($_idType == NULL) ? $idType = session::getType() : $idType = $_idType;
  64. $return["access"] = $return["noAccess"] = $return["exception"] = array();
  65. db::query("SELECT "
  66. . "" . DB_T_ACCESS . ".id, "
  67. . "" . DB_T_ACCESS . ".access, "
  68. . "" . DB_T_ACCESS . ".noAccess, "
  69. . "" . DB_T_ACCESS_EXCEPTION . ".exception "
  70. . "FROM " . DB_T_TYPE_ACCESS . " "
  71. . "INNER JOIN " . DB_T_ACCESS . " ON " . DB_T_TYPE_ACCESS . ".id_access = " . DB_T_ACCESS . ".id "
  72. . "LEFT JOIN " . DB_T_ACCESS_EXCEPTION . " ON " . DB_T_TYPE_ACCESS . ".id_exception = " . DB_T_ACCESS_EXCEPTION . ".id "
  73. . "WHERE " . DB_T_TYPE_ACCESS . ".id_type = :id_type ");
  74. db::bind(':id_type', $idType);
  75. try {
  76. $tmp = db::resultset();
  77. foreach ($tmp as $access) {
  78. $return["access"] = self::addInArray($access["access"], $return["access"]);
  79. $return["noAccess"] = self::addInArray($access["noAccess"], $return["noAccess"]);
  80. if(isset($access["exception"])) { $return["exception"] = self::addInArray($access["exception"], $return["exception"]); }
  81. }
  82. // Je supprime les restriction d'accès en fonction des accès accordés
  83. $return["noAccess"] = array_diff($return["noAccess"], $return["access"]);
  84. return $return;
  85. } catch (Exception $e) {
  86. return FALSE;
  87. }
  88. }
  89. /**
  90. * Récupère les types d'utilisateurs.
  91. *
  92. * @param bool $_expect TRUE pour exclure les contrôleurs, FALSE sinon.
  93. * @return array|bool Les types d'utilisateurs ou FALSE en cas d'erreur.
  94. */
  95. public static function getTypesUsers(bool $_expect = FALSE)
  96. {
  97. $except = ($_expect == FALSE) ? NULL : " WHERE " . DB_T_TYPE_USER . ".id != 2"; // Sauf les contrôleurs
  98. db::query("SELECT * FROM " . DB_T_TYPE_USER . $except);
  99. try {
  100. $tmp = db::resultset();
  101. return $tmp;
  102. } catch (Exception $e) {
  103. return FALSE;
  104. }
  105. }
  106. /**
  107. * Vérifie si une exception d'accès est limitée.
  108. *
  109. * @param string $_exception L'exception à vérifier.
  110. * @return bool TRUE si l'exception est limitée, FALSE sinon.
  111. */
  112. public static function ifLimitAccessException(string $_exception)
  113. {
  114. $accessList = self::getAccessList(session::getType());
  115. return in_array($_exception, $accessList["exception"]) ? TRUE : FALSE;
  116. }
  117. /**
  118. * Vérifie si un accès est autorisé.
  119. *
  120. * @param string $_accessAsk L'accès à vérifier.
  121. * @param int|null $_idType L'ID du type d'utilisateur (optionnel).
  122. * @return bool TRUE si l'accès est autorisé, FALSE sinon.
  123. */
  124. public static function ifAccesss(string $_accessAsk, ?int $_idType = NULL)
  125. {
  126. if (session::isConnect() == FALSE and self::checkAccessOffLine($_accessAsk)) {
  127. return TRUE;
  128. }
  129. // Si Admin OK
  130. $idType = $_idType == NULL ? session::getType() : $_idType;
  131. if ($idType == 1) {
  132. return TRUE;
  133. }
  134. // Si Admin OK
  135. $accessList = self::getAccessList($idType);
  136. $cheminGenrique = self::checkGenericAccess($_accessAsk, $accessList["access"]);
  137. if ($cheminGenrique != FALSE AND !in_array($_accessAsk, $accessList["noAccess"])) { // Si Accès générique
  138. return TRUE;
  139. } elseif (in_array($_accessAsk, $accessList["access"]) or self::checkAccessWhite($_accessAsk)) {
  140. return TRUE;
  141. } else {
  142. return FALSE;
  143. }
  144. }
  145. /**
  146. * Vérifie si un accès générique est autorisé.
  147. *
  148. * @param string $_string L'accès à vérifier.
  149. * @param array $_access_list La liste des accès.
  150. * @return string|bool Le chemin générique si autorisé, FALSE sinon.
  151. */
  152. private static function checkGenericAccess(string $_string, array $_access_list)
  153. {
  154. $string = explode("-", $_string)[0];
  155. $check = in_array($string."*", $_access_list);
  156. return ($check == TRUE) ? $string : FALSE;
  157. }
  158. /**
  159. * Sépare les accès à partir d'une chaîne.
  160. *
  161. * @param string $_string La chaîne à traiter.
  162. * @return array Les accès séparés.
  163. */
  164. private static function splitAccess(string $_string)
  165. {
  166. $return = array();
  167. $tmp = array_filter(explode("\n", $_string));
  168. foreach ($tmp as $key => $value) {
  169. $return[$key] = trim($value);
  170. }
  171. return $return;
  172. }
  173. /**
  174. * Ajoute des accès à un tableau existant.
  175. *
  176. * @param string $_string Les accès à ajouter.
  177. * @param array $_array Le tableau existant.
  178. * @return array Le tableau mis à jour.
  179. */
  180. private static function addInArray(string $_string, array $_array)
  181. {
  182. return array_unique(array_merge(self::splitAccess($_string), $_array));
  183. }
  184. /**
  185. * Récupère la liste des types d'utilisateurs, avec des exceptions optionnelles.
  186. *
  187. * @param array|null $_idExceptions Les IDs à exclure (optionnel).
  188. * @return array|bool La liste des types ou FALSE en cas d'erreur.
  189. */
  190. public static function getListTypeUser(?array $_idExceptions = NULL )
  191. {
  192. $return = array();
  193. db::query("SELECT id, type FROM " . DB_T_TYPE_USER);
  194. try {
  195. $return = [];
  196. foreach (db::resultset() as $value) {
  197. if(is_null($_idExceptions) OR (!is_null($_idExceptions) AND !in_array($value["id"], $_idExceptions)) ){
  198. $return[$value["id"]] = $value["type"];
  199. }
  200. }
  201. return $return;
  202. } catch (Exception $e) {
  203. return FALSE;
  204. }
  205. }
  206. /**
  207. * Affiche une ligne de tableau pour les accès.
  208. *
  209. * @param array $valueAccess Les données d'accès.
  210. * @return void
  211. */
  212. public static function printRenderAccessRow(array $valueAccess){
  213. if (!is_null($valueAccess["exception"])) {
  214. $tooltip = '<span class="ms-2" data-bs-toggle="tooltip" title="Possibilité d\'accès partiel avec les éléments cachés suivants : ' . htmlspecialchars($valueAccess["exception"]) . '"><i class="bi bi-info-circle-fill" style="color:#ffc107;"></i></span>';
  215. } else {
  216. $tooltip = '';
  217. }
  218. echo '<tr>';
  219. echo '<td style="vertical-align: middle; box-sizing: border-box;">' . $valueAccess["label"] . $tooltip . '</td>';
  220. $tmp = [];
  221. foreach ($valueAccess["access"] as $keyRole => $valueRole) {
  222. $tmp[$keyRole] = '<td style="width: 180px;"><div style="text-align:center;">';
  223. $tmp[$keyRole] .= self::getSelectAccess($valueAccess["access"][$keyRole], $valueAccess["exception"]);
  224. $tmp[$keyRole] .= '</div></td>';
  225. }
  226. echo $tmp[1]; // Administrateur
  227. echo $tmp[4]; // Modérateur du CMS
  228. echo $tmp[5]; // Bureau du CSE
  229. echo $tmp[6]; // Elu du CSE
  230. echo $tmp[7]; // Comptable
  231. echo $tmp[3]; // Assistance sociale
  232. echo '</tr>';
  233. }
  234. /**
  235. * Génère un menu déroulant pour les accès.
  236. *
  237. * @param array|null $_access Les données d'accès (optionnel).
  238. * @param string|null $_exception L'exception associée (optionnel).
  239. * @return string Le HTML du menu déroulant.
  240. */
  241. private static function getSelectAccess(?array $_access = NULL, ?string $_exception = NULL){
  242. if (!is_null($_exception)) {
  243. $options = [
  244. 1 => 'Autorisé',
  245. 0 => '-',
  246. 2 => 'Partiellement'
  247. ];
  248. } else {
  249. $options = [
  250. 1 => 'Autorisé',
  251. 0 => '-',
  252. ];
  253. }
  254. $bgColors = [
  255. 1 => 'background-color:#d4edda;',
  256. 0 => 'background-color:#f8d7da;',
  257. 2 => 'background-color:#ffeeba;'
  258. ];
  259. $disabled = ($_access["id_type"] == 1 OR $_access["id_access"] == 3) ? ' disabled' : '';
  260. $disabledStyle = ($_access["id_type"] == 1 OR $_access["id_access"] == 3) ? ' opacity: 0.5; cursor: not-allowed;' : '';
  261. $style = isset($bgColors[$_access["access"]]) ? $bgColors[$_access["access"]] : '';
  262. $return = '<select class="form-select form-select-sm" name="access-' . str_replace("#", "-", $_access["id_type_access"]) . '" style="' . $style . $disabledStyle . '"' . $disabled . '>';
  263. foreach ($options as $value => $label) {
  264. $selected = ($_access["access"] === $value) ? ' selected' : '';
  265. $return .= '<option value="' . $value . '"' . $selected . '>' . $label . '</option>';
  266. }
  267. $return .= '</select>';
  268. return $return;
  269. }
  270. /**
  271. * Complète les accès avec des valeurs par défaut.
  272. *
  273. * @param string $_idAccess L'ID de l'accès.
  274. * @param array|null $_access Les données d'accès existantes (optionnel).
  275. * @return array Les accès complétés.
  276. */
  277. private static function completeIdemAccess(string $_idAccess, ?array $_access = NULL){
  278. $roles = self::getListTypeUser([2]); // Tous les types sauf les contrôleurs
  279. foreach ($roles as $keyRole => $valueRole) {
  280. if(empty($_access["access"][$keyRole])){
  281. $tmp = [];
  282. $tmp["id_type_access"] = $keyRole . "#" . $_access["id_access"];
  283. $tmp["id_type"] = $keyRole;
  284. $tmp["id_access"] = $_idAccess;
  285. $tmp["type"] = $valueRole;
  286. $tmp["access"] = ($keyRole == 1) ? 1 : 0;
  287. $return[$keyRole] = $tmp;
  288. } else {
  289. $return[$keyRole] = $_access["access"][$keyRole];
  290. }
  291. }
  292. return $return;
  293. }
  294. /**
  295. * Récupère la liste complète des accès.
  296. *
  297. * @return array La liste complète des accès.
  298. */
  299. public static function finalCompletAccess(){
  300. $access = access::getTypesAccessRecording();
  301. $return = [];
  302. foreach ($access as $keyAccess => $valueAccess) {
  303. $completeAccess = access::completeIdemAccess($valueAccess["id_access"], $valueAccess);
  304. unset($valueAccess["access"]);
  305. $valueAccess["access"] = $completeAccess;
  306. $return[] = $valueAccess;
  307. }
  308. return $return;
  309. }
  310. /**
  311. * Récupère les types d'accès.
  312. *
  313. * @return array|bool Les types d'accès ou FALSE en cas d'erreur.
  314. */
  315. private static function getTypesAccess(){
  316. db::query("SELECT "
  317. . DB_T_ACCESS . ".id, "
  318. . DB_T_ACCESS . ".label, "
  319. . DB_T_ACCESS . ".show, "
  320. . DB_T_ACCESS . ".add, "
  321. . DB_T_TYPE_ACCESS . ".id AS id_type_access, "
  322. . DB_T_TYPE_ACCESS . ".id_type, "
  323. . "exception1.exception AS exception_type, "
  324. . "exception2.exception AS exception, "
  325. . DB_T_TYPE_USER . ".type "
  326. . "FROM " . DB_T_ACCESS . " "
  327. . "LEFT JOIN " . DB_T_ACCESS_EXCEPTION . " AS exception1 ON exception1.id_access = " . DB_T_ACCESS . ".id "
  328. . "LEFT JOIN " . DB_T_TYPE_ACCESS . " ON " . DB_T_TYPE_ACCESS . ".id_access = " . DB_T_ACCESS . ".id "
  329. . "LEFT JOIN " . DB_T_TYPE_USER . " ON " . DB_T_TYPE_ACCESS . ".id_type = " . DB_T_TYPE_USER . ".id "
  330. . "LEFT JOIN " . DB_T_ACCESS_EXCEPTION . " AS exception2 ON " . DB_T_TYPE_ACCESS . ".id_exception = exception2.id "
  331. . "ORDER BY " . DB_T_ACCESS . ".id");
  332. try {
  333. $tmp = db::resultset();
  334. return $tmp;
  335. } catch (Exception $e) {
  336. return FALSE;
  337. }
  338. }
  339. /**
  340. * Génère un libellé pour un accès.
  341. *
  342. * @param array $_array Les données de l'accès.
  343. * @return string Le libellé généré.
  344. */
  345. private static function getTitleLabel(array $_array){
  346. if ($_array["show"] == 1 AND $_array["add"] == 0) {
  347. return "Accès à <strong>" . $_array["label"] . "</strong> en lecture";
  348. } elseif ($_array["show"] == 0 AND $_array["add"] == 1) {
  349. return "Accès à <strong>" . $_array["label"] . "</strong> en écriture";
  350. } else {
  351. return "Accès à <strong>" . $_array["label"] . "</strong> en lecture et écriture";
  352. }
  353. }
  354. /**
  355. * Récupère les types d'accès pour l'enregistrement.
  356. *
  357. * @return array Les types d'accès.
  358. */
  359. public static function getTypesAccessRecording(){
  360. $return = [];
  361. foreach (self::getTypesAccess() as $valueAccess) {
  362. $return[$valueAccess["id"]]["id_access"] = $valueAccess["id"];
  363. $return[$valueAccess["id"]]["label"] = self::getTitleLabel($valueAccess);
  364. $return[$valueAccess["id"]]["show"] = $valueAccess["show"];
  365. $return[$valueAccess["id"]]["add"] = $valueAccess["add"];
  366. $return[$valueAccess["id"]]["exception"] = $valueAccess["exception_type"];
  367. if(!empty($valueAccess["id_type_access"])) {
  368. $return[$valueAccess["id"]]["access"][$valueAccess["id_type"]] = [
  369. "id_type_access" => $valueAccess["id_type_access"],
  370. "id_type" => $valueAccess["id_type"],
  371. "id_access" => $valueAccess["id"],
  372. "type" => $valueAccess["type"],
  373. "access" => (empty($valueAccess["exception"])) ? 1 : 2,
  374. ];
  375. }
  376. }
  377. return $return;
  378. }
  379. /**
  380. * Récupère les accès par rôle.
  381. *
  382. * @return array Les accès par rôle.
  383. */
  384. public static function getAccessByRole(){
  385. $getAccessByRole = self::getTypesAccessRecording();
  386. $allTypeRole = self::getTypesUsers();
  387. $return = [];
  388. foreach ($getAccessByRole as $valuesGetAccessByRole) {
  389. $tmp = [];
  390. $tmp["access"] = $valuesGetAccessByRole["label"];
  391. $tmp["exception"] = $valuesGetAccessByRole["exception"];
  392. foreach ($allTypeRole as $valueAllTypeRole) {
  393. if(!empty($valuesGetAccessByRole["access"][$valueAllTypeRole["id"]])){
  394. $tmp[$valuesGetAccessByRole["access"][$valueAllTypeRole["id"]]["type"]] = $valuesGetAccessByRole["access"][$valueAllTypeRole["id"]]["access"];
  395. } elseif($valueAllTypeRole["id"] == 1){
  396. $tmp[$valueAllTypeRole["type"]] = 1;
  397. } else {
  398. $tmp[$valueAllTypeRole["type"]] = 0;
  399. }
  400. }
  401. $return[] = $tmp;
  402. }
  403. return $return;
  404. }
  405. /**
  406. * Récupère l'ID d'une exception pour un accès donné.
  407. *
  408. * @param int $_idAccess L'ID de l'accès.
  409. * @return array|bool Les données de l'exception ou FALSE en cas d'erreur.
  410. */
  411. private static function getIdException(int $_idAccess){
  412. db::query("SELECT "
  413. . DB_T_ACCESS_EXCEPTION . ".id, "
  414. . DB_T_ACCESS_EXCEPTION . ".exception "
  415. . "FROM " . DB_T_ACCESS_EXCEPTION . " "
  416. . "WHERE " . DB_T_ACCESS_EXCEPTION . ".id_access = :id_access");
  417. db::bind(':id_access', $_idAccess);
  418. try {
  419. $tmp = db::single();
  420. return $tmp;
  421. } catch (Exception $e) {
  422. return FALSE;
  423. }
  424. }
  425. /**
  426. * Enregistre les accès dans la base de données.
  427. *
  428. * @return bool TRUE si l'enregistrement a réussi, FALSE sinon.
  429. */
  430. public static function recordAccess(){
  431. $post = core::getPost();
  432. $data = [];
  433. foreach ($post as $keyPost => $valuePost) {
  434. if($valuePost == 1 OR $valuePost == 2){
  435. $tmp = explode("-", $keyPost);
  436. $data[$tmp[1] . "#" . $tmp[2]]["id_access"] = $tmp[2];
  437. $data[$tmp[1] . "#" . $tmp[2]]["id_type"] = $tmp[1];
  438. if($valuePost == 2){
  439. $data[$tmp[1] . "#" . $tmp[2]]["id_exception"] = self::getIdException($tmp[2])["id"];
  440. } else {
  441. $data[$tmp[1] . "#" . $tmp[2]]["id_exception"] = NULL;
  442. }
  443. }
  444. }
  445. // Vide la table
  446. db::query("TRUNCATE TABLE " . DB_T_TYPE_ACCESS);
  447. db::execute();
  448. // Reconstruit la table
  449. foreach ($data as $keyData => $valueData) {
  450. db::query("INSERT INTO " . DB_T_TYPE_ACCESS . " (id, id_type, id_access, id_exception) VALUES (:id, :id_type, :id_access, :id_exception)");
  451. db::bind(':id', $keyData);
  452. db::bind(':id_type', $valueData["id_type"]);
  453. db::bind(':id_access', $valueData["id_access"]);
  454. db::bind(':id_exception', $valueData["id_exception"]);
  455. try {
  456. db::execute();
  457. } catch (Exception $ex) {
  458. alert::recError("Erreur à l'enregistrement des droits");
  459. if(debug::isFile("debug")) { alert::recError("Stack : " . $ex); }
  460. return FALSE;
  461. }
  462. }
  463. return TRUE;
  464. }
  465. }