action.php 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945
  1. <?php
  2. if(!ini_get('safe_mode')) @set_time_limit(0);
  3. require_once __DIR__.DIRECTORY_SEPARATOR."common.php";
  4. if(php_sapi_name() == 'cli'){
  5. array_shift($_SERVER['argv']);
  6. $_['action'] = array_shift($_SERVER['argv']);
  7. foreach ($_SERVER['argv'] as $keyvalue) {
  8. $infos = explode('=',$keyvalue);
  9. $key = $infos[0];
  10. $value = count($infos)<2 ? '' : $infos[1];
  11. $_[$key] = $value;
  12. }
  13. }
  14. if(!isset($_['action'])) throw new Exception('Action inexistante');
  15. //Execution du code en fonction de l'action
  16. switch ($_['action']){
  17. case 'login':
  18. Action::write(function(&$response){
  19. global $myUser,$myFirm,$_,$conf;
  20. try {
  21. if(!isset($_['login'])) $_['login'] = 'anonymous';
  22. if(!isset($_['password'])) $_['password'] = '';
  23. // ETAPE 1
  24. Log::put("Tentative de connexion avec le login \"".$_['login']."\"",'Utilisateur');
  25. if($conf->get('account_block')==1){
  26. $try = is_numeric($conf->get('account_block_try')) ?$conf->get('account_block_try') : 5;
  27. $delay = is_numeric($conf->get('account_block_delay')) ?$conf->get('account_block_delay') : 10;
  28. $trying = Log::loadAll(array('category'=>'auth_fail', 'label'=>$_['login'], 'created:>'=>(time() - ($delay*60))));
  29. if(count($trying)>=$try) throw new Exception("Suite à un trop grand nombre de tentatives, votre compte est bloqué pour un délai de ".$delay." minutes",509);
  30. }
  31. // ETAPE 3
  32. $myUser = User::check($_['login'],$_['password']);
  33. if(!$myUser)
  34. throw new Exception("Problème lors de la connexion, veuillez contacter l'administrateur");
  35. // ETAPE 4
  36. if(file_exists('enabled.maintenance') && $myUser->superadmin != 1)
  37. throw new Exception('Seul un compte Super Admin peut se connecter en mode maintenance');
  38. // ETAPE 5
  39. if(!$myUser->connected())
  40. throw new Exception('Identifiant ou mot de passe incorrect');
  41. $myUser->loadPreferences();
  42. // ETAPE 6
  43. if(is_numeric($myUser->preference('default_firm')) && $myUser->haveFirm($myUser->preference('default_firm'))){
  44. $_SESSION['firm'] = serialize(Firm::getById($myUser->preference('default_firm')));
  45. if(!$_SESSION['firm'])
  46. throw new Exception("Problème lors de la connexion, veuillez contacter l'administrateur");
  47. } else if(count($myUser->firms)!=0) {
  48. $_SESSION['firm'] = serialize(reset($myUser->firms));
  49. if(!$_SESSION['firm'])
  50. throw new Exception("Problème lors de la connexion, veuillez contacter l'administrateur");
  51. } else {
  52. throw new Exception('Ce compte n\'est actif sur aucun établissement');
  53. }
  54. // ETAPE 7
  55. $myFirm = isset($_SESSION['firm']) ? unserialize($_SESSION['firm']) : new Firm();
  56. if(!$myFirm)
  57. throw new Exception("Problème lors de la connexion, veuillez contacter l'administrateur");
  58. // ETAPE 8
  59. $_SESSION['currentUser'] = serialize($myUser);
  60. if(!$_SESSION['currentUser'])
  61. throw new Exception("Problème lors de la connexion, veuillez contacter l'administrateur");
  62. // ETAPE 10
  63. if(isset($_['rememberMe']) && $_['rememberMe']){
  64. $cookie = sha1(bin2hex(random_bytes(20)));
  65. $myUser->preference('cookie',$cookie);
  66. make_cookie(COOKIE_NAME, $cookie);
  67. } else {
  68. $myUser->preference('cookie','');
  69. }
  70. $response['redirect'] = isset($_['url']) ? base64_decode($_['url']) : 'index.php';
  71. if(isset($_SESSION['last_request']) && !isset($_['url'])){
  72. $response['redirect'] = $_SESSION['last_request'];
  73. unset($_SESSION['last_request']);
  74. }
  75. //permet la redirection classic pour certains plugin d'authentification qui ne passent pas par le formulaire ajax
  76. if(isset($_['redirect']) && $_['redirect']=='classic'){
  77. header('location: '. $response['redirect']);
  78. exit();
  79. }
  80. // ETAPE 11
  81. Log::put("Connexion réussie avec \"".$myUser->login."\"",'Utilisateur');
  82. } catch(Exception $e){
  83. Log::put("Echec de la connexion avec ".$_['login']." : ".$e->getMessage(),'Utilisateur');
  84. //La vérification sur le code 509 permet d'éviter d'allonger le temps de ban à chaque tentative
  85. if($e->getCode()!=509) Log::put($_['login'],'auth_fail');
  86. throw new Exception($e->getMessage());
  87. }
  88. });
  89. break;
  90. case 'logout':
  91. global $myUser;
  92. if(isset($myUser->login)) $myUser->preference('cookie','');
  93. $url = 'index.php';
  94. if(isset($_['url'])) $url = base64_decode($_['url']);
  95. //Permet la redirection vers une url spécifique lors de la déco
  96. if(isset($_SESSION['logout_redirect'])) $url = $_SESSION['logout_redirect'];
  97. unset($_SESSION['currentUser']);
  98. unset($_SESSION['firm']);
  99. session_destroy();
  100. unset($_COOKIE[COOKIE_NAME]);
  101. setcookie(COOKIE_NAME, null, -1, '/');
  102. $redirect = $url;
  103. Plugin::callHook('logout',array($url,$myUser));
  104. header('location: '.$redirect);
  105. break;
  106. /** FILTERS **/
  107. case 'filter_save':
  108. Action::write(function(&$response){
  109. global $myUser,$_;
  110. $preferences = json_decode($myUser->preference('search_filters'),true);
  111. if(!$preferences) $preferences = array();
  112. if(!isset($_['slug'])) return $response;
  113. function filter_recursive_save($filters){
  114. foreach($filters as $i=>$advanced){
  115. if(isset($filters[$i]['operator'])) $filters[$i]['operator'] = html_entity_decode($filters[$i]['operator']);
  116. if(isset($filters[$i]['group'])) $filters[$i]['group'] = filter_recursive_save($filters[$i]['group']);
  117. }
  118. return $filters;
  119. }
  120. if(isset($_['filters']['advanced'])) $_['filters']['advanced'] = filter_recursive_save($_['filters']['advanced']);
  121. $preferences[$_['slug']] = $_['filters'];
  122. $myUser->preference('search_filters',json_encode($preferences));
  123. $response['message'] = 'Recherche enregistrée';
  124. $_SESSION['currentUser'] = serialize($myUser);
  125. });
  126. break;
  127. case 'filter_load':
  128. Action::write(function(&$response){
  129. global $myUser,$_;
  130. if(empty($_['slug'])) return $response;
  131. $preferences = json_decode($myUser->preference('search_filters'),true);
  132. if(!$preferences) $preferences = array();
  133. $response['filters'] = array();
  134. if(isset($preferences[$_['slug']])) $response['filters'] = $preferences[$_['slug']];
  135. });
  136. break;
  137. /** LOGS */
  138. case 'search_log':
  139. Action::write(function(&$response){
  140. global $myUser,$_;
  141. User::check_access('log','read');
  142. $query = 'SELECT * FROM {{table}} WHERE 1';
  143. $data = array();
  144. //Recherche simple
  145. if(!empty($_['filters']['keyword'])){
  146. $query .= ' AND label LIKE ?';
  147. $data[] = '%'.$_['filters']['keyword'].'%';
  148. }
  149. //Recherche avancée
  150. if(isset($_['filters']['advanced'])) filter_secure_query($_['filters']['advanced'],array('label','category','creator','created','ip'),$query,$data);
  151. //Tri des colonnes
  152. if(isset($_['sort']))
  153. sort_secure_query($_['sort'],array('label','ip','created','category','creator'),$query,$data);
  154. else
  155. $query .= ' ORDER BY created DESC, id DESC ';
  156. //Pagination
  157. $response['pagination'] = Log::paginate(100,(!empty($_['page'])?$_['page']:0),$query,$data);
  158. foreach(Log::staticQuery($query,$data,true) as $log){
  159. $log->created = date('d/m/Y H:i:s',$log->created);
  160. if(!empty($_['keyword'])){
  161. $log->label = preg_replace_callback('|(.*)('.$_['keyword'].')(.*)|i', function($matches){
  162. return $matches[1].'<strong>'.$matches[2].'</strong>'.$matches[3];
  163. }, $log->label);
  164. }
  165. $response['rows'][] = $log;
  166. }
  167. });
  168. break;
  169. /** PLUGINS **/
  170. case 'search_plugin':
  171. Action::write(function(&$response){
  172. global $myUser,$_;
  173. User::check_access('plugin','read');
  174. foreach(Plugin::getAll() as $plugin){
  175. $plugin->folder = array('name'=>$plugin->folder,'path'=>$plugin->path());
  176. foreach($plugin->require as $id=>$version)
  177. $plugin->required[] = array('id'=>$id, 'version'=>$version);
  178. $response['rows'][] = $plugin;
  179. }
  180. });
  181. break;
  182. case 'change_plugin_state':
  183. Action::write(function(&$response){
  184. global $myUser,$_;
  185. User::check_access('plugin','configure');
  186. $plugin = Plugin::getById($_['plugin']);
  187. if($_['state']){
  188. $states = Plugin::states();
  189. $missingRequire = array();
  190. foreach($plugin->require as $require=>$version):
  191. $req = Plugin::getById($require);
  192. if($req == null || $req==false || !$req->state || $req->version!=$version)
  193. $missingRequire[]= $require.' - '.$version;
  194. endforeach;
  195. if(count($missingRequire)!=0) throw new Exception("Plugins pré-requis non installés : ".implode(',',$missingRequire));
  196. }
  197. Plugin::state($_['plugin'],$_['state']);
  198. //TODO - mettre en place un timeout - core_reference();
  199. Log::put(($_['state']?'Activation':'Désactivation')." du plugin ".$_['plugin'],'Plugin');
  200. });
  201. break;
  202. /** LIEN ETABLISSEMENT / PLUGIN **/
  203. case 'search_firm_plugin':
  204. Action::write(function(&$response){
  205. global $myUser,$_;
  206. User::check_access('plugin','configure');
  207. if(!isset($_['firm'])) throw new Exception("Etablissement non spécifié");
  208. $wholePlugins = array();
  209. if($_['firm'] == '0'){
  210. foreach(Firm::loadAll() as $firm){
  211. foreach(Plugin::getAll(true) as $plugin){
  212. $wholePlugins[$plugin->id][$firm->id] = in_array($firm->id, $plugin->firms) ? 1 : 0;
  213. }
  214. }
  215. }
  216. foreach(Plugin::getAll(true) as $plugin){
  217. if($_['firm'] == '0'){
  218. $plugin->state = count(array_unique($wholePlugins[$plugin->id])) === 1 ? end($wholePlugins[$plugin->id]) : 2;
  219. }else{
  220. $plugin->state = in_array($_['firm'], $plugin->firms) ? 1 : 0;
  221. }
  222. $response['rows'][] = $plugin;
  223. }
  224. });
  225. break;
  226. case 'toggle_firm_plugin':
  227. Action::write(function(&$response){
  228. global $myUser,$_;
  229. User::check_access('plugin','configure');
  230. foreach(Firm::loadAll() as $firm){
  231. if($firm->id != $_['firm'] && $_['firm'] != '0') continue;
  232. $states = Plugin::states();
  233. $firms = $states[$_['plugin']];
  234. $key = array_search($firm->id, $firms);
  235. if($_['state']==0 && $key !== false){
  236. unset($firms[$key]);
  237. }else if($_['state']==1 && $key === false){
  238. $firms[] = $firm->id;
  239. }
  240. $states[$_['plugin']] = array_values($firms);
  241. Plugin::states($states);
  242. }
  243. });
  244. break;
  245. /** ETABLISSEMENT */
  246. case 'select_firm':
  247. global $myUser,$_,$myFirm;
  248. try{
  249. if(!$myUser->haveFirm( $_['firm'])) throw new Exception("Vous n'avez pas accès à cet établissement");
  250. $myFirm = Firm::getById($_['firm']);
  251. $_SESSION['firm'] = serialize($myFirm);
  252. $myUser->preference('default_firm',$myFirm->id);
  253. $myUser->loadRights();
  254. $_SESSION['currentUser'] = serialize($myUser);
  255. unset($_SESSION['users']);
  256. header('location: index.php');
  257. }catch(Exception $e){
  258. header('location: index.php?error='.urlencode($e->getMessage()));
  259. }
  260. break;
  261. case 'search_firm':
  262. Action::write(function(&$response){
  263. global $myUser,$_;
  264. User::check_access('firm','read');
  265. foreach(Firm::loadAll() as $firm){
  266. $row = $firm->toArray();
  267. $row['address'] = $firm->address();
  268. $row['logo'] = $firm->logo();
  269. $response['rows'][] = $row;
  270. }
  271. });
  272. break;
  273. case 'firm_logo_download':
  274. global $myUser,$_;
  275. try {
  276. File::downloadFile(File::dir().Firm::logo_path().$_['firm'].'.'.$_['extension']);
  277. } catch(Exception $e) {
  278. File::downloadFile('img/default-image.png');
  279. }
  280. break;
  281. case 'firm_logo_delete':
  282. Action::write(function(&$response){
  283. global $myUser,$_;
  284. User::check_access('firm','edit');
  285. $firm = Firm::provide();
  286. if(!$firm) throw new Exception("Établissement non identifié");
  287. foreach (glob(__ROOT__.FILE_PATH.Firm::logo_path().$firm->id.".*") as $filename)
  288. unlink($filename);
  289. if(!file_exists(__ROOT__.FILE_PATH.Firm::logo_path().'.thumbnails')) return;
  290. foreach (glob(__ROOT__.FILE_PATH.Firm::logo_path().'.thumbnails'.SLASH.$firm->id.".*") as $filename) {
  291. unlink($filename);
  292. }
  293. });
  294. break;
  295. case 'save_firm':
  296. global $myUser,$_;
  297. try{
  298. User::check_access('firm','edit');
  299. $firm = Firm::provide();
  300. $firm->fromArray($_);
  301. if(empty($firm->label)) throw new Exception("Vous devez remplir au moins le libellé de l'entreprise");
  302. $firm->save();
  303. //Ajout de l'image à la base de media
  304. if(!empty($_FILES['logo']) && $_FILES['logo']['size']!=0 ){
  305. foreach (glob(Firm::logo_path().$firm->id.".*") as $filename) {
  306. unlink($filename);
  307. }
  308. $logo = File::upload('logo',Firm::logo_path().$firm->id.'.{{ext}}',1048576,array('jpg','png','jpeg'));
  309. Image::resize($logo['absolute'],200,200);
  310. }
  311. if($firm->id == $myFirm->id){
  312. unset($_SESSION['firm']);
  313. $_SESSION['firm'] = serialize($firm);
  314. $myFirm = isset($_SESSION['firm']) ? unserialize($_SESSION['firm']) : new Firm();
  315. }
  316. Log::put("Ajout/Modification de l'établissement ".$firm->toText(),'Etablissement');
  317. header('location: setting.php?section=firm&success=Établissement enregistré');
  318. }catch(Exception $e){
  319. header('location: firm.php?id='.$firm->id.'&error='.$e->getMessage());
  320. }
  321. break;
  322. case 'delete_firm':
  323. Action::write(function(&$response){
  324. global $myUser,$_;
  325. User::check_access('firm','delete');
  326. $firm =Firm::getById($_['id']);
  327. Firm::deleteById($_['id']);
  328. $states = Plugin::states();
  329. foreach ($states as $plugin => $firms) {
  330. $key = array_search($_['id'], $firms);
  331. if($key === false) continue;
  332. unset($firms[$key]);
  333. $states[$plugin] = array_values($firms);
  334. }
  335. Plugin::states($states);
  336. UserFirmRank::delete(array('firm'=>$_['id']));
  337. Right::delete(array('firm'=>$_['id']));
  338. Log::put("Suppression de l'établissement ".$firm->toText(),'Etablissement');
  339. });
  340. break;
  341. /** LIEN ETABLISSEMENT / UTILISATEUR / RANG **/
  342. case 'search_userfirmrank':
  343. Action::write(function(&$response){
  344. global $myUser,$_;
  345. User::check_access('firm','read');
  346. if($_['firm'] == 0)
  347. foreach(Firm::loadAll() as $firm)
  348. $firms[] = $firm->id;
  349. else
  350. $firms[] = $_['firm'];
  351. $users = array();
  352. foreach(User::getAll(false) as $user)
  353. $users[$user->login] = $user;
  354. foreach(UserFirmRank::staticQuery("SELECT *, ufr.id id, u.id uid, r.label rank, f.label firm
  355. FROM {{table}} ufr
  356. LEFT JOIN ".User::tableName()." u ON ufr.user=u.login
  357. LEFT JOIN ".Rank::tableName()." r ON r.id=ufr.rank
  358. LEFT JOIN ".Firm::tableName()." f ON f.id=ufr.firm
  359. WHERE ufr.firm IN ('".implode("','",$firms)."')",array(),false) as $userFirmRank){
  360. $user = isset($users[$userFirmRank['user']]) ? $users[$userFirmRank['user']] : new User();
  361. // Petit trick pour l'affichage mustache
  362. if($user->superadmin != 1) $userFirmRank['superadmin'] = null;
  363. $userFirmRank['avatar'] = $user->getAvatar();
  364. $userFirmRank['password'] = '';
  365. $user->name = $user->lastname();
  366. $user->firstname = $user->firstname();
  367. $userFirmRank['user'] = $user;
  368. $response['rows'][] = $userFirmRank;
  369. }
  370. });
  371. break;
  372. case 'save_userfirmrank':
  373. Action::write(function(&$response){
  374. global $myUser,$_;
  375. User::check_access('firm','edit');
  376. if(!isset($_['firm'])) throw new Exception('Champ "Établissement" obligatoire');
  377. if(!isset($_['user']) || empty($_['user'])) throw new Exception('Champ "Utilisateur" obligatoire');
  378. if(!isset($_['rank']) || empty($_['rank'])) throw new Exception('Champ "Rang" obligatoire');
  379. foreach(Firm::loadAll() as $firm){
  380. if($_['firm'] != 0 && $_['firm'] != $firm->id) continue;
  381. $user = User::byLogin(stripslashes($_['user']));
  382. $rank = Rank::getById($_['rank']);
  383. if($user->origin == 'active_directory' && (!array_key_exists($firm->id, $user->firms) || !$firm->has_plugin('fr.sys1.activedirectory'))) continue;
  384. $userFirmRank = UserFirmRank::provide();
  385. $exist = is_null($userFirmRank->id) || $_['firm'] == 0 ? UserFirmRank::rowCount(array('user'=>$user->login,'firm'=>$firm->id,'rank'=>$_['rank'])) : UserFirmRank::rowCount(array('id:!='=>$userFirmRank->id,'user'=>$user->login,'firm'=>$firm->id,'rank'=>$_['rank']));
  386. if($exist > 0){
  387. $response['warning'][] = "Le rang ".$rank->label." est déja défini pour ".$user->fullName()." sur l'établissement ".$firm->label;
  388. continue;
  389. }
  390. $userFirmRank->fromArray($_);
  391. $userFirmRank->firm = $firm->id;
  392. $userFirmRank->user = $user->login;
  393. $userFirmRank->save();
  394. $response['success'][] = "Rang ".$rank->label." ajouté pour ".$user->fullName()." sur l'établissement ".$firm->label;
  395. }
  396. });
  397. break;
  398. case 'edit_userfirmrank':
  399. Action::write(function(&$response){
  400. global $myUser,$_;
  401. User::check_access('firm','edit');
  402. $userFirmRank = UserFirmRank::getById($_['id']);
  403. $response = $userFirmRank;
  404. });
  405. break;
  406. case 'delete_userfirmrank':
  407. Action::write(function(&$response){
  408. global $myUser,$_,$conf;
  409. User::check_access('firm','delete');
  410. $userFirmRank = UserFirmRank::provide();
  411. $user = User::byLogin($userFirmRank->user);
  412. if($user->preference('default_firm') == $userFirmRank->firm)
  413. UserPreference::delete(array('user'=>$user->login, 'key'=>'default_firm'));
  414. UserFirmRank::deleteById($_['id']);
  415. });
  416. break;
  417. /** UTILISATEURS **/
  418. case 'search_user':
  419. Action::write(function(&$response){
  420. global $myUser,$_;
  421. User::check_access('user','read');
  422. foreach(User::getAll(false) as $user){
  423. if($user->state == User::INACTIVE || (!$myUser->superadmin && $user->superadmin)) continue;
  424. $user->login = htmlspecialchars_decode($user->login);
  425. $user->name = $user->lastname();
  426. $user->firstname = $user->firstname();
  427. $user->avatar = $user->getAvatar();
  428. $user->formatedLogin = urlencode($user->login);
  429. $response['rows'][] = $user;
  430. }
  431. });
  432. break;
  433. case 'user_autocomplete':
  434. Action::write(function(&$response){
  435. global $myUser,$_;
  436. if(!$myUser->connected()) throw new Exception("Vous devez être connecté",401);
  437. $response['rows'] = array();
  438. if($_['keyword'] == '') return;
  439. if(in_array('user', $_['data']['types'])){
  440. foreach(User::getAll(false) as $user){
  441. if(preg_match('|'.preg_quote(slugify($_['keyword'])).'|i', slugify($user->fullName())) || preg_match('|'.preg_quote(slugify($_['keyword'])).'|i', slugify($user->login))){
  442. $response['rows'][] = array(
  443. 'fullname'=>html_decode_utf8($user->fullName()),
  444. 'name'=>$user->fullName(),
  445. 'uid'=>html_decode_utf8(addslashes($user->login)),
  446. 'id'=>$user->login,
  447. 'mail'=>$user->mail,
  448. 'type'=>'user',
  449. 'avatar'=>$user->getAvatar(),
  450. 'function'=>$user->function
  451. );
  452. }
  453. }
  454. }
  455. if(in_array('rank', $_['data']['types'])){
  456. foreach(Rank::staticQuery('SELECT * FROM {{table}} WHERE label LIKE ?',array('%'.$_['keyword'].'%'),true) as $rank){
  457. $response['rows'][] = array(
  458. 'fullname'=>html_decode_utf8($rank->label),
  459. 'name'=>$rank->label,
  460. 'uid'=>$rank->id,
  461. 'id'=>$rank->id,
  462. 'type'=>'rank',
  463. 'description'=>$rank->description,
  464. );
  465. }
  466. }
  467. });
  468. break;
  469. case 'user_by_uid':
  470. Action::write(function(&$response){
  471. global $myUser,$_;
  472. if(!$myUser->connected()) throw new Exception("Vous devez être connecté",401);
  473. $response['users'] = array();
  474. $ranks = array();
  475. $users = array();
  476. foreach($_['uids'] as $uid){
  477. if(is_numeric($uid)){
  478. $ranks[] = $uid;
  479. continue;
  480. }
  481. //user
  482. $item = User::byLogin($uid);
  483. if(!$item) continue;
  484. $row = $item->toArray();
  485. $row['fullname'] = html_decode_utf8($item->fullName());
  486. $row['name'] = $item->fullName();
  487. $row['uid'] = html_decode_utf8(addslashes($item->login));
  488. $row['id'] = $item->login;
  489. $row['type'] = 'user';
  490. unset($row['password']);
  491. unset($row['token']);
  492. $response['users'][$item->login] = $row;
  493. }
  494. //rank
  495. foreach(Rank::loadAll(array('id:IN'=>implode(',',$ranks))) as $item){
  496. $row = $item->toArray();
  497. $row['fullname'] = $item->label;
  498. $row['name'] = $item->label;
  499. $row['uid'] = $item->id;
  500. $row['id'] = $item->id;
  501. $row['type'] = 'rank';
  502. $response['users'][$item->id] = $row;
  503. }
  504. });
  505. break;
  506. case 'account_lost_password':
  507. Action::write(function(&$response){
  508. global $myUser,$myFirm,$_,$conf;
  509. if(!isset($_['mail']) || empty($_['mail']) || !check_mail($_['mail'])) throw new Exception("Adresse e-mail non spécifiée ou incorrecte");
  510. foreach(User::getAll(false) as $user){
  511. if(strtolower($user->mail) != strtolower($_['mail'])) continue;
  512. $token = sha1(time().mt_rand(0,1000));
  513. $linkToken = base64_encode($user->login.'::'.$token);
  514. UserPreference::delete(array('user'=>$user->login,'key'=>'lost_password'));
  515. $saved = new UserPreference();
  516. $saved->user = $user->login;
  517. $saved->key = 'lost_password';
  518. $saved->value = $token;
  519. $saved->save();
  520. $mail = new Mail();
  521. $mail->title = "Récupération de mot de passe oublié";
  522. $link = ROOT_URL.'/account.lost.php?token='.$linkToken;
  523. $mail->message = "
  524. Vous recevez cet e-mail parce que quelqu'un a fait une demande de changement de mot de passe pour votre compte sur ".ROOT_URL.".
  525. <br/>S'il s'agit bien de vous, <a href='".$link."'>Cliquez ici pour changer votre mot de passe</a> ou copiez collez le lien suivant dans votre navigateur préféré (<span class='text-primary'>".$link."</span>).
  526. <br/>Si vous n'êtes pas à l'origine de ce mail, aucune action n'est requise.";
  527. $mail->recipients['to'][] = $user->mail;
  528. $mail->send();
  529. Log::put("Demande de récupération de mot de passe : ".$user->toText(),'Utilisateur');
  530. return;
  531. }
  532. throw new Exception("Aucun compte ne correspond à l'e-mail spécifié dans notre base, veuillez contacter un administrateur pour modifier votre mot de passe.");
  533. });
  534. break;
  535. case 'account_save':
  536. Action::write(function(&$response){
  537. global $myUser,$myFirm,$_,$conf;
  538. User::check_access('account','edit');
  539. if(!isset($_['login']) || empty($_['login'])) throw new Exception("Identifiant obligatoire");
  540. if(preg_match('|[,'.preg_quote(htmlspecialchars_decode($conf->get('login_forbidden_char'))).']|i', htmlspecialchars_decode($_['login']), $match)) throw new Exception("Caractère ".$match[0]." interdit dans l'identifiant");
  541. if(!isset($_['mail']) || empty($_['mail'])) throw new Exception('Adresse mail obligatoire');
  542. $userForm = new User();
  543. $userForm->fromArray($_);
  544. if(empty($userForm->login))
  545. if(!isset($_['password']) || empty($_['password'])) throw new Exception("Mot de passe obligatoire");
  546. //Vérifications & formattage des données
  547. $userForm->firstname = ucfirst($userForm->firstname);
  548. $userForm->name = mb_strtoupper($userForm->name);
  549. if(!empty($userForm->mail) && !check_mail($userForm->mail)) throw new Exception('Le format du champ "Mail" est invalide');
  550. if(!empty($userForm->phone) && !check_phone_number($userForm->phone)) throw new Exception('Le format du champ "Téléphone fixe" est invalide');
  551. $userForm->phone = !empty($userForm->phone) ? normalize_phone_number($userForm->phone) : '';
  552. if(!empty($userForm->mobile) && !check_phone_number($userForm->mobile)) throw new Exception('Le format du champ "Téléphone mobile" est invalide');
  553. $userForm->mobile = !empty($userForm->mobile) ? normalize_phone_number($userForm->mobile) : '';
  554. if(preg_match('|[,'.preg_quote(htmlspecialchars_decode($conf->get('password_forbidden_char'))).']|i', htmlspecialchars_decode($_['password']), $match)) throw new Exception("Caractère ".$match[0]." interdit dans le mot de passe");
  555. if($_['password'] != $_['password2']) throw new Exception("Mot de passe et confirmation non similaires");
  556. //Recuperation des hash des precedents passwords
  557. $chain = explode('-',$myUser->preference('account_chain'));
  558. if(!empty(trim($_['password']))) {
  559. $hashedPassword = sha1(md5('$a1u7'.$_['password'].'$y$1'));
  560. if(in_array($hashedPassword, $chain) && !$myUser->superadmin) throw new Exception("Vous devez choisir un mot de passe différent des précédents");
  561. if(count($chain)==10) array_shift($chain);
  562. $chain[] = $hashedPassword;
  563. $myUser->preference('account_chain',implode('-',$chain));
  564. }
  565. //save des comptes type db
  566. if($myUser->origin == ''){
  567. if(!empty(trim($_['password']))){
  568. $passwordErrors = User::check_password_format($_['password']);
  569. if(count($passwordErrors)!=0 && !$myUser->superadmin) throw new Exception("Le format de mot de passe ne respecte pas les conditions suivantes : ".implode(',',$passwordErrors));
  570. if(($_['password']==$myUser->login || $_['password']==$myUser->mail) && !$myUser->superadmin) throw new Exception("Le mot de passe ne peut pas être identique à l'identifiant ou à l'e-mail");
  571. $myUser->password = sha1(md5($_['password']));
  572. $myUser->preference('passwordTime',time());
  573. }
  574. $myUser->firstname = $userForm->firstname;
  575. $myUser->name = $userForm->name;
  576. $myUser->mail = $userForm->mail;
  577. $myUser->function = $userForm->function;
  578. $myUser->phone = $userForm->phone;
  579. $myUser->mobile = $userForm->mobile;
  580. $myUser->manager = is_object($myUser->manager) ? $myUser->manager->login : $myUser->manager;
  581. $myUser->save();
  582. if($myUser->superadmin == 1){
  583. foreach(Firm::loadAll() as $firm)
  584. $firms[$firm->id] = $firm;
  585. $myUser->setFirms($firms);
  586. }
  587. }
  588. //Save de l'avatar
  589. if(!empty($_FILES['avatar']) && $_FILES['avatar']['size']!=0 ){
  590. $login = User::format_avatar_name($myUser->login);
  591. foreach (glob(__ROOT__.FILE_PATH.AVATAR_PATH.$login.".*") as $filename)
  592. unlink($filename);
  593. $avatar = File::upload('avatar',AVATAR_PATH.$login.'.{{ext}}',104857060,array('jpg','png','jpeg','gif'));
  594. Image::resize($avatar['absolute'],150,150);
  595. }
  596. //save des comptes types plugin
  597. Plugin::callHook("user_save",array(&$myUser,$userForm,&$response));
  598. $myUser->loadRights();
  599. unset($_SESSION['users']);
  600. $_SESSION['currentUser'] = serialize($myUser);
  601. });
  602. break;
  603. case 'account_avatar_download':
  604. global $myUser,$_;
  605. try {
  606. $user = str_replace(array('..','/'),'',$_['user']);
  607. $extension = str_replace(array('..','/'),'',$_['extension']);
  608. File::downloadFile(File::dir().AVATAR_PATH.User::format_avatar_name($user).'.'.$extension);
  609. } catch(Exception $e) {
  610. File::downloadFile('img/default-avatar.png');
  611. }
  612. break;
  613. case 'account_avatar_delete':
  614. Action::write(function(&$response){
  615. global $myUser,$_;
  616. $user = User::byLogin($_['login']);
  617. if(!$user) throw new Exception("Utilisateur non identifié");
  618. if($myUser->login != $user->login && !$myUser->can('user', 'edit')) throw new Exception("Permissions insuffisantes",403);
  619. foreach(glob(__ROOT__.FILE_PATH.AVATAR_PATH.User::format_avatar_name($user->login).".*") as $filename)
  620. unlink($filename);
  621. if(!file_exists(__ROOT__.FILE_PATH.AVATAR_PATH.'.thumbnails')) return;
  622. foreach(glob(__ROOT__.FILE_PATH.AVATAR_PATH.'.thumbnails'.SLASH.User::format_avatar_name($user->login).".*") as $filename)
  623. unlink($filename);
  624. });
  625. break;
  626. case 'save_user':
  627. Action::write(function(&$response){
  628. global $myUser,$_,$conf;
  629. User::check_access('user','edit');
  630. if(!isset($_['login']) || empty($_['login'])) throw new Exception("Identifiant obligatoire");
  631. if(preg_match('|[,'.preg_quote(htmlspecialchars_decode($conf->get('login_forbidden_char'))).']|i', htmlspecialchars_decode($_['login']), $match)) throw new Exception("Caractère ".$match[0]." interdit dans l'identifiant");
  632. //Calcule de la taille max du login en focntion du chemin absolu pour avatar + extension (5)
  633. $osElementMaxLength = OS_path_max_length() - strlen(__ROOT__.FILE_PATH.AVATAR_PATH) - strlen(User::get_avatar_extension_brace());
  634. if(strlen($_['login']) > $osElementMaxLength) throw new Exception("Identifiant trop long : maximum ".$osElementMaxLength." caractères");
  635. $osElementMaxLength = OS_element_max_length();
  636. if(strlen($_['login']) > $osElementMaxLength) throw new Exception("Identifiant trop long : maximum ".$osElementMaxLength." caractères");
  637. if(!isset($_['mail']) || empty($_['mail'])) throw new Exception('Le champ "Mail" est obligatoire');
  638. if(!check_mail($_['mail'])) throw new Exception('Le format du champ "Mail" est invalide');
  639. if(preg_match('|[,'.preg_quote(htmlspecialchars_decode($conf->get('password_forbidden_char'))).']|i', htmlspecialchars_decode($_['password']), $match)) throw new Exception("Caractère ".$match[0]." interdit dans le mot de passe");
  640. if($_['password'] != $_['password2']) throw new Exception("Mot de passe et confirmation non similaires");
  641. $user = User::byLogin($_['login']);
  642. $user = $user && empty($user->origin) ? $user : new User();
  643. //Check si un user n'existe pas déjà avec ce login (on récupère tous les users car user peut être supprimé logiquement / désactivé uniquement)
  644. if(empty($user->id) && User::load(array('login'=>$_['login']))) throw new Exception("Un utilisateur existe déjà avec cet identifiant");
  645. if(!$user->login) $user->login = $_['login'];
  646. foreach(User::getAll(false) as $existingUser)
  647. if($existingUser->mail == trim($_['mail']) && $existingUser->login != $user->login) throw new Exception("Un utilisateur existe déjà avec cette adresse e-mail");
  648. if($user->id == 0 && (!isset($_['password']) || empty($_['password']))) throw new Exception("Mot de passe obligatoire");
  649. if(!empty(trim($_['password']))){
  650. $passwordErrors = User::check_password_format(html_entity_decode($_['password']));
  651. if(count($passwordErrors)!=0) throw new Exception("Le format de mot de passe ne respecte pas les conditions suivantes : ".implode(',',$passwordErrors));
  652. if($_['password']==$_['login'] || $_['password']==$_['mail'] ) throw new Exception("Le mot de passe ne peut pas être identique à l'identifiant ou à l'e-mail");
  653. $user->password = sha1(md5($_['password']));
  654. $user->preference('passwordTime',time());
  655. }
  656. $user->firstname = ucfirst($_['firstname']);
  657. $user->name = mb_strtoupper($_['name']);
  658. $user->mail = trim($_['mail']);
  659. $user->state = User::ACTIVE;
  660. if(isset($_['manager'])) $user->manager = $_['manager'];
  661. $user->save();
  662. unset($_SESSION['users']);
  663. $user->password = '';
  664. Log::put("Création/Modification de l'utilisateur ".$user->toText(),'Utilisateur');
  665. });
  666. break;
  667. case 'edit_user':
  668. Action::write(function(&$response){
  669. global $myUser,$_;
  670. User::check_access('user','edit');
  671. $user = User::byLogin($_['login']);
  672. $user->login = htmlspecialchars_decode($user->login);
  673. $user->name = $user->lastname();
  674. $user->firstname = $user->firstname();
  675. if(!$user) throw new Exception("Utilisateur non identifié");
  676. $user->password = '';
  677. $response = $user;
  678. });
  679. break;
  680. case 'delete_user':
  681. Action::write(function(&$response){
  682. global $myUser,$_;
  683. User::check_access('user','delete');
  684. $user = User::byLogin($_['login']);
  685. if(!$user) throw new Exception("Utilisateur non identifié");
  686. if($user->superadmin == 1) throw new Exception("Vous ne pouvez pas supprimer le compte super admin");
  687. if($user->login == $myUser->login) throw new Exception("Vous ne pouvez pas supprimer votre propre compte");
  688. if(!$user = User::getById($user->id)) throw new Exception("Impossible de supprimer un compte en dehors de de la base de données");
  689. $user->state = User::INACTIVE;
  690. $user->save();
  691. foreach(UserFirmRank::loadAll(array('user'=>$user->login)) as $ufrLink)
  692. UserFirmRank::deleteById($ufrLink->id);
  693. unset($_SESSION['users']);
  694. Log::put("Suppression de l'utilisateur ".$user->toText(),'Utilisateur');
  695. });
  696. break;
  697. /** DROITS **/
  698. case 'search_right':
  699. Action::write(function(&$response){
  700. global $myUser,$_;
  701. User::check_access('rank','edit');
  702. if(!isset($_['firm'])) throw new Exception("Etablissement non spécifié");
  703. $wholeRights = array();
  704. $sections = array();
  705. Plugin::callHook('section',array(&$sections));
  706. foreach(Firm::loadAll() as $firm){
  707. if($firm->id != $_['firm'] && $_['firm'] != '0') continue;
  708. $rights = Right::loadAll(array('rank'=>$_['rank'],'firm'=>$firm->id));
  709. $rightsTable = array();
  710. foreach($rights as $right)
  711. $rightsTable[$right->section] = $right;
  712. if($_['firm'] == '0'){
  713. foreach($sections as $section=>$description) {
  714. $right = isset($rightsTable[$section])? $rightsTable[$section] : new Right();
  715. $wholeRights[$section]['read'][$firm->id] = (int)$right->read;
  716. $wholeRights[$section]['edit'][$firm->id] = (int)$right->edit;
  717. $wholeRights[$section]['delete'][$firm->id] = (int)$right->delete;
  718. $wholeRights[$section]['configure'][$firm->id] = (int)$right->configure;
  719. }
  720. }
  721. }
  722. foreach ($sections as $section=>$description) {
  723. if($_['firm'] == '0'){
  724. $read = count(array_unique($wholeRights[$section]['read'])) === 1 ? end($wholeRights[$section]['read']) : 2;
  725. $edit = count(array_unique($wholeRights[$section]['edit'])) === 1 ? end($wholeRights[$section]['edit']) : 2;
  726. $delete = count(array_unique($wholeRights[$section]['delete'])) === 1 ? end($wholeRights[$section]['delete']) : 2;
  727. $configure = count(array_unique($wholeRights[$section]['configure'])) === 1 ? end($wholeRights[$section]['configure']) : 2;
  728. }else{
  729. $right = isset($rightsTable[$section])? $rightsTable[$section] : new Right();
  730. $read = $right->read;
  731. $edit = $right->edit;
  732. $delete = $right->delete;
  733. $configure = $right->configure;
  734. }
  735. $response['rows'][] = array(
  736. 'section'=>$section,
  737. 'description'=>$description,
  738. 'read'=>(int)$read,
  739. 'edit'=>(int)$edit,
  740. 'delete'=>(int)$delete,
  741. 'configure'=>(int)$configure
  742. );
  743. usort($response['rows'], function($a, $b){
  744. return strcmp($a['section'], $b['section']);
  745. });
  746. }
  747. });
  748. break;
  749. case 'toggle_right':
  750. Action::write(function(&$response){
  751. global $myUser,$_,$myFirm;
  752. User::check_access('rank','edit');
  753. if(!isset($_['section']) || empty($_['section'])) throw new Exception("Droit non spécifié");
  754. if(!isset($_['rank']) || empty($_['rank'])) throw new Exception("Rang non spécifié");
  755. if(!isset($_['right']) || empty($_['right'])) throw new Exception("Droit non spécifié");
  756. if(!isset($_['firm'])) throw new Exception("Établissement non spécifié");
  757. foreach(Firm::loadAll() as $firm){
  758. if($firm->id != $_['firm'] && $_['firm'] != '0') continue;
  759. $item = Right::load(array('rank'=>$_['rank'],'firm'=>$firm->id,'section'=>$_['section']));
  760. $item = !$item ? new Right() : $item ;
  761. $item->rank = $_['rank'];
  762. $item->firm = $firm->id;
  763. $item->section = $_['section'];
  764. $item->{$_['right']} = $_['state'];
  765. $item->save();
  766. $myUser->loadRights();
  767. $_SESSION['currentUser'] = serialize($myUser);
  768. }
  769. });
  770. break;
  771. /** RANGS **/
  772. case 'search_rank':
  773. Action::write(function(&$response){
  774. global $myUser,$_;
  775. User::check_access('rank','read');
  776. $rankQry = 'SELECT *,(SELECT GROUP_CONCAT(CONCAT(f.label,":",`section`,":",`read`,":",`edit`,":",`delete`,":",`configure`))
  777. FROM `'.Right::tableName().'` r LEFT JOIN firm f ON f.id = r.firm
  778. WHERE (r.read=1 OR r.edit=1 OR r.delete=1 OR r.configure=1) AND r.rank={{table}}.id) as rights
  779. FROM {{table}}';
  780. $ranks = Rank::staticQuery($rankQry,array(),true);
  781. foreach($ranks as $rank){
  782. $row = $rank->toArray(true);
  783. $row['rights'] = array();
  784. foreach (explode(',', $rank->foreign('rights')) as $right) {
  785. $infos = explode(':', $right);
  786. $row['rights'][] = array(
  787. 'configure' => !empty(array_pop($infos)),
  788. 'delete' => !empty(array_pop($infos)),
  789. 'edit' => !empty(array_pop($infos)),
  790. 'read' => !empty(array_pop($infos)),
  791. 'section' => array_pop($infos),
  792. 'firm' => array_pop($infos)
  793. );
  794. usort($row['rights'], function($a, $b){
  795. return strcmp($a['firm'], $b['firm']);
  796. });
  797. }
  798. $response['rows'][] = $row;
  799. }
  800. });
  801. break;
  802. case 'save_rank':
  803. Action::write(function(&$response){
  804. global $myUser,$_;
  805. User::check_access('rank','edit');
  806. if(!isset($_['label']) || empty($_['label'])) throw new Exception("Libellé obligatoire");
  807. $item = isset($_['id']) && !empty($_['id']) ? Rank::getById($_['id']) : new Rank();
  808. $item->label = $_['label'];
  809. $item->description = $_['description'];
  810. $item->save();
  811. Log::put("Ajout/Modification du rang ".$item->toText(),'Rang');
  812. });
  813. break;
  814. case 'edit_rank':
  815. Action::write(function(&$response){
  816. global $myUser,$_;
  817. User::check_access('rank','edit');
  818. $response = Rank::getById($_['id']);
  819. });
  820. break;
  821. case 'delete_rank':
  822. Action::write(function(&$response){
  823. global $myUser,$_;
  824. User::check_access('rank','delete');
  825. $rank = Rank::getById($_['id']);
  826. Rank::deleteById($_['id']);
  827. Log::put("Suppression du rang ".$rank->toText(),'Rang');
  828. });
  829. break;
  830. /** LISTES **/
  831. case 'search_dictionnary':
  832. Action::write(function(&$response){
  833. global $myUser,$_;
  834. User::check_access('dictionnary','read');
  835. foreach(Dictionnary::loadAll(array('parent'=>$_['parent'], 'state'=>Dictionnary::ACTIVE), array(' label ASC ')) as $item){
  836. $item->label = html_entity_decode($item->label);
  837. $response['rows'][] = $item;
  838. }
  839. });
  840. break;
  841. case 'save_dictionnary':
  842. Action::write(function(&$response){
  843. global $myUser,$_;
  844. User::check_access('dictionnary','edit');
  845. if(!isset($_['label']) || empty($_['label'])) throw new Exception("Libellé obligatoire");
  846. if(!is_numeric($_['parent'])){
  847. if($myUser->superadmin == 1)
  848. $_['parent'] = 0;
  849. else
  850. throw new Exception("Veuillez sélectionner une liste");
  851. }
  852. $item = Dictionnary::provide();
  853. $item->label = $_['label'];
  854. $item->parent = $_['parent'];
  855. $item->state = Dictionnary::ACTIVE;
  856. if(!empty($_['slug'])){
  857. $parameters = array('slug'=>$_['slug'], 'state'=>Dictionnary::ACTIVE);
  858. if(isset($item->id) && !empty($item->id)) $parameters['id:!='] = $item->id;
  859. if(Dictionnary::rowCount($parameters)>0) throw new Exception("Le slug renseigné est déjà utilisé");
  860. $item->slug = $_['slug'];
  861. }
  862. if(empty($item->slug)){
  863. $parentSlug = $_['parent'] == 0 ? '' : Dictionnary::getById($_['parent'])->slug;
  864. $slug = empty($parentSlug) ? $_['label'] : $parentSlug.'-'.$_['label'];
  865. $item->slug = Dictionnary::generateSlug($slug, 'slug');
  866. }
  867. if(isset($_['sublistlabel'])) $item->sublistlabel = $_['sublistlabel'];
  868. $item->save();
  869. Log::put("Création/Modification de l'item de liste ".$item->toText(),'Liste');
  870. });
  871. break;
  872. case 'edit_dictionnary':
  873. Action::write(function(&$response){
  874. global $myUser,$_;
  875. User::check_access('dictionnary','edit');
  876. $dictionnary = Dictionnary::getById($_['id']);
  877. $response = $dictionnary->toArray(true);
  878. });
  879. break;
  880. case 'delete_dictionnary':
  881. Action::write(function(&$response){
  882. global $myUser,$_;
  883. User::check_access('dictionnary','delete');
  884. if(!isset($_['id']) || empty($_['id'])) throw new Exception("Aucun identifiant spécifié");
  885. $item = Dictionnary::getById($_['id']);
  886. $item->state = Dictionnary::INACTIVE;
  887. $item->save();
  888. Dictionnary::change(array('state'=>Dictionnary::INACTIVE), array('parent'=>$item->id));
  889. Log::put("Suppression de la liste et des sous-listes associées".$item->toText(), 'Liste');
  890. });
  891. break;
  892. case 'get_parent_dictionnary':
  893. Action::write (function (&$response){
  894. global $myUser,$_;
  895. $selected = Dictionnary::loadAll(array("id"=>$_['selected']));
  896. foreach ($selected as $item) {
  897. if($item->parent == 0) {
  898. $parents = Dictionnary::loadAll(array("parent"=>$item->parent), array(' label ASC '));
  899. } else {
  900. $tmpParent = Dictionnary::loadAll(array("id"=>$item->parent), array(' label ASC '));
  901. $parents = Dictionnary::loadAll(array("parent"=>$tmpParent[0]->parent), array(' label ASC '));
  902. }
  903. $parentId = !empty($tmpParent) ? $tmpParent[0]->id : '';
  904. $response['rows'][] = array(
  905. 'parents'=> $parents,
  906. 'currentId'=> $item->id,
  907. 'parentId'=> $parentId,
  908. 'label'=> $item->label
  909. );
  910. }
  911. });
  912. break;
  913. case 'load_dictionnary_component':
  914. Action::write (function (&$response){
  915. global $myUser,$_;
  916. $dictionnaries = array();
  917. if(isset($_['slug']) && $_['slug'] != "")
  918. $dictionnaries = Dictionnary::load(array("slug"=>$_['slug']));
  919. if(isset($_['parentId']) && $_['parentId'] != "")
  920. $dictionnaries = Dictionnary::getById($_['parentId']);
  921. if($dictionnaries) {
  922. $children = Dictionnary::childs(array('id'=>$dictionnaries->id));
  923. $dictionnaries->childs = $children;
  924. }
  925. if(isset($_['value']) && $_['value'] != "" && $_['value'] != 0){
  926. if(!$_['hierarchy']){
  927. foreach ($dictionnaries->childs as $i => $child) {
  928. if($child->id == $_['value']) $child->selected = true;
  929. $dictionnaries->childs[$i] = $child;
  930. }
  931. } else {
  932. $dictionnaries = Dictionnary::hierarchy($_['value']);
  933. }
  934. }
  935. $response['content'] = $dictionnaries;
  936. });
  937. break;
  938. case 'dictionnary_slug_proposal':
  939. Action::write(function(&$response){
  940. global $myUser,$_;
  941. if(!isset($_['label']) || empty($_['label'])) return;
  942. //Check si l'item n'a pas déjà un slug
  943. if(isset($_['id']) && !empty($_['id']) && is_numeric($_['id'])){
  944. $item = Dictionnary::provide();
  945. if(!empty($item->slug)) return;
  946. }
  947. $parentSlug = empty($_['parent']) ? '' : Dictionnary::getById($_['parent'])->slug;
  948. $slug = empty($parentSlug) ? $_['label'] : $parentSlug.'-'.$_['label'];
  949. $response['slug'] = Dictionnary::generateSlug($slug, 'slug');
  950. });
  951. break;
  952. /* Composant tag list */
  953. case 'tag_list_autocomplete':
  954. Action::write(function(&$response){
  955. global $myUser,$_;
  956. if(!$myUser->connected()) throw new Exception("Vous devez être connecté",401);
  957. $response['rows'] = array();
  958. foreach(Dictionnary::staticQuery('SELECT * FROM {{table}} WHERE parent=(SELECT id from {{table}} WHERE slug= ? LIMIT 1) AND label LIKE ? AND state = "'.Dictionnary::ACTIVE.'"',array($_['data']['parent'],'%'.$_['keyword'].'%'),true) as $item){
  959. $response['rows'][] = array(
  960. 'name'=>$item->label,
  961. 'id'=>$item->id,
  962. 'slug'=>$item->slug
  963. );
  964. }
  965. });
  966. break;
  967. case 'tag_list_autocreate':
  968. Action::write(function(&$response){
  969. global $myUser,$_;
  970. if(!$myUser->connected()) throw new Exception("Vous devez être connecté",401);
  971. $response = array();
  972. $parent = Dictionnary::bySlug($_['slug']);
  973. $newtag = new Dictionnary();
  974. $newtag->state = Dictionnary::ACTIVE;
  975. $newtag->parent= $parent->id;
  976. $newtag->label= $_['label'];
  977. $newtag->slug= $parent->slug.'-'.slugify($_['label']);
  978. $newtag->save();
  979. $response = array(
  980. 'name'=>$newtag->label,
  981. 'id'=>$newtag->id,
  982. 'slug'=>$newtag->slug
  983. );
  984. });
  985. break;
  986. case 'tag_list_by_id':
  987. Action::write(function(&$response){
  988. global $myUser,$_;
  989. if(!$myUser->connected()) throw new Exception("Vous devez être connecté",401);
  990. $response['tags'] = array();
  991. foreach (explode(',',$_['id']) as $id) {
  992. $item = Dictionnary::getById($id);
  993. $item = !$item ? new Dictionnary(): $item;
  994. $row = $item->toArray();
  995. $row['name'] = $item->label;
  996. $row['slug'] = $item->slug;
  997. $row['id'] = $item->id;
  998. $response['tags'][] = $row;
  999. }
  1000. });
  1001. break;
  1002. /** TABLEAU DE DICTIONNARY */
  1003. case 'dictionnary_table_search':
  1004. Action::write(function(&$response){
  1005. global $myUser,$_;
  1006. if(!is_numeric($_['id'])) throw new Exception("Aucun identifiant de liste spécifié");
  1007. $dic = Dictionnary::getById($_['id']);
  1008. $response['dictionnary'] = $dic->toArray(true);
  1009. foreach (Dictionnary::childs(array('slug'=>$dic->slug)) as $child) {
  1010. $response['rows'][] = $child->toArray(true);
  1011. }
  1012. });
  1013. break;
  1014. case 'dictionnary_table_save':
  1015. Action::write(function(&$response){
  1016. global $myUser,$_;
  1017. if(!isset($_['label']) || empty($_['label'])) throw new Exception("Aucun libellé de liste renseigné");
  1018. if(!isset($_['id']) && !isset($_['list'])) throw new Exception("Aucun identifiant de liste ou de parent de liste trouvé");
  1019. $dic = isset($_['id']) && !empty($_['id'])? Dictionnary::getById($_['id']) : new Dictionnary();
  1020. $dic->parent = $_['list'];
  1021. $dic->label = $_['label'];
  1022. if(isset($_['slug']) && !empty($_['slug'])) {
  1023. $parameters = array('slug'=>$_['slug'], 'state'=>Dictionnary::ACTIVE);
  1024. if(isset($dic->id) && !empty($dic->id)) $parameters['id:!='] = $dic->id;
  1025. if(Dictionnary::rowCount($parameters)>0) throw new Exception("Le slug renseigné est déjà utilisé");
  1026. $dic->slug = $_['slug'];
  1027. }
  1028. $dic->state = Dictionnary::ACTIVE;
  1029. $dic->save();
  1030. });
  1031. break;
  1032. /* COMPOSANT LOCATION */
  1033. case 'location_search':
  1034. Action::write(function(&$response){
  1035. global $myUser,$_,$conf;
  1036. if(!$myUser->connected()) throw new Exception("Vous devez être connecté",401);
  1037. $appUrl = $conf->get('maps_api_suggest_url');
  1038. $appId = $conf->get('maps_api_id');
  1039. $appKey = $conf->get('maps_api_key');
  1040. if(empty($appUrl) || empty($appId) || empty($appKey)) throw new Exception("Impossible d'initialiser le composant de localisation");
  1041. if(!isset($_['keyword']) || empty($_['keyword'])) return;
  1042. $default = array(
  1043. 'query' => $_['keyword'],
  1044. 'app_id' => $appId,
  1045. 'app_code' => $appKey
  1046. );
  1047. $params = array_merge($default, $_['data']);
  1048. $curlOpt = array(
  1049. CURLOPT_URL => sprintf("%s?%s", $appUrl, http_build_query($params)),
  1050. CURLOPT_HTTPHEADER => array(
  1051. 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0',
  1052. 'Content-Type: application/json',
  1053. ),
  1054. CURLOPT_RETURNTRANSFER => 1,
  1055. CURLOPT_HTTPAUTH => CURLAUTH_ANY,
  1056. CURLOPT_SSL_VERIFYPEER => false,
  1057. CURLOPT_SSL_VERIFYHOST => false,
  1058. );
  1059. $ch = curl_init();
  1060. curl_setopt_array($ch, $curlOpt);
  1061. $result = curl_exec($ch);
  1062. if($result === false) throw new Exception("Erreur de récupération cURL : ".curl_error($curl));
  1063. $result = json_decode($result);
  1064. $infos = curl_getinfo($ch);
  1065. curl_close($ch);
  1066. $response['rows'] = $result->suggestions;
  1067. });
  1068. break;
  1069. case 'location_detail_search':
  1070. Action::write(function(&$response){
  1071. global $myUser,$_,$conf;
  1072. if(!$myUser->connected()) throw new Exception("Vous devez être connecté",401);
  1073. $appUrl = $conf->get('maps_api_geocode_url');
  1074. $appId = $conf->get('maps_api_id');
  1075. $appKey = $conf->get('maps_api_key');
  1076. if(empty($appUrl) || empty($appId) || empty($appKey)) throw new Exception("Impossible de récupérer les détails de la localisation");
  1077. if(!isset($_['locationId']) || empty($_['locationId'])) return;
  1078. $params = array(
  1079. 'locationid' => $_['locationId'],
  1080. 'app_id' => $appId,
  1081. 'app_code' => $appKey
  1082. );
  1083. $curlOpt = array(
  1084. CURLOPT_URL => sprintf("%s?%s", $appUrl, http_build_query($params)),
  1085. CURLOPT_HTTPHEADER => array(
  1086. 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0',
  1087. 'Content-Type: application/json',
  1088. ),
  1089. CURLOPT_RETURNTRANSFER => 1,
  1090. CURLOPT_HTTPAUTH => CURLAUTH_ANY,
  1091. CURLOPT_SSL_VERIFYPEER => false,
  1092. CURLOPT_SSL_VERIFYHOST => false,
  1093. );
  1094. $ch = curl_init();
  1095. curl_setopt_array($ch, $curlOpt);
  1096. $response = curl_exec($ch);
  1097. if($response === false) throw new Exception("Erreur de récupération cURL : ".curl_error($curl));
  1098. $response = json_decode($response);
  1099. $infos = curl_getinfo($ch);
  1100. curl_close($ch);
  1101. });
  1102. break;
  1103. /** CRONTAB */
  1104. case 'cron':
  1105. try{
  1106. if(php_sapi_name() !== 'cli') throw new Exception("Le cron ne peut être executé qu'en mode CLI depuis le serveur");
  1107. Plugin::callHook('cron');
  1108. }catch(Exception $e){
  1109. file_put_contents(__DIR__.SLASH.'cron.log',date('d-m-Y H:i').' | '.$e->getMessage().PHP_EOL,FILE_APPEND);
  1110. }
  1111. break;
  1112. /** FILES & UPLOADS */
  1113. //Gestion de l'upload temporaire (avant soumission d'un form)
  1114. case 'upload_temporary_file':
  1115. Action::write(function(&$response){
  1116. global $myUser,$_;
  1117. User::check_access('file','edit');
  1118. $response['previews'] = array();
  1119. $fileIndex = isset($_FILES[$_['index']]) ? $_FILES[$_['index']] : $_FILES['document'];
  1120. File::clear_temp();
  1121. for($i=0; $i<count($_FILES[$_['index']]['name']);$i++) {
  1122. $tempPath = File::temp().basename($fileIndex['tmp_name'][$i]);
  1123. move_uploaded_file($fileIndex['tmp_name'][$i], $tempPath);
  1124. $ext = getExt($fileIndex['name'][$i]);
  1125. $response['previews'][] = array(
  1126. 'path' => basename($fileIndex['tmp_name'][$i]),
  1127. 'name' => $fileIndex['name'][$i],
  1128. 'temporary' => true,
  1129. 'ext' => $ext,
  1130. 'url' => 'action.php?action=download_temporary_file&name='.$fileIndex['name'][$i].'&path='.basename($fileIndex['tmp_name'][$i]),
  1131. 'icon' => getExtIcon($ext)
  1132. );
  1133. }
  1134. });
  1135. break;
  1136. case 'download_temporary_file':
  1137. global $myUser,$_;
  1138. User::check_access('file','read');
  1139. File::downloadFile(File::temp().$_['path'],$_['name']);
  1140. break;
  1141. /** GENERAL SETTINGS **/
  1142. case 'general_settings_save':
  1143. Action::write(function(&$response){
  1144. global $myUser, $_, $conf;
  1145. User::check_access('setting_global','configure');
  1146. //Durée de conservation des logs
  1147. foreach(Log::staticQuery('SELECT DISTINCT category FROM {{table}}',array(),true) as $log):
  1148. $slug = slugify($log->category);
  1149. $key = 'log_retention_time_'.$slug;
  1150. if(!isset($_[$key])) continue;
  1151. if($_[$key] == 0 || !is_numeric($_[$key])) $_[$key] = '';
  1152. $conf->put($key,$_[$key]);
  1153. endforeach;
  1154. //Save du logo clair de l'application
  1155. if(!empty($_FILES['logo']) && $_FILES['logo']['size']!=0 ){
  1156. $logo = File::upload('logo','core'.SLASH.'logo.{{ext}}', 1048576, array('jpg','png','jpeg'));
  1157. Image::resize($logo['absolute'], 200, 200);
  1158. Image::toPng($logo['absolute']);
  1159. }
  1160. //Save du logo sombre de l'application
  1161. if(!empty($_FILES['logo_dark']) && $_FILES['logo_dark']['size']!=0 ){
  1162. $logo = File::upload('logo_dark','core'.SLASH.'logo.dark.{{ext}}', 1048576, array('jpg','png','jpeg'));
  1163. Image::resize($logo['absolute'], 200, 200);
  1164. Image::toPng($logo['absolute']);
  1165. }
  1166. if(!empty($_FILES['favicon']) && $_FILES['favicon']['size']!=0 ){
  1167. $logo = File::upload('favicon','core'.SLASH.'favicon.{{ext}}', 1048576, array('png'));
  1168. Image::resize($logo['absolute'], 64, 64);
  1169. Image::toPng($logo['absolute']);
  1170. }
  1171. //Gestion save des configuration générales
  1172. foreach(Configuration::setting('configuration-global') as $key => $value){
  1173. if(!is_array($value)) continue;
  1174. $allowedSettings[] = $key;
  1175. }
  1176. foreach ($_ as $key => $value)
  1177. if(in_array($key, $allowedSettings)) $conf->put($key, $value);
  1178. //Politique authentification
  1179. if(isset($_['password_format'])) $conf->put('password_format',$_['password_format']);
  1180. //Maintenance
  1181. if(isset($_['maintenance'])){
  1182. if($_['maintenance']){
  1183. if(file_exists('disabled.maintenance')) rename('disabled.maintenance', 'enabled.maintenance');
  1184. file_put_contents('enabled.maintenance', $_['maintenance-content']);
  1185. } else {
  1186. if(file_exists('enabled.maintenance')) rename('enabled.maintenance', 'disabled.maintenance');
  1187. file_put_contents('disabled.maintenance', $_['maintenance-content']);
  1188. }
  1189. }
  1190. });
  1191. break;
  1192. case 'general_reset_password_delay':
  1193. Action::write(function(&$response){
  1194. global $myUser, $_, $conf;
  1195. User::check_access('setting_global','configure');
  1196. foreach(User::getAll(false) as $user){
  1197. $user->preference('passwordTime',strtotime('01/01/1990'));
  1198. }
  1199. });
  1200. break;
  1201. //Récupération logo application générale
  1202. case 'general_logo_download':
  1203. global $_;
  1204. $variant = isset($_['variant']) && in_array($_['variant'], array('dark')) ? '.'.$_['variant'] : '';
  1205. $logoPath = File::dir().'core'.SLASH.'logo'.$variant.'.png';
  1206. $path = file_exists($logoPath) ? $logoPath : __ROOT__.SLASH.'img'.SLASH.'logo'.SLASH.'default-logo'.$variant.'.png';
  1207. File::downloadFile($path,'logo.png','image/png');
  1208. break;
  1209. //Suppression logo de l'application
  1210. case 'general_logo_delete':
  1211. Action::write(function(&$response){
  1212. global $myUser,$_;
  1213. User::check_access('setting_global','configure');
  1214. foreach (glob(File::dir().'core'.SLASH."logo.*") as $filename)
  1215. unlink($filename);
  1216. });
  1217. break;
  1218. //Récupération favicon application générale
  1219. case 'general_favicon_download':
  1220. $faviconPath = File::dir().'core'.SLASH.'favicon.png';
  1221. $path = file_exists($faviconPath) ? $faviconPath : __ROOT__.SLASH.'img'.SLASH.'logo'.SLASH.'default-favicon.png';
  1222. File::downloadFile($path,'favicon.png','image/png');
  1223. break;
  1224. //Suppression favicon de l'application
  1225. case 'general_favicon_delete':
  1226. Action::write(function(&$response){
  1227. global $myUser,$_;
  1228. User::check_access('setting_global','configure');
  1229. foreach (glob(File::dir().'core'.SLASH."favicon.*") as $filename)
  1230. unlink($filename);
  1231. });
  1232. break;
  1233. //Permet de se connecter "en tant que"
  1234. case 'user_impersonation':
  1235. try{
  1236. global $myUser,$myFirm,$_;
  1237. if(!$myUser->superadmin) throw new Exception("Seul le super administrateur peut exécuter cette fonctionnalité");
  1238. if(!isset($_['login'])) throw new Exception("Identifiant non spécifié");
  1239. unset($_SESSION['users']);
  1240. $user = new User();
  1241. $user = User::load(array('login'=>$_['login'],'state'=>User::ACTIVE));
  1242. Plugin::callHook("user_login", array(&$user,$_['login'],null,true,true,true));
  1243. if($user!=false){
  1244. $user->ranks = empty($user->ranks) ? array() : $user->ranks;
  1245. $user->firms = empty($user->firms) ? array() : $user->firms;
  1246. $user->loadRanks();
  1247. $user->loadPreferences();
  1248. $firms = $user->firms;
  1249. $firmValues = array_values($firms);
  1250. $defaultFirm = !empty($user->preference('default_firm')) ? $user->preferences['default_firm'] : (!is_null(key($firms)) ? key($firms) : array_shift($firmValues));
  1251. $myFirm = isset($user->firms[$defaultFirm]) ? $user->firms[$defaultFirm] : reset($user->firms);
  1252. if(!isset($defaultFirm) || empty($defaultFirm)) throw new Exception("Ce compte n'est actif sur aucun établissement");
  1253. }
  1254. if($user == false || empty($user->login)) throw new Exception("Utilisateur inexistant");
  1255. $user->loadRights();
  1256. $myUser = $user;
  1257. $_SESSION['currentUser'] = serialize($myUser);
  1258. $_SESSION['firm'] = serialize($myFirm);
  1259. header('location: index.php?info='.rawurlencode('Connecté avec l\'utilisateur : '.$user->login));
  1260. } catch(Exception $e){
  1261. header('location: setting.php?section=user&error='.rawurlencode($e->getMessage()));
  1262. }
  1263. break;
  1264. /** PERMISSION **/
  1265. //Récuperation d'une liste de permission
  1266. case 'core_permission_search':
  1267. Action::write(function(&$response){
  1268. global $myUser,$_;
  1269. User::check_access('core','read');
  1270. $permissions = Permission::loadAll(array('entity'=>$_['entity'],'uid'=>$_['uid']));
  1271. foreach($permissions as $permission){
  1272. $row = $permission->toArray();
  1273. if( !$permission->read ) unset($row['read']);
  1274. if( !$permission->edit ) unset($row['edit']);
  1275. if( !$permission->delete ) unset($row['delete']);
  1276. if( !$permission->configure ) unset($row['configure']);
  1277. if( !$permission->recursive ) unset($row['recursive']);
  1278. if($permission->targetEntity == 'rank'){
  1279. $row['target'] = '<i class="far fa-address-card"></i> '.Rank::getById($permission->targetUid)->label;
  1280. }else{
  1281. $user = User::byLogin($permission->targetUid);
  1282. $row['target'] = '<img class="avatar avatar-mini avatar-rounded" src="'.$user->getAvatar().'"> '.$user->fullName();
  1283. }
  1284. $response['rows'][] = $row;
  1285. }
  1286. });
  1287. break;
  1288. //Récuperation ou edition d'élément permission
  1289. case 'core_permission_edit':
  1290. Action::write(function(&$response){
  1291. global $myUser,$_;
  1292. User::check_access('core','edit');
  1293. $permissions = Permission::loadAll(array('uid'=>$_['uid'],'entity'=>$_['entity']));
  1294. $response['rows']= $permissions;
  1295. });
  1296. break;
  1297. /** CUSTOM API */
  1298. // pour obtenir un schema de toutes les api actives : http://url.com/api/schema?pretty
  1299. case 'api':
  1300. /* CORE API */
  1301. //Infos api
  1302. $api = new Api("core", "Api du coeur applicatif");
  1303. $api->route('infos','retourne les informations sur l\'environnement','GET',function($request,&$response){
  1304. global $myUser;
  1305. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1306. $repository = '';
  1307. if(file_exists(__DIR__.SLASH.'.git'.SLASH.'config')){
  1308. $stream = file_get_contents(__DIR__.SLASH.'.git'.SLASH.'config');
  1309. preg_match('|url = (.*\.fr)[:/]([^\n]*)|is', $stream,$match);
  1310. $repository = $match[2];
  1311. $repositoryUrl = preg_replace('|[^@]*@|i','http://',$match[1]).'/'.$match[2];
  1312. }
  1313. if(file_exists(__DIR__.SLASH.'.git'.SLASH.'refs'.SLASH.'heads'.SLASH.'master'))
  1314. $commitVersion = str_replace(array("\n","\r"),"",file_get_contents(__DIR__.SLASH.'.git'.SLASH.'refs'.SLASH.'heads'.SLASH.'master'));
  1315. $response['application']['label'] = PROGRAM_NAME;
  1316. $response['application']['version'] = SOURCE_VERSION;
  1317. $response['application']['versionning']['type'] = 'git';
  1318. $response['application']['versionning']['repository'] = $repository;
  1319. $response['application']['versionning']['repository_url'] = $repositoryUrl;
  1320. $response['application']['versionning']['commit_version'] = $commitVersion;
  1321. $response['application']['timezone'] = TIME_ZONE;
  1322. $response['php']['version'] = phpversion();
  1323. $response['apache']['version'] = apache_get_version();
  1324. $response['database']['type'] = BASE_SGBD;
  1325. $response['database']['version'] = Database::version();
  1326. $response['database']['host'] = BASE_HOST;
  1327. $response['os']['type'] = PHP_OS;
  1328. $response['os']['time'] = time();
  1329. });
  1330. //right api
  1331. $api->route('rights','retourne la liste des droits du logiciel','GET',function($request,&$response){
  1332. global $myUser;
  1333. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1334. $response['rights'] = array();
  1335. if(isset($request['parameters']['sort'])) throw new Exception("Sort is not implemented for firms",501);
  1336. if(isset($request['parameters']['filter'])) throw new Exception("Filter is not implemented for firms",501);
  1337. $limit = isset($request['parameters']['limit']) ? array($request['parameters']['limit']) : array();
  1338. foreach (Right::loadAll(array(),array(),$limit) as $right) {
  1339. $row = $right->toArray();
  1340. $response['rights'][] = $row;
  1341. }
  1342. });
  1343. $api->route('rights/[rightid]','ajoute/modifie un droit du logiciel','PUT',function($request,&$response){
  1344. global $myUser;
  1345. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1346. $response['right'] = array();
  1347. //Création
  1348. $_ = $request['parameters'];
  1349. $form = json_decode($request['body'],true);
  1350. if(!$form) throw new Exception("Invalid JSON body",400);
  1351. User::check_access('right','edit');
  1352. if(!empty($request['pathes'])){
  1353. $right = Right::getById($request['pathes'][0]);
  1354. if(empty($right->id)) throw new Exception("Right not found", 404);
  1355. $response['code'] = 200; //Modifié
  1356. }else{
  1357. $right = new right();
  1358. if(!isset($form['rank']) || empty($form['rank'])) throw new Exception("L'id du rang est obligatoire",400);
  1359. if(!isset($form['section']) || empty($form['section'])) throw new Exception("Le nom de la section est obligatoire",400);
  1360. if(!isset($form['firm']) || empty($form['firm'])) throw new Exception("L'id de l'établissement est obligatoire",400);
  1361. $response['code'] = 201; //Créé
  1362. }
  1363. //Check si le rang existe
  1364. $rank = Rank::getById($form['rank']);
  1365. if(empty($rank->id)) throw new Exception("Rank not found", 400);
  1366. //Check si la firm existe
  1367. $firm = Firm::getById($form['firm']);
  1368. if(empty($firm->id)) throw new Exception("Firm not found", 400);
  1369. //Check si la section existe
  1370. $sections = array();
  1371. Plugin::callHook('section',array(&$sections));
  1372. $find = false;
  1373. foreach($sections as $section=>$description){
  1374. if ($section==$form['section']){
  1375. $find = true;
  1376. break;
  1377. }
  1378. }
  1379. if (!$find) throw new Exception("Section not found", 400);
  1380. if(isset($form['rank'])) $right->rank = $form['rank'];
  1381. if(isset($form['section'])) $right->section = $form['section'];
  1382. if(isset($form['firm'])) $right->firm = $form['firm'];
  1383. if(isset($form['read'])) $right->read = $form['read'];
  1384. if(isset($form['edit'])) $right->edit = $form['edit'];
  1385. if(isset($form['delete'])) $right->delete = $form['delete'];
  1386. if(isset($form['configure'])) $right->configure = $form['configure'];
  1387. $right->save();
  1388. Log::put("Création/Modification de droit ".$right->toText(),'Droit');
  1389. $response['right'] = array('id'=>$right->id,'section'=>$right->section);
  1390. });
  1391. $api->route('rights/rightid','Supprime un rang du logiciel','DELETE',function($request,&$response){
  1392. global $myUser;
  1393. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1394. if(empty($request['pathes'])) throw new Exception("You must specify right id", 400);
  1395. User::check_access('right','delete');
  1396. $right = Right::getById($request['pathes'][0]);
  1397. if(!$right) throw new Exception("Right not found",404);
  1398. $right->deleteById($right->id);
  1399. Log::put("Suppression du rang ".$right->toText(),'Rang');
  1400. $response['code'] = 204;
  1401. });
  1402. //rank api
  1403. $api->route('ranks','retourne la liste des rangs du logiciel','GET',function($request,&$response){
  1404. global $myUser;
  1405. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1406. $response['ranks'] = array();
  1407. if(isset($request['parameters']['sort'])) throw new Exception("Sort is not implemented for firms",501);
  1408. if(isset($request['parameters']['filter'])) throw new Exception("Filter is not implemented for firms",501);
  1409. $limit = isset($request['parameters']['limit']) ? array($request['parameters']['limit']) : array();
  1410. foreach (Rank::loadAll(array(),array(),$limit) as $rank) {
  1411. $row = $rank->toArray();
  1412. $response['ranks'][] = $row;
  1413. }
  1414. });
  1415. $api->route('ranks/[rankid]','ajoute/modifie un rang du logiciel','PUT',function($request,&$response){
  1416. global $myUser;
  1417. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1418. $response['rank'] = array();
  1419. //Création
  1420. $_ = $request['parameters'];
  1421. $form = json_decode($request['body'],true);
  1422. if(!$form) throw new Exception("Invalid JSON body",400);
  1423. User::check_access('rank','edit');
  1424. if(!empty($request['pathes'])){
  1425. $rank = Rank::getById($request['pathes'][0]);
  1426. if(empty($rank->id)) throw new Exception("Rank not found", 404);
  1427. $response['code'] = 200; //Modifié
  1428. }else{
  1429. $rank = new rank();
  1430. if(!isset($form['label']) || empty($form['label'])) throw new Exception("Le libellé est obligatoire",400);
  1431. //Check si un rang n'existe pas déjà avec ce label
  1432. if(Rank::load(array('label'=>$form['label']))) throw new Exception("Un rang existe déjà avec ce nom",400);
  1433. $rank->label = $form['label'];
  1434. $response['code'] = 201; //Créé
  1435. }
  1436. if(isset($form['label'])) $rank->label = $form['label'];
  1437. if(isset($form['description'])) $rank->description = $form['description'];
  1438. $rank->save();
  1439. Log::put("Création/Modification de rang ".$rank->toText(),'Rang');
  1440. $response['rank'] = array('id'=>$rank->id,'label'=>$rank->label);
  1441. });
  1442. $api->route('ranks/rankid','Supprime un rang du logiciel','DELETE',function($request,&$response){
  1443. global $myUser;
  1444. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1445. if(empty($request['pathes'])) throw new Exception("You must specify rank id", 400);
  1446. User::check_access('rank','delete');
  1447. $rank = Rank::getById($request['pathes'][0]);
  1448. if(!$rank) throw new Exception("Rank not found",404);
  1449. foreach(UserFirmRank::loadAll(array('rank'=>$rank->id)) as $ufrLink)
  1450. UserFirmRank::deleteById($ufrLink->id);
  1451. $rank->deleteById($rank->id);
  1452. Log::put("Suppression du rang ".$rank->toText(),'Rang');
  1453. $response['code'] = 204;
  1454. });
  1455. //firm api
  1456. $api->route('firms','retourne la liste des établissements du logiciel','GET',function($request,&$response){
  1457. global $myUser;
  1458. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1459. $response['firms'] = array();
  1460. if(isset($request['parameters']['sort'])) throw new Exception("Sort is not implemented for firms",501);
  1461. if(isset($request['parameters']['filter'])) throw new Exception("Filter is not implemented for firms",501);
  1462. $limit = isset($request['parameters']['limit']) ? array($request['parameters']['limit']) : array();
  1463. foreach (Firm::loadAll(array(),array(),$limit) as $i=>$firm) {
  1464. $row = $firm->toArray();
  1465. $response['firms'][] = $row;
  1466. }
  1467. });
  1468. $api->route('firms/[firmid]','ajoute/modifie un établissement du logiciel','PUT',function($request,&$response){
  1469. global $myUser;
  1470. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1471. $response['firm'] = array();
  1472. //Création
  1473. $_ = $request['parameters'];
  1474. $form = json_decode($request['body'],true);
  1475. if(!$form) throw new Exception("Invalid JSON body",400);
  1476. User::check_access('firm','edit');
  1477. if(!empty($request['pathes'])){
  1478. $firm = Firm::getById($request['pathes'][0]);
  1479. if(empty($firm->id)) throw new Exception("Firm not found", 404);
  1480. $response['code'] = 200; //Modifié
  1481. }else{
  1482. $firm = new Firm();
  1483. if(!isset($form['label']) || empty($form['label'])) throw new Exception("Le libellé est obligatoire",400);
  1484. if(!isset($form['mail']) || empty($form['mail'])) throw new Exception('Le champ "Mail"est obligatoire',400);
  1485. //Check si une firm n'existe pas déjà avec ce label
  1486. if(Firm::load(array('label'=>$form['label']))) throw new Exception("Un établissement existe déjà avec ce nom",400);
  1487. $firm->label = $form['label'];
  1488. $response['code'] = 201; //Créé
  1489. }
  1490. if(isset($form['label'])) $firm->label = $form['label'];
  1491. if(isset($form['description'])) $firm->description = $form['description'];
  1492. if(isset($form['mail'])) $firm->mail = $form['mail'];
  1493. if(isset($form['phone'])) $firm->phone = $form['phone'];
  1494. if(isset($form['fax'])) $firm->fax = $form['fax'];
  1495. if(isset($form['street'])) $firm->street = $form['street'];
  1496. if(isset($form['street2'])) $firm->street2 = $form['street2'];
  1497. if(isset($form['city'])) $firm->city = $form['city'];
  1498. if(isset($form['zipcode'])) $firm->zipcode = $form['zipcode'];
  1499. if(isset($form['siret'])) $firm->siret = $form['siret'];
  1500. if(isset($form['iban'])) $firm->iban = $form['iban'];
  1501. $firm->save();
  1502. Log::put("Création/Modification de l'établissement ".$firm->toText(),'Etablissement');
  1503. $response['firm'] = array('id'=>$firm->id,'label'=>$firm->label);
  1504. });
  1505. $api->route('firms/firmid','Supprime un établissement du logiciel','DELETE',function($request,&$response){
  1506. global $myUser;
  1507. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1508. if(empty($request['pathes'])) throw new Exception("You must specify firm id", 400);
  1509. User::check_access('firm','delete');
  1510. $firm = Firm::getById($request['pathes'][0]);
  1511. if(!$firm) throw new Exception("Firm not found",404);
  1512. foreach(UserFirmRank::loadAll(array('firm'=>$firm->id)) as $ufrLink)
  1513. UserFirmRank::deleteById($ufrLink->id);
  1514. $firm->deleteById($firm->id);
  1515. Log::put("Suppression de l'établissement ".$firm->toText(),'Etablissement');
  1516. $response['code'] = 204;
  1517. });
  1518. //user api
  1519. $api->route('users','retourne la liste des utilisateurs du logiciel','GET',function($request,&$response){
  1520. global $myUser;
  1521. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1522. $response['users'] = array();
  1523. if(isset($request['parameters']['sort'])) throw new Exception("Sort is not implemented for users",501);
  1524. if(isset($request['parameters']['filter'])) throw new Exception("Filter is not implemented for users",501);
  1525. foreach (User::getAll(false) as $i=>$user) {
  1526. if(isset($request['parameters']['limit']) && $request['parameters']['limit']==$i) break;
  1527. $row = $user->toArray();
  1528. unset($row['password']);
  1529. unset($row['manager']);
  1530. $row['origin'] = !isset($row['id']) ? 'plugin': 'database';
  1531. $response['users'][] = $row;
  1532. }
  1533. });
  1534. $api->route('users/[userid]','ajoute/modifie un utilisateur du logiciel','PUT',function($request,&$response){
  1535. global $myUser;
  1536. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1537. $response['user'] = array();
  1538. //Création
  1539. $_ = $request['parameters'];
  1540. $form = json_decode($request['body'],true);
  1541. if(!$form) throw new Exception("Invalid JSON body",400);
  1542. User::check_access('user','edit');
  1543. if(!empty($request['pathes'])){
  1544. $user = User::byLogin($request['pathes'][0]);
  1545. if(empty($user->login)) throw new Exception("User not found", 404);
  1546. $response['code'] = 200; //Modifié
  1547. }else{
  1548. $user = new User();
  1549. if(!isset($form['login']) || empty($form['login'])) throw new Exception("Identifiant obligatoire",400);
  1550. if(!isset($form['password']) || empty($form['password'])) throw new Exception("Mot de passe obligatoire",400);
  1551. if(!isset($form['mail']) || empty($form['mail'])) throw new Exception('Le champ "Mail"est obligatoire',400);
  1552. foreach(User::getAll(false) as $existingUser)
  1553. if($existingUser->mail == trim($_['mail'])) throw new Exception("Un utilisateur existe déjà avec cette adresse e-mail");
  1554. //Check si un user n'existe pas déjà avec ce login (on récupère tous les users car user peut être supprimé logiquement / désactivé uniquement)
  1555. if(User::load(array('login'=>$form['login']))) throw new Exception("Un utilisateur existe déjà avec cet identifiant",400);
  1556. $user->login = $form['login'];
  1557. $response['code'] = 201; //Créé
  1558. }
  1559. if(!empty($form['password']) && trim($form['password'])!=''){
  1560. $passwordErrors = User::check_password_format(html_entity_decode($form['password']));
  1561. if(count($passwordErrors)!=0) throw new Exception("Le format de mot de passe ne respecte pas les conditions suivantes : ".implode(',',$passwordErrors),400);
  1562. if($form['password']==$form['login'] || $form['password']==$form['mail'] ) throw new Exception("Le mot de passe ne peut pas être identique à l'identifiant ou à l'e-mail",400);
  1563. $user->password = sha1(md5($form['password']));
  1564. $user->preference('passwordTime',time());
  1565. }
  1566. if(isset($form['firstname'])) $user->firstname = ucfirst($form['firstname']);
  1567. if(isset($form['name'])) $user->name = mb_strtoupper($form['name']);
  1568. if(isset($form['mail'])) $user->mail = $form['mail'];
  1569. $user->state = User::ACTIVE;
  1570. if(isset($form['manager'])) $user->manager = $form['manager'];
  1571. $user->save();
  1572. User::getAll(true,true);
  1573. Log::put("Création/Modification de l'utilisateur ".$user->toText(),'Utilisateur');
  1574. $response['user'] = array('id'=>$user->id,'login'=>$user->login);
  1575. });
  1576. //user api
  1577. $api->route('users/userid','Supprime un utilisateur du logiciel','DELETE',function($request,&$response){
  1578. global $myUser;
  1579. if(!$myUser->connected()) throw new Exception("Credentials are missing",401);
  1580. if(empty($request['pathes'])) throw new Exception("You must spcify user login", 400);
  1581. User::check_access('user','delete');
  1582. $user = User::byLogin($request['pathes'][0]);
  1583. if(!$user) throw new Exception("User not found",404);
  1584. if($user->superadmin == 1) throw new Exception("You can't delete superadmin account",403);
  1585. if($user->login == $myUser->login) throw new Exception("You can't delete your own account",403);
  1586. if(empty($user->id)) throw new Exception("You cant delete no db account", 400);
  1587. $user = User::getById($user->id);
  1588. $user->state = User::INACTIVE;
  1589. $user->save();
  1590. foreach(UserFirmRank::loadAll(array('user'=>$user->login)) as $ufrLink)
  1591. UserFirmRank::deleteById($ufrLink->id);
  1592. unset($_SESSION['users']);
  1593. Log::put("Suppression de l'utilisateur ".$user->toText(),'Utilisateur');
  1594. $response['code'] = 204;
  1595. });
  1596. $api->register();
  1597. /* FIN CORE API */
  1598. Api::run();
  1599. break;
  1600. /** CUSTOM REWRITE */
  1601. case 'rewrite':
  1602. try{
  1603. $root = substr($_SERVER['SCRIPT_NAME'], 0,strrpos($_SERVER['SCRIPT_NAME'] , '/'));
  1604. $requested = substr($_SERVER['REQUEST_URI'], strlen($root)+1);
  1605. ob_start();
  1606. Plugin::callHook('rewrite',array($requested));
  1607. $stream = ob_get_clean();
  1608. if($stream !='') echo $stream;
  1609. }catch(Exception $e){
  1610. exit('<div style="width:300px;margin:30px auto;padding:15px;background:#cecece;text-align:center;font-family:Arial">'.$e->getMessage().'</div>');
  1611. }
  1612. break;
  1613. /** ACTIONS DE PLUGINS */
  1614. default:
  1615. Plugin::callHook('action');
  1616. break;
  1617. }
  1618. ?>