noalyss Version-10
NOALYSS : serveur de comptabilité et ERP (2002)
Loading...
Searching...
No Matches
noalyss_user.class.php
Go to the documentation of this file.
1<?php
2use chillerlan\Authenticator\{Authenticator, AuthenticatorOptions};
3use chillerlan\Authenticator\Authenticators\AuthenticatorInterface;
4/*
5 * This file is part of NOALYSS.
6 *
7 * NOALYSS is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * NOALYSS is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with NOALYSS; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21// Copyright Author Dany De Bontridder danydb@aevalys.eu
22/**
23 * @file
24 * @brief Data & function about connected users
25 */
26/**
27 * @brief Data & function about connected users
28 *
29 */
30require_once NOALYSS_INCLUDE.'/constant.php';
31require_once NOALYSS_INCLUDE.'/lib/user_common.php';
32require_once NOALYSS_INCLUDE.'/lib/ac_common.php';
33
35{
36
37 var $id; //!< in account_repository , ac_users.use_id
38
39 var $db; //!< database connx to the folder NOT repository
40 var $admin; //!< is or is not admin
41 var $valid; //!< is or is not valid
43 var $last_name ; //!< user's last_name
44 var $name;
45 var $active; //!< 1 active , 0 disables
46 var $login; //!< login lower case
47 var $password; //!< md5 of the password
48 var $email; //!< user's email
49 var $access_mode; //!< MOBILE or PC depending if when connecting $login contains @mobile
50 var $lang ; //!< user's language
51 var $theme ; //!< user's CSS Theme
52 var $authent_method; //!< authentication method use for this user
53 private $otp_secret; //!< string use as secret for OTP
54 private $repository; //!< account_repository (\Database )
55 /**
56 * @brief Create an user , load an existing one or if p_id == -1 search for the connected user. To have an empty
57 * user, give a p_id smaller than -1 or zero.
58 *
59 * @param $p_cn DatabaseCore connection
60 * @param $p_id if -1 then load the current user, > 0 load the user , = 0 (or < -1 ) means an empty user
61 * \param $repository ( \Database default null) database
62 * to repository, if null is given the database will be defined in config.inc.php
63 */
64 function __construct($p_cn, $p_id=-1,$repository=null)
65 {
66 $this->db=$p_cn;
67 if ( $repository == null ) {
68 $this->repository=new Database(0);
69 } else {
70 $this->repository=$repository;
71 }
72
73 // if p_id is not set then check the connected user
74 if ($p_id==-1)
75 {
76 $this->connect_user();
77 $this->set_session_var();
78 }
79 else // if p_id is set get data of another user
80 {
81 $this->id=$p_id;
82 $this->load();
83 }
84 }
85 /**
86 * @brief get the repository
87 * @return Database
88 */
89 public function get_repository():\Database {
90 return $this->repository;
91 }
92 /**
93 * @brief set the repository
94 * @return Database
95 */
97 $this->repository = $repository;
98 return $this;
99 }
100
101 /**
102 * @brief put user_login into Postgres config (session), it can be used for tracking users activities
103 * @return void
104 */
105 public function set_session_var()
106 {
107 $this->db->exec_sql(sprintf("select set_config('noalyss.user_login','%s',false)",
108 Database::escape_string($_SESSION[SESSION_KEY.'g_user'])));
109 $this->repository->exec_sql(sprintf("select set_config('noalyss.user_login','%s',false)",
110 Database::escape_string($_SESSION[SESSION_KEY.'g_user'])));
111
112 }
113 public function __toString(): string
114 {
115 return "User ".print_r($this,true);
116 }
117 /**
118 * @brief check the password and user
119 */
120 function can_connect()
121 {
122
123 $can_connect=$this->repository->get_value("select count(*) from ac_users
124 where use_active=1 and
125 use_login=$1 and use_pass=$2",
126 [$this->login,$this->password]);
127 return $can_connect;
128 }
129 /**
130 * @brief connect the user and set the $_SESSION variables if not set thanks the $_REQUEST
131 */
132 private function connect_user()
133 {
134 if (!isset($_SESSION[SESSION_KEY.'g_user']))
135 {
136 $http=new \HttpInput();
137 $user_login=$http->request("p_user", "string", "");
138 $user_password=$http->request("p_pass", "string", "");
139
140 if ($user_login!=""&&$user_password!="")
141 {
142 $_SESSION[SESSION_KEY."g_user"]=$user_login;
143 $_SESSION[SESSION_KEY."g_pass"]=md5($user_password);
144 }
145 else
146 {
147 echo '<h2 class="error">'._('Session expirée<br>Utilisateur déconnecté').'</h2>';
148 redirect('index.php', 1);
149 exit();
150 }
151
152
153 if (strpos($user_login, '@mobile')!=false)
154 {
155 $this->access_mode='MOBILE';
156 $this->login=str_ireplace("@mobile", "", $user_login);
157 }
158 else
159 {
160 $this->access_mode='PC';
161 $this->login=strtolower($user_login);
162 }
163
164 $_SESSION[SESSION_KEY."access_mode"]=$this->access_mode;
165 $_SESSION[SESSION_KEY.'g_user']=$this->login;
166 }
167 $this->login=$_SESSION[SESSION_KEY."g_user"];
168 $this->password=$_SESSION[SESSION_KEY.'g_pass'];
169
170 $this->id=-1;
171 $this->lang=(isset($_SESSION[SESSION_KEY.'g_lang']))?$_SESSION[SESSION_KEY.'g_lang']:'fr_FR.utf8';
172 $this->access_mode=$_SESSION[SESSION_KEY."access_mode"];
173
174
175 // share user login with the repository
176 $this->repository->exec_sql(sprintf("select set_config('noalyss.user_login','%s',false)",
177 Database::escape_string($_SESSION[SESSION_KEY.'g_user'])));
178
179 if ($this->can_connect() == 0 || $this->load()==-1 )
180 {
181 echo '<h2 class="error">'._('Utilisateur ou mot de passe incorrect').'</h2>';
182 $sql="insert into audit_connect (ac_user,ac_ip,ac_module,ac_url,ac_state) values ($1,$2,$3,$4,$5)";
183 $server_remote=$_SERVER['REMOTE_ADDR']?? "cmd-line";
184 $request_uri=$_SERVER['REQUEST_URI']??"REQUEST-URI";
185
186 $this->repository->exec_sql($sql,
187 array($_SESSION[SESSION_KEY.'g_user'],$server_remote, "DISCON",
188 $request_uri , 'FAIL'));
189 $this->clean_session();
190 redirect('logout.php', 1);
191 exit();
192 }
193
194 $this->load_global_pref();
195
196 $_SESSION[SESSION_KEY.'g_lang']=$this->lang;
197 $this->valid=(isset($_SESSION[SESSION_KEY.'isValid']))?1:0;
198 if (isset($_SESSION[SESSION_KEY.'g_theme']))
199 {
200 $this->theme=$_SESSION[SESSION_KEY.'g_theme'];
201 }
202 $_SESSION[SESSION_KEY.'use_admin']=$this->admin;
203 $_SESSION[SESSION_KEY.'use_name']=$this->name;
204 $_SESSION[SESSION_KEY.'use_first_name']=$this->first_name;
205 }
206
207 /**
208 * @brief access_mode tells what mode must be used : pc or mobile
209 */
210 public function get_access_mode()
211 {
212 return $this->access_mode;
213 }
214
215 /**
216 * @brief access_mode tells what mode must be used : pc or mobile
217 */
218 public function set_access_mode($access_mode): object
219 {
220 $this->access_mode=$access_mode;
221 return $this;
222 }
223
224 /**
225 * @return int|mixed
226 */
227 public function getId(): int
228 {
229 return $this->id;
230 }
231
232 /**
233 * @param int|mixed $id
234 */
235 public function setId(int $id): void
236 {
237 $this->id=$id;
238 }
239
240 /**
241 * @return mixed
242 */
243 public function getDb()
244 {
245 return $this->db;
246 }
247
248 /**
249 * @param mixed $db
250 */
251 public function setDb($db): void
252 {
253 $this->db=$db;
254 }
255
256 /**
257 * @return default|int|mixed|string|string[]|null
258 */
259 public function getAdmin()
260 {
261 return $this->admin;
262 }
263
264 /**
265 * @param default|int|mixed|string|string[]|null $admin
266 */
267 public function setAdmin($admin): void
268 {
269 $this->admin=$admin;
270 }
271
272 /**
273 * @return int
274 */
275 public function getValid(): int
276 {
277 return $this->valid;
278 }
279
280 /**
281 * @param int $valid
282 */
283 public function setValid(int $valid): void
284 {
285 $this->valid=$valid;
286 }
287
288 /**
289 * @return default|mixed|string|string[]|null
290 */
291 public function getFirstName()
292 {
293 return $this->first_name;
294 }
295
296 /**
297 * @param default|mixed|string|string[]|null $first_name
298 */
299 public function setFirstName($first_name): void
300 {
301 $this->first_name=$first_name;
302 }
303
304 /**
305 * @return default|mixed|string|string[]|null
306 */
307 public function getName()
308 {
309 return $this->name;
310 }
311
312 /**
313 * @param default|mixed|string|string[]|null $name
314 */
315 public function setName($name): void
316 {
317 $this->name=$name;
318 }
319
320 /**
321 * @return mixed
322 */
323 public function getActive()
324 {
325 return $this->active;
326 }
327
328 /**
329 * @param mixed $active
330 */
331 public function setActive($active): void
332 {
333 $this->active=$active;
334 }
335
336 /**
337 * @return string
338 */
339 public function getLogin(): string
340 {
341 return $this->login;
342 }
343
344 /**
345 * @param string $login
346 */
347 public function setLogin(string $login): void
348 {
349 $this->login=$login;
350 }
351
352 /**
353 * @return mixed
354 */
355 public function getPassword()
356 {
357 return $this->password;
358 }
359
360 /**
361 * @param mixed $password
362 */
363 public function setPassword($password): void
364 {
365 $this->password=$password;
366 }
367
368 /**
369 * @return mixed
370 */
371 public function getEmail()
372 {
373 return $this->email;
374 }
375
376 /**
377 * @param mixed $email
378 */
379 public function setEmail($email): void
380 {
381 $this->email=$email;
382 }
383
384 /* * \brief load data from database.
385 * if this->id == -1, it is unknown so we have to retrieve it
386 from the database by the login
387 * return -1 if nothing is found or the use_id
388 */
389
390 function load():int
391 {
392 /* if this->id == -1, it is unknown so we have to retrieve it from
393 the database thanks it login */
394 if ($this->id<0)
395 {
396 $sql_cond=" where lower(use_login)=lower($1)";
397 $sql_array=array($this->login);
398 }
399 else
400 {
401 $sql_cond=" where use_id=$1";
402 $sql_array=array($this->id);
403 }
404 $sql="select use_id,
405 use_first_name,
406 use_name,
407 use_login,
408 use_active,
409 use_admin,
410 use_pass,
411 use_email,
412 use_auth_method,
413 use_otp_secret
414 from ac_users ";
415 $Res=$this->repository->exec_sql($sql.$sql_cond, $sql_array);
416 if (($Max=Database::num_row($Res))==0)
417 return -1;
419 $this->id=$row['use_id'];
420 $this->first_name=$row['use_first_name'];
421 $this->last_name=$row['use_name'];
422 $this->name=$row['use_name'];
423 $this->active=$row['use_active'];
424 $this->login=strtolower($row['use_login']);
425 $this->admin=$row['use_admin'];
426 $this->password=$row['use_pass'];
427 $this->email=$row['use_email'];
428 $this->authent_method=$row['use_auth_method'];
429 $this->otp_secret=$row['use_otp_secret'];
430 return $this->id;
431 }
432
433 function save()
434 {
435 if ( $this->authent_method != 0 && $this->otp_secret == null) {
436 $this->generate_otp();
437 }
438 $Sql="update ac_users set use_first_name=$1, use_name=$2
439 ,use_active=$3,use_admin=$4,use_pass=$5 ,use_email = $7
440 , use_auth_method=$8,use_otp_secret=$9
441 where use_id=$6";
442 $Res=$this->repository->exec_sql($Sql,
443 array($this->first_name //1
444 , $this->last_name // 2
445 , $this->active //3
446 , $this->admin //4
447 , $this->password //5
448 , $this->id //6
449 , $this->email //7
450 , $this->authent_method //8
451 , $this->otp_secret //9
452 ));
453 }
454
455 function insert()
456 {
457
458 $Sql="INSERT INTO ac_users(
459 use_first_name, use_name, use_login, use_active,
460 use_admin, use_pass, use_email)
461 VALUES ($1, $2, $3, $4, $5, $6, $7) returning use_id";
462
463 $this->id=$this->repository->get_value($Sql,
464 array($this->first_name, $this->last_name, $this->login, 1, $this->admin,
465 $this->password, $this->email));
466 }
467
468 /**
469 * \brief Check if user is active and exists in therepository
470 * Automatically redirect, it doesn't check if a user can access a folder
471 * \param $silent false, echo an error message and exit, true : exit without warning
472 * default is false
473 *
474 ++ */
475 function Check($silent=false, $from='')
476 {
477
478 $res=0;
479 $pass5=$this->password;
480
481 $sql="select ac_users.use_login,ac_users.use_active, ac_users.use_pass,
482 use_admin,use_first_name,use_name
483 from ac_users
484 where ac_users.use_id=$1
485 and ac_users.use_active=1
486 and ac_users.use_pass=$2";
487 $ret=$this->repository->exec_sql($sql, array($this->id, $pass5));
489 if ($res>0)
490 {
492 $_SESSION[SESSION_KEY.'use_admin']=$r['use_admin'];
493 $_SESSION[SESSION_KEY.'use_name']=$r['use_name'];
494 $_SESSION[SESSION_KEY.'use_first_name']=$r['use_first_name'];
495 $_SESSION[SESSION_KEY.'isValid']=1;
496
497 $this->admin=$_SESSION[SESSION_KEY.'use_admin'];
498 $this->name=$_SESSION[SESSION_KEY.'use_name'];
499 $this->first_name=$_SESSION[SESSION_KEY.'use_first_name'];
500 $this->load_global_pref();
501 }
502 $sql="insert into audit_connect (ac_user,ac_ip,ac_module,ac_url,ac_state) values ($1,$2,$3,$4,$5)";
503
504 if ($res==0 || $this->can_connect() == 0)
505 {
506 $this->repository->exec_sql($sql,
507 array($_SESSION[SESSION_KEY.'g_user'], $_SERVER["REMOTE_ADDR"],
508 $from, $_SERVER['REQUEST_URI'], 'FAIL'));
509 if (!$silent)
510 {
511 echo '<script> alert(\''._('Utilisateur ou mot de passe incorrect').'\')</script>';
512 redirect('index.html');
513 }
514 $this->valid=0;
515 session_unset();
516 exit-1;
517 }
518 else
519 {
520 if ($from=='LOGIN' || $from=='PORTAL')
521 {
522 $this->repository->exec_sql($sql,
523 array($_SESSION[SESSION_KEY.'g_user'], $_SERVER["REMOTE_ADDR"], $from,
524 $_SERVER['REQUEST_URI'], 'SUCCESS'));
525 }
526 $this->valid=1;
527 }
528
529 return $ret;
530 }
531
532 /**
533 * \brief return the access to a folder,
534 * \param $p_dossier id if it is == 0 then we take the value from $_SESSION
535 * \return the priv_priv
536 * - X no access
537 * - R has access (normal user)
538
539 *
540 */
541 function get_folder_access($p_dossier=0)
542 {
543
544 if ($p_dossier==0)
545 $p_dossier=dossier::id();
546 if ($this->admin==1)
547 return 'R';
548
549 $sql="select 'R' from jnt_use_dos where use_id=$1 and dos_id=$2";
550
551 $res=$this->repository->get_value($sql, array($this->id, $p_dossier));
552
553 if ($this->repository->get_affected()==0)
554 return 'X';
555 return $res;
556 }
557
558 /**
559 * \brief save the access of a folder
560 * \param $db_id the dossier id
561 * \param $priv boolean, true then it is granted, false it is removed
562 */
563 function set_folder_access($db_id, $priv)
564 {
565
566 if ($priv)
567 {
568 // the access is granted
569 $jnt=$this->repository->get_value("select jnt_id from jnt_use_dos where dos_id=$1 and use_id=$2", array($db_id, $this->id));
570
571 if ($this->repository->size()==0)
572 {
573
574 $Res=$this->repository->exec_sql("insert into jnt_use_dos(dos_id,use_id) values($1,$2)", array($db_id, $this->id));
575 }
576 }
577 else
578 {
579 // Access is revoked
580 $this->repository->exec_sql('delete from jnt_use_dos where use_id = $1 and dos_id = $2 ', array($this->id, $db_id));
581 }
582 }
583
584 /**
585 * \brief check that a user is valid and the access to the folder
586 * \param $p_ledger the ledger to check
587 * \return the priv_priv
588 * - O only predefined operation
589 * - W write
590 * - R read only
591 * - X no access
592 *
593 *
594 */
595 function get_ledger_access($p_ledger)
596 {
597 if ($this->admin==1||
598 $this->is_local_admin(dossier::id())==1||$this->get_status_security_ledger()==0)
599 return 'W';
600
601 $sql="select uj_priv from user_sec_jrn where uj_login=$1 and uj_jrn_id=$2";
602 $res=$this->db->get_value($sql, array($this->login, $p_ledger));
603
604 if ($res=='')
605 $res='X';
606 return $res;
607 }
608
609 /**
610 * \brief get all the available ledgers for the current user
611 * \param $p_type = ALL or the type of the ledger (ACH,VEN,FIN,ODS)
612 * \param $p_access =3 for Read or WRITE, 2 write, 1 for readonly
613 * \param (boolean) $all if true show also inactive
614 * \return a double array of available ledgers
615 @verbatim
616 [0] => [jrn_def_id]
617 [jrn_def_type]
618 [jrn_def_name]
619 [jrn_def_class_deb]
620 [jrn_def_class_cred]
621 [jrn_type_id]
622 [jrn_desc]
623 [uj_priv]
624 @endverbatim
625 */
626 function get_ledger($p_type='ALL', $p_access=3, $all=TRUE)
627 {
628 $p_type=strtoupper($p_type);
629 if (!in_array($p_type, ["FIN", "ALL", "ODS", "VEN", 'ACH']))
630 {
631 record_log(sprintf("UGL1, p_type %s", $p_type));
632 throw new Exception("UGL1"._("Type incorrecte"));
633 }
634 if ($all==TRUE)
635 {
636 $sql_enable="";
637 }
638 else
639 {
640 $sql_enable="and jrn_enable=1";
641 }
642 if ($this->admin!=1&&$this->is_local_admin()!=1&&$this->get_status_security_ledger()==1)
643 {
644 $sql_type=($p_type=='ALL')?'':"and jrn_def_type=upper('".sql_string($p_type)."')";
645 switch ($p_access)
646 {
647 case 3:
648 $sql_access=" and uj_priv!= 'X' ";
649 break;
650 case 2:
651 $sql_access=" and uj_priv = 'W' and jrn_enable=1 ";
652 break;
653
654 case 1:
655 $sql_access=" and ( uj_priv = 'R' or uj_priv='W') ";
656 break;
657 }
658
659 $sql="select jrn_def_id,jrn_def_type,jrn_def_code,
660 jrn_def_name,jrn_def_class_deb,jrn_def_class_cred,jrn_type_id,jrn_desc,uj_priv,
661 jrn_deb_max_line,jrn_cred_max_line,jrn_def_description,jrn_enable
662 from jrn_def join jrn_type on jrn_def_type=jrn_type_id
663 join user_sec_jrn on uj_jrn_id=jrn_def_id
664 where
665 uj_login='".$this->login."'".
666 $sql_type.$sql_access.$sql_enable.
667 " order by jrn_Def_name";
668 }
669 else
670 {
671 $sql_type=($p_type=='ALL')?' '.$sql_enable:"where jrn_def_type=upper('".sql_string($p_type)."') ".$sql_enable;
672 $sql="select jrn_def_id,jrn_def_type,jrn_def_code,jrn_def_name,jrn_def_class_deb,jrn_def_class_cred,jrn_deb_max_line,jrn_cred_max_line,
673 jrn_type_id,jrn_desc,'W' as uj_priv,jrn_def_description,jrn_enable
674 from jrn_def join jrn_type on jrn_def_type=jrn_type_id
675 $sql_type
676 order by jrn_Def_name";
677 }
678 $res=$this->db->exec_sql($sql);
679 if (Database::num_row($res)==0)
680 return null;
681 $array=Database::fetch_all($res);
682 return $array;
683 }
684
685 /**
686 * \brief return an sql condition for filtering the permitted ledger
687 * \param $p_type = ALL or the type of the ledger (ACH,VEN,FIN,ODS)
688 * \param $p_access =3 for READ or WRITE, 2 READ and write, 1 for readonly
689 *
690 * \return sql condition like = jrn_def_id in (...)
691 */
692 function get_ledger_sql($p_type='ALL', $p_access=3)
693 {
694 $aLedger=$this->get_ledger($p_type, $p_access);
695 if (empty($aLedger))
696 return ' jrn_def_id < 0 ';
697 $sql=" jrn_def_id in (";
698 foreach ($aLedger as $row)
699 {
700 $sql.=$row['jrn_def_id'].',';
701 }
702 $sql.='-1)';
703 return $sql;
704 }
705
706 /**
707 * @brief synomym for isAdmin,
708 * @deprecated
709 */
710 function Admin():int
711 {
712 return $this->isAdmin();
713 }
714
715 /**
716 * @brief Check if an user is an admin and check also his password
717 *
718 * @return 1 for yes 0 for no
719 */
720 function isAdmin():int
721 {
722 $this->admin=0;
723 $pass5=$this->password;
724 $sql="select count(*) from ac_users where use_login=$1
725 and use_active=1 and use_admin=1 and use_pass=$2 ";
726
727 $this->admin=$this->repository->get_value($sql, array($this->login,$pass5));
728 return $this->admin;
729 }
730
731 /**
732 * \brief Set the selected periode in the user's preferences
733 *
734 * \param $p_periode periode
735 * \param - $p_user
736 *
737 */
738 function set_periode($p_periode)
739 {
740 $sql="update user_local_pref set parameter_value=$1 where user_id=$2 and parameter_type='PERIODE'";
741 $Res=$this->db->exec_sql($sql, [$p_periode, $this->id]);
742 }
743
744 private function set_default_periode()
745 {
746
747 /* get the first periode */
748 $sql='select min(p_id) as pid '
749 .' from parm_periode '
750 .' where p_closed = false and p_start = (select min(p_start) from parm_periode)';
751 $Res=$this->db->exec_sql($sql);
752
753 $pid=Database::fetch_result($Res, 0, 0);
754 /* if all the periode are closed, then we use the last closed period */
755 if ($pid==null)
756 {
757 $sql='select min(p_id) as pid '
758 .'from parm_periode '
759 .'where p_start = (select max(p_start) from parm_periode)';
760 $Res2=$this->db->exec_sql($sql);
761 $pid=Database::fetch_result($Res2, 0, 0);
762 if ($pid==null)
763 {
764 throw new Exception(_("Aucune période trouvéee !!!"));
765 }
766
767 $pid=Database::fetch_result($Res2, 0, 0);
768 }
769
770 $sql=sprintf("insert into user_local_pref (user_id,parameter_value,parameter_type)
771 values ('%s','%d','PERIODE')", $this->id, $pid);
772 $Res=$this->db->exec_sql($sql);
773 }
774
775 /**
776 * \brief Get the default periode from the user's preferences
777 *
778 * \return the default periode
779 *
780 *
781 */
782 function get_periode()
783 {
784
785 $array=$this->get_preference();
786 if (!isset($array['PERIODE']))
787 {
788 $this->set_default_periode();
789 $array=$this->get_preference();
790 }
791 return $array['PERIODE'];
792 }
793
794
795 /**
796 * @brief Save the preference , the scope is global, the settings are saved
797 * into account_repository
798 * @param $key THEME, LANG , PAGESIZE
799 * @param $value value of the key
800 */
801 function save_global_preference($key, $value)
802 {
803 $count=$this->repository->get_value("select count(*)
804 from
805 user_global_pref
806 where
807 parameter_type=$1 and user_id=$2", array($key, $this->login));
808 if ($count==1)
809 {
810 $this->repository->exec_sql("update user_global_pref set parameter_value=$1
811 where parameter_type=$2 and user_id=$3", array($value, $key, $this->login));
812 }
813 elseif ($count==0)
814 {
815 $this->repository->exec_sql("insert into user_global_pref(user_id,parameter_type,parameter_value)
816 values($1,$2,$3)", array($this->login, $key, $value));
817 }
818 }
819
820 /**
821 * \brief Get the default user's preferences
822 * \return array of (parameter_type => parameter_value)
823 */
824 function get_preference()
825 {
826 $sql="select parameter_type,parameter_value from user_local_pref where user_id=$1";
827 $Res=$this->db->exec_sql($sql, array($this->id));
828 $l_array=array();
829 for ($i=0; $i<Database::num_row($Res); $i++)
830 {
831 $row=Database::fetch_array($Res, $i);
832 $type=$row['parameter_type'];
833 $l_array[$type]=$row['parameter_value'];
834 }
835 $a_global_pref=$this->repository->get_array("select parameter_type,parameter_value from user_global_pref
836 where
837 upper(user_id) = upper($1)", [$this->login]);
838 $nb_global=count($a_global_pref);
839 for ($i=0; $i<$nb_global; $i++)
840 {
841 $idx=$a_global_pref[$i]['parameter_type'];
842 $value=$a_global_pref[$i]['parameter_value'];
843 $l_array[$idx]=$value;
844 }
845
846 return $l_array;
847 }
848 /**
849 * @brief Check if an user can access a module, return 1 if yes, otherwise 0
850 * record in audit log
851 * This function works only if user is connected to a Folder
852 * @param string $p_module menu_ref.me_code
853 * @returns 0 for FORBIDDEN, 1 for GRANTED
854 */
855 function check_module($p_module)
856 {
857 if ( $this->access_mode == "PC") {
858
859 $acc=$this->db->get_value("select count(*) from v_all_menu where p_id = $1
860 and me_code=$2", array($this->get_profile(), $p_module));
861 } elseif ($this->access_mode=="MOBILE") {
862 $acc=$this->db->get_value("select count(*) from profile_mobile where p_id=$1 and me_code=$2",
863 array($this->get_profile(), $p_module));
864 } else {
865 throw new Exception("USER:823:ACCESS_MODE INCONNU");
866 }
867 if ($acc==0)
868 {
869 $this->audit("FAIL", $p_module);
870 return 0;
871 }
872 $this->audit("SUCCESS", $p_module);
873 return 1;
874 }
875
876 /**
877 * \brief Check if an user is allowed to do an action
878 * \param p_action_id
879 * \return
880 * - 0 no priv
881 * - 1 priv granted
882 * @see constant.security.php
883 */
884 function check_action($p_action_id)
885 {
886 /* save it into the log */
887 global $audit;
888 if ($this->Admin()==1)
889 return 1;
890 if ($this->is_local_admin(dossier::id())==1)
891 return 1;
892 if ($this->get_status_security_action()==0)
893 return 1;
894 $Res=$this->db->exec_sql(
895 "select * from user_sec_act where ua_login=$1 and ua_act_id=$2", array($this->login, $p_action_id));
896 $Count=Database::num_row($Res);
897 if ($Count==0)
898 {
899 if (isset($audit)&&$audit==true)
900 {
901
902 $sql="insert into audit_connect (ac_user,ac_ip,ac_module,ac_url,ac_state) values ($1,$2,$3,$4,$5)";
903 $this->repository->exec_sql($sql,
904 array($_SESSION[SESSION_KEY.'g_user'], $_SERVER["REMOTE_ADDR"], $p_action_id, $_SERVER['REQUEST_URI'],
905 'FAIL'));
906 }
907 return 0;
908 }
909 if ($Count==1)
910 return 1;
911 echo_error(_("Action invalide"));
912 record_log("User:check_action".sprintf("login %s ua_act_id %s", $this->login, $p_action_id));
913 exit();
914 }
915
916 /**
917 * \brief Get the global preferences from user_global_pref
918 * in the account_repository db
919 *
920 * \note set $SESSION[g_variable]
921 */
922 function load_global_pref()
923 {
924 // Load everything in an array
925 $Res=$this->repository->exec_sql("select parameter_type,parameter_value from
926 user_global_pref
927 where user_id=$1", [$this->login]);
928 $Max=Database::num_row($Res);
929 if ($Max==0)
930 {
931 $this->insert_default_global_pref();
932 $this->load_global_pref();
933 return;
934 }
935 // Load value into array
936 $line=array();
937 for ($i=0; $i<$Max; $i++)
938 {
939 $row=Database::fetch_array($Res, $i);
940 $type=$row['parameter_type'];
941 $line[$type]=$row['parameter_value'];
942 }
943 // save array into g_ variable
944 $array_pref=array('g_theme'=>'THEME',
945 'g_pagesize'=>'PAGESIZE',
946 'g_topmenu'=>'TOPMENU',
947 'g_lang'=>'LANG',
948 'csv_fieldsep'=>'csv_fieldsep',
949 'csv_decimal'=>'csv_decimal',
950 'csv_encoding'=>'csv_encoding',
951 'first_week_day'=>'first_week_day');
952
953 foreach ($array_pref as $name=> $parameter)
954 {
955 if (!isset($line[$parameter]))
956 {
957 $this->insert_default_global_pref($parameter);
958 $this->load_global_pref();
959 return;
960 }
961 $_SESSION[SESSION_KEY.$name]=$line[$parameter];
962 }
963 }
964
965 /**
966 * \brief insert default pref
967 * if no parameter are given insert all the existing
968 * parameter otherwise only the requested
969 * \param $p_type parameter's type or nothing
970 * \param $p_value parameter value
971 *
972 */
973 function insert_default_global_pref($p_type="", $p_value="")
974 {
975
976 $default_parameter=array("THEME"=>"classic",
977 "PAGESIZE"=>"50",
978 'TOPMENU'=>'TEXT',
979 'LANG'=>'fr_FR.utf8',
980 'csv_fieldsep'=>'0',
981 'csv_decimal'=>'0',
982 'csv_encoding'=>'utf8',
983 'first_week_day'=>1
984 );
985 $sql="insert into user_global_pref(user_id,parameter_type,parameter_value)
986 values ($1,$2,$3)";
987 if ($p_type=="")
988 {
989 foreach ($default_parameter as $name=> $value)
990 {
991 $this->repository->exec_sql($sql, array($this->login, $name, $value));
992 }
993 }
994 else
995 {
996 $value=($p_value=="")?$default_parameter[$p_type]:$p_value;
997 if ( $this->repository->get_value("select count(*) from user_global_pref where user_id=$1 and parameter_type=$2",
998 array($this->login,$p_type)) == 1)
999 {
1000 $this->repository->exec_sql("update user_global_pref set parameter_value=$1 where user_id=$2 and parameter_type=$3",
1001 array($value,$this->login,$p_type));
1002 } else {
1003 $this->repository->exec_sql($sql, array($this->login, $p_type, $value));
1004 }
1005 }
1006 }
1007
1008 /**
1009 * \brief update default pref
1010 * if value is not given then use the default value
1011 *
1012 * \param $p_type parameter's type
1013 * \param $p_value parameter's value value of the type
1014 */
1015 function update_global_pref($p_type, $p_value="")
1016 {
1017 $default_parameter=array("THEME"=>"classic",
1018 "PAGESIZE"=>"50",
1019 "LANG"=>'fr_FR.utf8',
1020 'TOPMENU'=>'SELECT',
1021 'csv_fieldsep'=>'0',
1022 'csv_decimal'=>'0',
1023 'csv_encoding'=>'utf8',
1024 'first_week_day'=>1
1025 );
1026 $Sql="update user_global_pref set parameter_value=$1
1027 where parameter_type=$2 and
1028 user_id=$3";
1029 $value=($p_value=="")?$default_parameter[$p_type]:$p_value;
1030 $this->repository->exec_sql($Sql, array($value, $p_type, $this->login));
1031 }
1032
1033//end function
1034 /**
1035 * \brief Return the year of current Periode
1036 * it is the parm_periode.p_exercice col
1037 * if an error occurs return 0
1038 */
1039
1040 function get_exercice()
1041 {
1042 $sql="select p_exercice from parm_periode where p_id=$1";
1043 $Ret=$this->db->exec_sql($sql,[$this->get_periode()]);
1044 if (Database::num_row($Ret)==1)
1045 {
1046 $r=Database::fetch_array($Ret, 0);
1047 return $r['p_exercice'];
1048 }
1049 else
1050 return 0;
1051 }
1052
1053 /**
1054 * \brief Check if the user can access
1055 * otherwise warn and exit
1056 * \param $p_action requested action
1057 * \param $p_js = 1 javascript, or 0 just a text or 2 to log it silently
1058 * \return nothing the program exits automatically
1059 */
1060
1061 function can_request($p_action, $p_js=0)
1062 {
1063 if ($this->check_action($p_action)==0)
1064 {
1065 $this->audit('FAIL');
1066 if ($p_js==1)
1067 {
1068 echo create_script("alert_box(content[59])");
1069 }
1070 elseif ($p_js==2)
1071 {
1072 record_log(_("Access invalid").$p_action);
1073 }
1074 else
1075 {
1076 echo '<h2 class="error">',
1077 htmlspecialchars(_("Cette action ne vous est pas autorisée Contactez votre responsable")),
1078 '</h2>';
1079 echo '</div>';
1080 }
1081 exit(-1);
1082 }
1083 }
1084
1085 /**
1086 * @brief Check if the user can print (in menu_ref p_type_display=p)
1087 * otherwise warn and exit
1088 * @param $p_action requested action
1089 * @return nothing the program exits automatically
1090 */
1091 function check_print($p_action)
1092 {
1093 global $audit;
1094 $this->audit('AUDIT', $p_action);
1095 if ($this->Admin()==1)
1096 return 1;
1097
1098 $res=$this->db->get_value("select count(*) from profile_menu
1099 join profile_user using (p_id)
1100 where user_name=$1 and me_code=$2 ", array($this->login, $p_action));
1101 return $res;
1102 }
1103
1104 /**
1105 * \brief Check if the user can print (in menu_ref p_type_display=p)
1106 * otherwise warn and exit
1107 * \param $p_action requested action
1108 * \return nothing the program exits automatically
1109 */
1110
1111 function can_print($p_action, $p_js=0)
1112 {
1113 if ($this->check_print($p_action)==0)
1114 {
1115 $this->audit('FAIL');
1116 if ($p_js==1)
1117 {
1118 echo create_script("alert_box(content[59])");
1119 }
1120 else
1121 {
1122 echo '<div class="redcontent">';
1123 echo '<h2 class="error">',
1124 htmlspecialchars(_("Cette action ne vous est pas autorisée Contactez votre responsable")),
1125 '</h2>';
1126 echo '</div>';
1127 }
1128 exit(-1);
1129 }
1130 }
1131
1132 /**
1133 * \brief Check if an user is an local administrator
1134 * @deprecated since version 6.7
1135 *
1136 *
1137 * \param $p_dossier : dossier_id
1138 *
1139 * \return
1140 * - 0 if no
1141 * - 1 if yes
1142 *
1143 */
1144 function is_local_admin($p_dossier=-1)
1145 {
1146 return 0;
1147 }
1148
1149 /**
1150 * @brief return array of available repository
1151 *
1152 * @param $p_access R for read W for write
1153 * @return an array
1154 */
1155 function get_available_repository($p_access='R')
1156 {
1157 $profile=$this->get_profile();
1158 $r=array();
1159 if ($p_access=='R')
1160 {
1161 $r=$this->db->get_array("select distinct u.r_id,r_name
1162 from
1163 profile_sec_repository as u
1164 join stock_repository as s on(u.r_id=s.r_id)
1165 where
1166 p_id =$1
1167 and ur_right='W'
1168 order by 2
1169 ", array($profile));
1170 }
1171 if ($p_access=='W')
1172 {
1173 $r=$this->db->get_array("select distinct u.r_id,r_name
1174 from
1175 profile_sec_repository as u
1176 join stock_repository as s on(u.r_id=s.r_id)
1177 where
1178 p_id =$1 order by 2
1179 ", array($profile));
1180 }
1181 return $r;
1182 }
1183
1184 /**
1185 * \brief return an array with all the active users who can access
1186 * $p_dossier including the global admin. The list concerns the user
1187 * in the repository of the "domain" defined in config.inc.php
1188 *
1189 * The user must be activated
1190 *
1191 * \param $p_dossier dossier
1192 * \return an array of user's object
1193 * array indices
1194 * - use_id (id )
1195 * - use_login (login of the user)
1196 * - use_name
1197 * - use_first_name
1198 * \param $db_repository ( \Database default null) database
1199 * to repository, if null is given the database will be defined in config.inc.php
1200 * \exception throw an exception if nobody can access
1201 */
1202 static function get_list($p_dossier,
1203 $db_repository = null
1204 )
1205 {
1206 $sql="select distinct use_id,use_login,use_first_name,use_name from ac_users
1207 left outer join jnt_use_dos using (use_id)
1208 where
1209 (dos_id=$1 and use_active=1) or (use_active=1 and use_admin=1)
1210 order by use_login,use_name";
1211
1212 // connect to the repository
1213 if ( $db_repository == null ) {
1214 $repo_cnx=new Database(0);
1215 } else {
1216 $repo_cnx=$db_repository;
1217 }
1218 $array=$repo_cnx->get_array($sql, array($p_dossier));
1219 if ($repo_cnx->size()==0)
1220 {
1221 throw new \Exception('noalyss_user.get_list error inaccessible folders',1186);
1222 }
1223 return $array;
1224 }
1225
1226 /**
1227 * \brief check the access of an user on a ledger
1228 *
1229 * \param $p_jrn the ledger id
1230 * \return
1231 * - O only predefined operation
1232 * - W write
1233 * - R read only
1234 * - X no access
1235 *
1236 */
1237 function check_jrn($p_jrn)
1238 {
1239 return $this->get_ledger_access($p_jrn);
1240 }
1241
1242 /**
1243 * \brief check if an user can access a folder, if he cannot display a dialog box
1244 * and exit
1245 * \param the folder if
1246 * \param $silent false, echo an error message and exit, true : exit without warning
1247 * default is false
1248 * \return
1249 * - L for administrator (local and global)
1250 * - X no access
1251 * - R regular user
1252 */
1253 function check_dossier($p_dossier_id, $silent=false)
1254 {
1255 $this->Admin();
1256 if ($this->admin==1||$this->is_local_admin($p_dossier_id)==1)
1257 return 'L';
1258
1259
1260 $dossier=$this->repository->get_value("select 'R' from jnt_use_dos where dos_id=$1 and use_id=$2",
1261 array($p_dossier_id, $this->id));
1262 $dossier=($dossier=='')?'X':$dossier;
1263 if ($dossier=='X')
1264 {
1265 $this->audit('FAIL', "Access folder ");
1266 if (!$silent)
1267 {
1268 alert(_('Dossier non accessible'));
1269 exit();
1270 }
1271 }
1272 return $dossier;
1273 }
1274
1275 /**
1276 * @brief return the first date and the last date of the current exercice for the current user
1277 * @return and array ([0] => start_date,[1] => end_date)
1278 */
1279 function get_limit_current_exercice()
1280 {
1281 $current_exercice=$this->get_exercice();
1282 $periode=new Periode($this->db);
1283 list($per_start, $per_end)=$periode->get_limit($current_exercice);
1284 $start=$per_start->first_day();
1285 $end=$per_end->last_day();
1286 return array($start, $end);
1287 }
1288
1289 /**
1290 * \brief Show all the available folder for the users
1291 * at the login page. For the special case 'E'
1292 * go directly to extension and bypasse the dashboard
1293 * \param $p_filtre user
1294 *
1295 * \return table in HTML
1296 *
1297 */
1298 function show_dossier($p_filtre="")
1299 {
1300 $p_array=$this->get_available_folder($p_filtre);
1301
1302 $result="";
1303
1304 $result.="<TABLE id=\"folder\" class=\"result\">";
1305 $result.="<tr>";
1306 $result.="<th>";
1307 $result.=_("Id");
1308 $result.="</th>";
1309 $result.="<th>";
1310 $result.=_("Nom");
1311 $result.="</th>";
1312 $result.="<th>";
1313 $result.=_("Description");
1314 $result.="</th>";
1315 $result.="</tr>";
1316 if ($p_array==0)
1317 {
1318 $result.="<tr>";
1319 $result.='<td style="width:auto" colspan=3>';
1320 $result.=_("Aucun dossier disponible");
1321 $result.='</td>';
1322 $result.="</tr>";
1323 return $result;
1324 }
1325
1326 for ($i=0; $i<sizeof($p_array); $i++)
1327 {
1328
1329 $id=$p_array[$i]['dos_id'];
1330 $name=$p_array[$i]['dos_name'];
1331 $desc=$p_array[$i]['dos_description'];
1332 if ($i%2==0)
1333 $tr="odd";
1334 else
1335 $tr="even";
1336 $target="do.php?gDossier=$id";
1337
1338 $result.="<TR class=\"$tr\">";
1339
1340 $result.=td($id, ' class="num" ');
1341 $result.="<TD class=\"$tr\">";
1342 $result.="<A class=\"dossier\" HREF=\"$target\">";
1343 $result.=" <B>".h($name)."</B>";
1344 $result.="</A>";
1345 $result.="</TD>";
1346 $desc=($desc=="")?"<i>Aucune description</i>":h($desc);
1347 $desc="<A class=\"dossier\" HREF=\"$target\">$desc</A>";
1348 $result.="<TD class=\"$tr\" >".$desc;
1349 $result.="</TD>";
1350 $result.="</TR>";
1351 }
1352 $result.="</TABLE>";
1353 return $result;
1354 }
1355
1356 /**
1357 * \brief Get all the available folders
1358 * for the users, checked with the security
1359 *
1360 * \param $p_filter
1361 * \return array containing
1362 * - ac_dossier.dos_id
1363 * - ac_dossier.dos_name
1364 * - ac_dossier.dos_description
1365 *
1366 */
1367 function get_available_folder($p_filter="")
1368 {
1369 $cn=$this->repository;
1370 $filter="";
1371 if ($this->admin==0)
1372 {
1373 // show only available folders
1374 // if user is not an admin
1375 $Res=$this->repository->exec_sql("select
1376 distinct dos_id,dos_name,dos_description
1377 from ac_users
1378 natural join jnt_use_dos
1379 natural join ac_dossier
1380 where
1381 use_login= $1
1382 and use_active = 1
1383 and ( dos_name ilike '%' || $2 || '%' or dos_description ilike '%' || $2 || '%' )
1384 order by dos_name", array($this->login, $p_filter));
1385 }
1386 else
1387 {
1388 $Res=$this->repository->exec_sql("select
1389 distinct dos_id,dos_name,dos_description from ac_dossier
1390 where
1391 dos_name ilike '%' || $1|| '%' or dos_description ilike '%' || $1 || '%'
1392 order by dos_name", array($p_filter));
1393 }
1394
1395 $max=Database::num_row($Res);
1396 if ($max==0)
1397 return 0;
1398
1399 for ($i=0; $i<$max; $i++)
1400 {
1401 $array[]=Database::fetch_array($Res, $i);
1402 }
1403 return $array;
1404 }
1405
1406 /**
1407 * @brief Audit action from the administration menu.
1408 * Connect to the repository of the domain defined in config.inc.php
1409 * @param $p_module description of the action
1410 * @param $db_repository ( \Database default null) database
1411 * to repository, if null is given the database will be defined in config.inc.php
1412 */
1413 static function audit_admin($p_module,$db_repository=null)
1414 {
1415 // connect to the repository
1416 if ( $db_repository == null ) {
1417 $repo_cnx=new Database(0);
1418 } else {
1419 $repo_cnx=$db_repository;
1420 }
1421 $sql="insert into audit_connect (ac_user,ac_ip,ac_module,ac_url,ac_state) values ($1,$2,$3,$4,$5)";
1422
1423 $repo_cnx->exec_sql($sql,
1424 array(
1425 $_SESSION[SESSION_KEY.'g_user'],
1426 $_SERVER["REMOTE_ADDR"],
1427 $p_module,
1428 $_SERVER['REQUEST_URI'],
1429 'ADMIN'));
1430 }
1431
1432 function audit($action='AUDIT', $p_module="")
1433 {
1434 global $audit;
1435 $http=new \HttpInput();
1436 if ($audit)
1437 {
1438 if ($p_module==""&&isset($_REQUEST['ac']))
1439 {
1440 $p_module=$_REQUEST['ac'];
1441 }
1442 $dossier=$http->request("gDossier","string",0);
1443 if ( $dossier != 0)
1444 $p_module.=" dossier : ".$dossier;
1445
1446 $sql="insert into audit_connect (ac_user,ac_ip,ac_module,ac_url,ac_state) values ($1,$2,$3,$4,$5)";
1447
1448 $this->repository->exec_sql($sql,
1449 array(
1450 $_SESSION[SESSION_KEY.'g_user'],
1451 $_SERVER["REMOTE_ADDR"],
1452 $p_module,
1453 $_SERVER['REQUEST_URI'],
1454 $action));
1455 }
1456 }
1457
1458 function save_profile($p_id)
1459 {
1460 $count=$this->db->get_value("select count(*) from profile_user where user_name=$1", array($this->login));
1461 if ($count==0)
1462 {
1463 $this->db->exec_sql("insert into profile_user(p_id,user_name)
1464 values ($1,$2)", array($p_id, $this->login));
1465 }
1466 else
1467 {
1468 $this->db->exec_sql("update profile_user set p_id=$1 where user_name=$2", array($p_id, $this->login));
1469 }
1470 }
1471
1472 /**
1473 * @brief return the profile (p_id)
1474 * @return profile.p_id
1475 */
1476 function get_profile()
1477 {
1478 $profile=$this->db->get_value("select p_id from profile_user where
1479 lower(user_name)=lower($1) ", array($this->login));
1480 return $profile;
1481 }
1482
1483 /**
1484 * @brief Compute the SQL string for the writable profile,
1485 * the subselect for p_id , example
1486 * p_id in $g_user->sql_writable_profile.
1487 * The administrator can access all the profiles
1488 * R = Read Only W = Write and delete O = write and not delete
1489 * @return SQL string with the subselect for p_id
1490 */
1491 function sql_writable_profile()
1492 {
1493 if ($this->admin!=1)
1494 {
1495 $sql=" (select p_granted "
1496 ." from user_sec_action_profile "
1497 ." where ua_right in ('W','O') and p_id=".$this->get_profile().") ";
1498 }
1499 else
1500 {
1501 $sql="(select p_id p_granted from profile)";
1502 }
1503 return $sql;
1504 }
1505 /**
1506 * @brief return array of writable action_profile
1507 *
1508 */
1509 function get_writable_profile()
1510 {
1511 $value=$this->db->get_array("select p_granted from ".$this->sql_writable_profile()." as m") ;
1512 $aGranted=array_column($value,"p_granted");
1513 return $aGranted;
1514 }
1515 /**
1516 * @brief return array of readable action_profile
1517 *
1518 */
1519 function get_readable_profile()
1520 {
1521 $value=$this->db->get_array("select p_granted from ".$this->sql_readable_profile()." as m") ;
1522 $aGranted=array_column($value,"p_granted");
1523 return $aGranted;
1524 }
1525 /**
1526 *@brief Compute the SQL string for the readable profile,
1527 * the subselect for p_id , example
1528 * p_id in $g_user->sql_readable_profile.
1529 * The administrator can read all the profiles
1530 * @return SQL string with the subselect for p_id
1531 */
1532 function sql_readable_profile()
1533 {
1534 if ($this->admin!=1)
1535 {
1536 $sql=" (select p_granted "
1537 ." from user_sec_action_profile "
1538 ." where ua_right in ('W','R','O') and p_id=".$this->get_profile().") ";
1539 }
1540 else
1541 {
1542 $sql="(select p_id p_granted from profile)";
1543 }
1544 return $sql;
1545 }
1546
1547 /**
1548 * @brief Check if the current user can add an action in the profile given
1549 * in parameter
1550 * @param type $p_profile profile.p_id = action_gestion.ag_dest
1551 * @return boolean
1552 */
1553 function can_add_action($p_profile)
1554 {
1555
1556 $r=$this->db->get_value(' select count(*)
1557 from user_sec_action_profile
1558 where p_granted=$2
1559 and p_id=$1', array($this->get_profile(), $p_profile));
1560 if ($r==0)
1561 {
1562 return false;
1563 }
1564 return true;
1565 }
1566
1567 /**
1568 * @brief Check if the profile of the user can write for this profile
1569 * @param $dtoc action_gestion.ag_id
1570 * @return true if he can write otherwise false
1571 */
1572 function can_write_action($dtoc)
1573 {
1574 if ($this->Admin()==1)
1575 return TRUE;
1576 if ($this->get_status_security_action()==0)
1577 return TRUE;
1578 $profile=$this->get_profile();
1579 $r=$this->db->get_value(" select count(*) from action_gestion where ag_id=$1 and ag_dest in
1580 (select p_granted from user_sec_action_profile where ua_right in ('W','O') and p_id=$2) ", array($dtoc, $profile));
1581 if ($r==0)
1582 return FALSE;
1583 return true;
1584 }
1585
1586 /**
1587 * @brief Check if the profile of the user can write AND delete for this profile
1588 * @param $dtoc action_gestion.ag_id
1589 * @return true if he can write otherwise false
1590 */
1591 function can_delete_action($dtoc)
1592 {
1593 if ($this->Admin()==1)
1594 return TRUE;
1595 if ($this->get_status_security_action()==0)
1596 return TRUE;
1597 $profile=$this->get_profile();
1598 $r=$this->db->get_value(" select count(*) from action_gestion where ag_id=$1 and ag_dest in
1599 (select p_granted from user_sec_action_profile where ua_right='W' and p_id=$2) ", array($dtoc, $profile));
1600 if ($r==0)
1601 return FALSE;
1602 return true;
1603 }
1604
1605 /**
1606 * @brief Check if the profile of the user can write for this profile
1607 * @param $dtoc action_gestion.ag_id
1608 * @return true if he can write otherwise false
1609 */
1610 function can_read_action($dtoc)
1611 {
1612 if ($this->Admin()==1)
1613 return true;
1614 $profile=$this->get_profile();
1615 $r=$this->db->get_value(" select count(*) from action_gestion where ag_id=$1 and (ag_dest in
1616 (select p_granted from user_sec_action_profile where p_id=$2) or ag_owner=$3)",
1617 array($dtoc, $profile, $this->login));
1618 if ($r==0)
1619 return false;
1620 return true;
1621 }
1622
1623 /**
1624 * @brief Check if the profile of the user can write for this repository
1625 * @param $p_repo stock_repository.r_id
1626 * @return true if he can write otherwise false
1627 */
1628 function can_write_repo($p_repo)
1629 {
1630 if ($this->Admin()==1)
1631 return true;
1632 $profile=$this->get_profile();
1633 $r=$this->db->get_value("select count(*)
1634 from profile_sec_repository
1635 where
1636 r_id=$1
1637 and p_id =$2
1638 and ur_right='W'", array($p_repo, $profile));
1639 if ($r==0)
1640 return false;
1641 return true;
1642 }
1643
1644 /**
1645 * @brief Check if the profile of the user can read for this repository
1646 * @param $p_repo stock_repository.r_id
1647 * @return true if he read write otherwise false
1648 */
1649 function can_read_repo($p_repo)
1650 {
1651 if ($this->Admin()==1)
1652 return true;
1653 $profile=$this->get_profile();
1654 $r=$this->db->get_value("select count(*)
1655 from profile_sec_repository
1656 where
1657 r_id=$1
1658 and p_id =$2
1659 ", array($p_repo, $profile));
1660 if ($r==0)
1661 return false;
1662 return true;
1663 }
1664 /**
1665 * @brief store the password in session
1666 */
1667 function password_to_session()
1668 {
1669 $_SESSION[SESSION_KEY.'g_pass']=$this->getPassword();
1670 }
1671 /**
1672 * @brief Save the password of the current user
1673 * @param string $p_pass1 password (clear)
1674 * @param string $p_pass2 for confirming password (clear)
1675 * @see check_password_strength()
1676 * @return true : password successfully changed otherwise false
1677 */
1678 function save_password($p_pass1, $p_pass2)
1679 {
1680 if ($p_pass1==$p_pass2 && count(check_password_strength($p_pass1)['msg'])==0)
1681 {
1682
1683 $l_pass=md5($p_pass1);
1684 $this->setPassword($l_pass);
1685 $this->repository->exec_sql("update ac_users set use_pass=$1 where use_login=$2",
1686 array($l_pass, $this->login));
1687 return true;
1688 }
1689 else
1690 {
1691
1692 return false;
1693 }
1694 }
1695
1696 /**
1697 * @brief Save the password from PREFERENCE MODULE
1698 * @param type $p_email
1699 */
1700 function save_email($p_email)
1701 {
1702 $this->repository->exec_sql("update ac_users set use_email=$1 where use_login=$2",
1703 array($p_email, $_SESSION[SESSION_KEY.'g_user']));
1704 }
1705
1706 /**
1707 *@brief Remove a user and all his privileges
1708 * So it cannot connect anymore and all his privileges are removed from
1709 * the dossier.
1710 * @param $p_login (String) login
1711 * @param $p_dossier (int) dossier id
1712 * @param $db_repository ( \Database default null) database
1713 * to repository, if null is given the database will be defined in config.inc.php
1714 *
1715 */
1716 static function revoke_access($p_login, $p_dossier,$db_repository=null)
1717 {
1718 // connect to the repository
1719 if ( $db_repository == null ) {
1720 $repo_cnx=new Database(0);
1721 } else {
1722 $repo_cnx=$db_repository;
1723 }
1724
1725 // Retrieve the user
1726 $user=$repo_cnx->get_array('select use_id,use_login from ac_users where use_login=$1', array($p_login));
1727 if (!$user)
1728 return false;
1729
1730 // remove him from jnt_use_dos
1731 $repo_cnx->exec_sql("delete from jnt_use_dos WHERE use_id=$1 and dos_id=$2",
1732 array($user[0]['use_id'], $p_dossier));
1733
1734 // Remove user from user's dossier
1735 $cn_dossier=new Database($p_dossier);
1736 $cn_dossier->exec_sql("delete from profile_user where user_name=$1", array($p_login));
1737 $cn_dossier->exec_sql("delete from user_sec_act where ua_login=$1", array($p_login));
1738 }
1739
1740 /**
1741 * @brief Grant access to folder, grant administrator profile , all the ledgers and all the action
1742 * @param $p_login (String) login
1743 * @param $p_dossier (int) dossier id
1744 * @param $db_repository ( \Database default null) database
1745 * to repository, if null is given the database will be defined in config.inc.php
1746 */
1747 static function grant_admin_access($p_login, $p_dossier,$db_repository=null)
1748 {
1749 // connect to the repository
1750 if ( $db_repository == null ) {
1751 $repo_cnx=new Database(0);
1752 } else {
1753 $repo_cnx=$db_repository;
1754 }
1755 $user=$repo_cnx->get_array("select use_id,use_login
1756 from ac_users
1757 where use_login=$1", array($p_login));
1758
1759 if (!$user)
1760 return false;
1761 $cn_dossier=new Database($p_dossier);
1762 // if not access to DB
1763 if (
1764 $repo_cnx->get_value("select count(*) from jnt_use_dos where use_id=$1 and dos_id=$2",
1765 array($user[0]['use_id'], $p_dossier))==0
1766 )
1767 {
1768 $repo_cnx->exec_sql("insert into jnt_use_dos(use_id,dos_id) values ($1,$2)",
1769 array($user[0]['use_id'], $p_dossier));
1770 }
1771 //------ Give him the admin menu
1772 if ($cn_dossier->get_value("select count(*) from profile_user where user_name=$1", array($user[0]['use_login']))==0)
1773 {
1774 $cn_dossier->exec_sql('insert into profile_user(user_name,p_id) values($1,1)', array($user[0]['use_login']));
1775 }
1776 // Grant all action + ledger to him
1777 $cn_dossier->exec_sql("delete from user_sec_act where ua_login=$1", array($p_login));
1778
1779 $cn_dossier->exec_sql("insert into user_sec_act (ua_login,ua_act_id)"
1780 ." select $1 ,ac_id from action ", array($p_login));
1781
1782 $cn_dossier->exec_sql("delete from user_sec_jrn where uj_login=$1", array($p_login));
1783 $cn_dossier->exec_sql("insert into user_sec_jrn(uj_login,uj_jrn_id,uj_priv)"
1784 ." select $1,jrn_def_id,'W' from jrn_def", array($p_login));
1785 }
1786 /**
1787 * @brief cleansing : remove inexistant user
1788 * @param $p_dossier (int) dossier id
1789 * @param $db_repository ( \Database default null) database
1790 * to repository, if null is given the database will be defined in config.inc.php
1791 * @return bool : true if success , false if no change
1792 */
1793 static function remove_inexistant_user($p_dossier,$db_repository=null)
1794 {
1795 // connect to the repository
1796 if ( $db_repository == null ) {
1797 $cnx_repo=new Database(0);
1798 } else {
1799 $cnx_repo=$db_repository;
1800 }
1801 $name=$cnx_repo->format_name($p_dossier, 'dos');
1802 if ($cnx_repo->exist_database($name)==0)
1803 return false;
1804 $cnx_dossier=new Database($p_dossier);
1805 if ($cnx_dossier->exist_table('profile_user'))
1806 $a_user=$cnx_dossier->get_array('select user_name from profile_user');
1807 else
1808 return false;
1809
1810 if (!$a_user)
1811 return;
1812 $nb=count($a_user);
1813 for ($i=0; $i<$nb; $i++)
1814 {
1815 if ($cnx_repo->get_value('select count(*) from ac_users where use_login=$1', array($a_user[$i]['user_name']))==0)
1816 {
1817 if ($cnx_dossier->exist_table('user_sec_jrn'))
1818 $cnx_dossier->exec_sql("delete from user_sec_jrn where uj_login=$1", array($a_user[$i]['user_name']));
1819 $cnx_dossier->exec_sql("delete from profile_user where user_name=$1", array($a_user[$i]['user_name']));
1820 if ($cnx_dossier->exist_table('user_sec_act'))
1821 $cnx_dossier->exec_sql("delete from user_sec_act where ua_login=$1", array($a_user[$i]['user_name']));
1822 if ($cnx_dossier->exist_table('user_sec_jrn'))
1823 $cnx_dossier->exec_sql("delete from user_sec_jrn where uj_login=$1", array($a_user[$i]['user_name']));
1824 if ($cnx_dossier->exist_table('user_active_security'))
1825 $cnx_dossier->exec_sql("delete from user_active_security where us_login=$1",
1826 array($a_user[$i]['user_name']));
1827 }
1828 }
1829 return true;
1830 }
1831
1832 /**
1833 * @brief Check the security on ledger for the user , it returns 1 if the security
1834 * on ledgers is enabled, otherwise 0
1835 */
1837 {
1838 $security=$this->db->get_value("select us_ledger from user_active_security
1839 where
1840 us_login=$1", [$this->login]);
1841 $n_security=($security=="Y")?1:0;
1842 return $n_security;
1843 }
1844
1845 /**
1846 * @brief Set the flag in the table user_active_security
1847 * @param int $p_value 1==enable , 0 = disable
1848 * @exceptions invalid value
1849 */
1851 {
1852 if ($p_value!=0&&$p_value!=1)
1853 throw new Exception(_("Valeur invalide"));
1854 $exist=$this->db->get_value("select count(*) from user_active_security where us_login=$1", [$this->login]);
1855 $flag=($p_value==1)?"Y":"N";
1856 if ($exist==0)
1857 {
1858 $this->db->exec_sql("insert into user_active_security (us_login,us_ledger,us_action) values ($1,$2,$3)",
1859 [$this->login, $flag, 'Y']);
1860 }
1861 else
1862 {
1863 $this->db->exec_sql("update user_active_security set us_ledger=$1 where us_login = $2",
1864 [$flag, $this->login]);
1865 }
1866 }
1867
1868 /**
1869 * Check the security on ledger for the user , it returns 1 if the security
1870 * on ledgers is enabled, otherwise 0
1871 */
1873 {
1874 $security=$this->db->get_value("select us_action from user_active_security
1875 where
1876 us_login=$1", [$this->login]);
1877 $n_security=($security=="Y")?1:0;
1878 return $n_security;
1879 }
1880
1881 /**
1882 * Set the flag in the table user_active_security
1883 * @param int $p_value 1==enable , 0 = disable
1884 * @exceptions invalid value
1885 */
1887 {
1888 if ($p_value!=0&&$p_value!=1)
1889 throw new Exception(_("Valeur invalide"));
1890 $exist=$this->db->get_value("select count(*) from user_active_security where us_login=$1", [$this->login]);
1891 $flag=($p_value==1)?"Y":"N";
1892 if ($exist==0)
1893 {
1894 $this->db->exec_sql("insert into user_active_security (us_login,us_action,us_ledger) values ($1,$2,$3)",
1895 [$this->login, $flag, 'Y']);
1896 }
1897 else
1898 {
1899 $this->db->exec_sql("update user_active_security set us_action=$1 where us_login = $2",
1900 [$flag, $this->login]);
1901 }
1902 }
1903
1904 /**
1905 *@brief first day in calendar
1906 * @see IDate::set_firstDate(
1907 */
1909 {
1910
1911 $result=$this->repository->get_value("select parameter_value from user_global_pref where parameter_type=$1 and user_id=$2 ",
1912 array("first_week_day", $this->login));
1913 if ($this->repository->count()==0)
1914 {
1915 $this->save_global_preference("first_week_day", 1);
1916 return 1;
1917 }
1918 return $result;
1919 }
1920 /**
1921 * @brief clean the sessions
1922 */
1923 static function clean_session()
1924 {
1925
1926 $aSession=$_SESSION;
1927 foreach($aSession as $key => $value) {
1928 if(DEBUGNOALYSS>1) { echo "[$key]=>[$value]";}
1929
1930 if ( strpos($key,SESSION_KEY) === 0) {
1931 unset($_SESSION[$key]);
1932 if(DEBUGNOALYSS>1) { echo "=> [$key] cleaned";}
1933 }
1934 }
1935 }
1936 /**
1937 *@brief Get preference , either the user see the numeric id for VAT or its code, if the preference doesn't exist
1938 * by default , 0 is saved in ACCOUNT_REPOSITORY
1939 * @see ITva_Popup::set_vat_code()
1940 * @see ITva_Popup
1941 *
1942 */
1944 {
1945
1946
1947 $result=$this->repository->get_value("select parameter_value from user_global_pref where parameter_type=$1 and user_id=$2 ",
1948 array("vat_code", $this->login));
1949 if ($this->repository->count()==0)
1950 {
1951 $this->save_global_preference("vat_code", 0);
1952 return 0;
1953 }
1954 return $result;
1955 }
1956 /**
1957 * @brief generate OTP secret to store in AC_USER.USE_OTP_SECRET
1958 */
1959 function generate_otp()
1960 {
1961 $otp=new \Noalyss\OTP();
1962 $this->otp_secret=$otp->build_secret();
1963 }
1964 /**
1965 * @brief retrieve authent_method
1966 * - 0 password
1967 * - 1 password + code by email
1968 * - 2 password + OTP from application
1969 */
1970 public function get_authent_method() {
1971 return $this->authent_method;
1972 }
1973
1974 public function get_otp_secret() {
1975 return $this->otp_secret;
1976 }
1977
1978
1980 $this->authent_method = $authent_method;
1981 return $this;
1982 }
1983
1984 public function set_otp_secret($otp_secret) {
1985 $this->otp_secret = $otp_secret;
1986 return $this;
1987 }
1988 public function set_identified()
1989 {
1990 $_SESSION[SESSION_KEY."db_auth"]='ok';
1991 }
1992 /**
1993 * @brief check is the double authentication has been successful
1994 * @return bool
1995 */
1996 public function is_double_identified() {
1997
1998 if ( $this->authent_method == 0 )
1999 {
2000 $_SESSION[SESSION_KEY."db_auth"]='ok';
2001 return true;
2002 }
2003 if ( ! isset($_SESSION[SESSION_KEY."db_auth"])) {
2004 return false;
2005 }
2006 if ($_SESSION[SESSION_KEY."db_auth"] == "ok") {
2007 return true;
2008 }
2009 return false;
2010 }
2011 /**
2012 * @brief send a code to the user and save the expected code + UUID in
2013 * a table OTP_SEND_SECRET
2014 * @return bool false if fails true if succeeds
2015 * @throws \Exception
2016 */
2017 public function send_code_otp()
2018 {
2019 if ( $this->authent_method !=1 ) { return false; }
2020 $mail=new \Sendmail();
2021 $mail->set_format("HTML");
2022 $mail->set_from(ADMIN_WEB);
2023 $mail->mailto($this->getEmail());
2024 $mail->set_subject(_("NOALYSS : votre code secret "));
2025 $noalyss_url=NOALYSS_URL;
2026
2027
2028 if ( strlen(trim($this->otp_secret??"")) == 0 ) {
2029 throw new \Exception("noalyss_user.send_code_otp:secret empty",1945);
2030 }
2031 $otp=new \Noalyss\OTP();
2032 $code=$otp->compute_code($this->otp_secret);
2033 $message="<p>Bonjour,
2034 <br>
2035 <br>
2036 <p>Voici votre code secret utilisable pendant 10 minutes pour NOALYSS : <b> $code</b> .
2037 </p>
2038
2039 <p>
2040 Merci d'utiliser NOALYSS
2041 <br/>
2042 <br/>
2043 <br/>
2044
2045Cordialement,
2046 <br/>
2047 <br/>
2048
2049Noalyss team
2050 </p>
2051
2052 <p>
2053 <i> Si cet email est dans vos spams, ajoutez l'expéditeur dans votre carnet d'adresse</i>
2054 </p>
2055";
2056 try {
2057 $uuid= guidv4();
2058 // remove old for this user
2059 $this->repository->exec_sql("delete from otp_send_secret where use_id=$1 and os_code is not null"
2060 ,[$this->id]);
2061 // remove also old one
2062 $this->repository->exec_sql("delete from otp_send_secret where os_valid_time < now()");
2063 $now=new \DateTime();
2064 $valid=new \DateTime();
2065 $valid->modify('+10 minutes');
2066
2067 $otp_send_secret=new Otp_Send_Secret_SQL($this->repository);
2068 $otp_send_secret->set("use_id",$this->id)
2069 ->set('os_request',$uuid)
2070 ->set("os_code",$code)
2071 ->set('os_valid_time',$valid->format('d.m.Y H:i:s'));
2072 $otp_send_secret->save();
2073 $mail->set_message($message);
2074 $mail->compose();
2075 $mail->send();
2076 return $uuid;
2077 } catch (Exception $ex) {
2078 \record_log ($ex);
2079 throw new \Exception("noalyss_user.send_code_otp",1963,$ex);
2080 }
2081 }
2082 /**
2083 * @brief send an email with link to the user
2084 * @param $base_url (string) http url to scan the QRCode, the url in the
2085 * mail will be {$base_url}/index.php?otp={$uuid}
2086 */
2087 function send_link_otp($base_url=null) {
2088 $mail = new \Sendmail();
2089 $mail->set_format("HTML");
2090 $mail->set_from(ADMIN_WEB);
2091 $mail->mailto($this->getEmail());
2092 $mail->set_subject(_("NOALYSS : Double authentification lien pour 2FA: OTP"));
2093 $noalyss_url = $base_url??NOALYSS_URL;
2094 $uuid = guidv4();
2095 $valid_time=new \DateTime();
2096 $valid_time->add(new \DateInterval('PT12H'));
2097 $str_time=$valid_time->format('d-m-Y H:i');
2098 /**
2099 * save in DB first
2100 */
2101 $message = "<p>Bonjour,</p>
2102<p>
2103 Afin de pouvoir utiliser la double authentification avec 2FA: OTP, pourriez-vous
2104 suivre ce lien et scanner le QRCode avec votre application android freeOTP ou Google Authenticator.
2105 </p>
2106 <p>Ce lien expirera le <b>{$str_time}</b>.
2107 <br>
2108 <br>
2109 <br>
2110
2111 <a href=\"{$noalyss_url}/index.php?otp={$uuid}\">{$noalyss_url}/index.php?otp={$uuid}</a>
2112 </p>
2113
2114 <p>
2115
2116 Merci d'utiliser NOALYSS
2117 </p>
2118
2119<p>
2120Bien cordialement,
2121</p>
2122 <p>
2123 <i> Si cet email est dans vos spams, ajoutez l'expéditeur dans votre carnet d'adresse</i>
2124 </p>
2125";
2126 try {
2127
2128 // remove old for this user
2129 $this->repository->exec_sql("delete from otp_send_secret where use_id=$1 and os_code is null"
2130 ,[$this->id]);
2131 // remove also old one
2132 $this->repository->exec_sql("delete from otp_send_secret where os_valid_time < now()");
2133
2134 $otp_send_secret_sql = new \Otp_Send_Secret_SQL($this->repository);
2135 $otp_send_secret_sql->set('use_id', $this->id)
2136 ->set('os_valid_time',$valid_time->format('d-m-Y H:i'))
2137 ->set('os_request', $uuid);
2138
2139 $otp_send_secret_sql->save();
2140 $mail->set_message($message);
2141 $mail->compose();
2142 $mail->send();
2143 return $uuid;
2144 } catch (Exception $ex) {
2146 throw new \Exception("noalyss_user.send_link_otp",1998,$ex);
2147 }
2148 }
2149 /**
2150 * @brief FORM to enter the 6 digit enter by OTP
2151 * @param $uuid (string UUID) UUID in the message, null if there is no message
2152 */
2153 function input_otp($uuid="",$url="")
2154 {
2155 require_once NOALYSS_TEMPLATE."/noalyss_user-input_otp.php" ;
2156 }
2157 /**
2158 * @brief check that the OTP code is the one on smartphone
2159 * returns false if the given does not match the OTP
2160 */
2162 {
2163 $otp=new \Noalyss\OTP();
2164
2165 if ( $otp->compute_code($this->otp_secret) == $code ) {
2166 return true;
2167 }
2168 return false;
2169 }
2170}
2171
2172?>
h2($p_string, $p_class="", $raw="")
Definition ac_common.php:68
guidv4($data=null)
generate an UUID
record_log($p_message)
Record an error message into the log file of the server or in the log folder of NOALYSS Record also t...
td($p_string='', $p_extra='')
surround the string with td
Definition ac_common.php:83
$sql_array['query']
catch(Exception $exc) if(! $g_user->can_write_action($ag_id)) $r
if(!headers_sent())
– pour utiliser unoconv démarrer un server libreoffice commande libreoffice –headless –accept="socket...
$profile p_id
$anc_grandlivre from
$opd_description style
margin jrn_def_id
$from
$from_poste name
_("actif, passif,charge,...")
$ex
static escape_string($p_string)
wrapper for the function pg_escape_string
static fetch_array($ret, $p_indice=0, $p_mode=PGSQL_ASSOC)
wrapper for the function pg_fetch_array
static num_row($ret)
wrapper for the function pg_num_rows
contains the class for connecting to Noalyss
manage the current dossier, everywhere we need to know to which folder we are connected,...
Data & function about connected users.
set_repository(Database $repository)
set the repository
generate_otp()
generate OTP secret to store in AC_USER.USE_OTP_SECRET
get_vat_code_preference()
Get preference , either the user see the numeric id for VAT or its code, if the preference doesn't ex...
$login
login lower case
is_double_identified()
check is the double authentication has been successful
set_status_security_ledger($p_value)
Set the flag in the table user_active_security.
get_access_mode()
access_mode tells what mode must be used : pc or mobile
get_status_security_action()
Check the security on ledger for the user , it returns 1 if the security on ledgers is enabled,...
$id
in account_repository , ac_users.use_id
set_status_security_action($p_value)
Set the flag in the table user_active_security.
get_status_security_ledger()
Check the security on ledger for the user , it returns 1 if the security on ledgers is enabled,...
static grant_admin_access($p_login, $p_dossier, $db_repository=null)
Grant access to folder, grant administrator profile , all the ledgers and all the action.
set_authent_method($authent_method)
set_session_var()
put user_login into Postgres config (session), it can be used for tracking users activities
$active
1 active , 0 disables
get_first_week_day()
first day in calendar
$admin
is or is not admin
get_repository()
get the repository
$theme
user's CSS Theme
get_authent_method()
retrieve authent_method
$lang
user's language
$last_name
user's last_name
$password
md5 of the password
$access_mode
MOBILE or PC depending if when connecting $login contains @mobile.
Check($silent=false, $from='')
Check if user is active and exists in therepository Automatically redirect, it doesn't check if a use...
$authent_method
authentication method use for this user
$db
database connx to the folder NOT repository
__construct($p_cn, $p_id=-1, $repository=null)
Create an user , load an existing one or if p_id == -1 search for the connected user.
send_link_otp($base_url=null)
send an email with link to the user
load_global_pref()
Get the global preferences from user_global_pref in the account_repository db.
save_global_preference($key, $value)
Save the preference , the scope is global, the settings are saved into account_repository.
set_otp_secret($otp_secret)
static clean_session()
clean the sessions
send_code_otp()
send a code to the user and save the expected code + UUID in a table OTP_SEND_SECRET
set_access_mode($access_mode)
access_mode tells what mode must be used : pc or mobile
setLogin(string $login)
check_otp($code)
check that the OTP code is the one on smartphone returns false if the given does not match the OTP
input_otp($uuid="", $url="")
FORM to enter the 6 digit enter by OTP.
can_connect()
check the password and user
static remove_inexistant_user($p_dossier, $db_repository=null)
cleansing : remove inexistant user
connect_user()
connect the user and set the $_SESSION variables if not set thanks the $_REQUEST
setFirstName($first_name)
$repository
account_repository (\Database )
$otp_secret
string use as secret for OTP
$valid
is or is not valid
abstract of the table public.otp_send_secret
const ALL
Definition constant.php:210
for($e=0; $e< count($afiche); $e++) exit
$SecUser db
$flag
Definition install.php:535
$valid
Definition recover.php:57
if(count($exist_request)> 1) $mail
Definition recover.php:100
$message
Definition recover.php:106
$noalyss_url
Definition recover.php:105
redirect( $p_string, $p_time=0)
redirect with javascript