Improve : tighten the security + cosmetic set double authentication : create, send link, usable with Google Authenticator and FreeOTP 1. OTP : prevent direct access without going throught the 2FA mechanism 2. Go back to the url where you were disconnected 3. Cosmetic
2069 lines
64 KiB
PHP
2069 lines
64 KiB
PHP
<?php
|
|
use chillerlan\Authenticator\{Authenticator, AuthenticatorOptions};
|
|
use chillerlan\Authenticator\Authenticators\AuthenticatorInterface;
|
|
/*
|
|
* This file is part of NOALYSS.
|
|
*
|
|
* NOALYSS is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* NOALYSS is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with NOALYSS; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
// Copyright Author Dany De Bontridder danydb@aevalys.eu
|
|
/**
|
|
* @file
|
|
* @brief Data & function about connected users
|
|
*/
|
|
/**
|
|
* @brief Data & function about connected users
|
|
*
|
|
*/
|
|
require_once NOALYSS_INCLUDE.'/constant.php';
|
|
require_once NOALYSS_INCLUDE.'/lib/user_common.php';
|
|
require_once NOALYSS_INCLUDE.'/lib/ac_common.php';
|
|
|
|
class Noalyss_User
|
|
{
|
|
|
|
var $id; //!< in account_repository , ac_users.use_id
|
|
|
|
var $db; //!< database connx to the folder NOT repository
|
|
var $admin; //!< is or is not admin
|
|
var $valid; //!< is or is not valid
|
|
var $first_name;
|
|
var $last_name ; //!< user's last_name
|
|
var $name;
|
|
var $active; //!< 1 active , 0 disables
|
|
var $login; //!< login lower case
|
|
var $password; //!< md5 of the password
|
|
var $email; //!< user's email
|
|
var $access_mode; //!< MOBILE or PC depending if when connecting $login contains @mobile
|
|
var $lang ; //!< user's language
|
|
var $theme ; //!< user's CSS Theme
|
|
var $authent_method; //!< authentication method use for this user
|
|
private $otp_secret; //!< string use as secret for OTP
|
|
/**
|
|
* @brief Create an user , load an existing one or if p_id == -1 search for the connected user. To have an empty
|
|
* user, give a p_id smaller than -1 or zero.
|
|
*
|
|
* @param $p_cn DatabaseCore connection
|
|
* @param $p_id if -1 then load the current user, > 0 load the user , = 0 (or < -1 ) means an empty user
|
|
*/
|
|
function __construct($p_cn, $p_id=-1)
|
|
{
|
|
$this->db=$p_cn;
|
|
// if p_id is not set then check the connected user
|
|
if ($p_id==-1)
|
|
{
|
|
$this->connect_user();
|
|
$this->set_session_var();
|
|
}
|
|
else // if p_id is set get data of another user
|
|
{
|
|
$this->id=$p_id;
|
|
$this->load();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief put user_login into Postgres config (session), it can be used for tracking users activities
|
|
* @return void
|
|
*/
|
|
public function set_session_var()
|
|
{
|
|
$this->db->exec_sql(sprintf("select set_config('noalyss.user_login','%s',false)",
|
|
Database::escape_string($_SESSION[SESSION_KEY.'g_user'])));
|
|
|
|
}
|
|
public function __toString(): string
|
|
{
|
|
return "User ".print_r($this,true);
|
|
}
|
|
/**
|
|
* @brief check the password and user
|
|
*/
|
|
function can_connect()
|
|
{
|
|
$cn=new \Database();
|
|
$can_connect=$cn->get_value("select count(*) from ac_users
|
|
where use_active=1 and
|
|
use_login=$1 and use_pass=$2",
|
|
[$this->login,$this->password]);
|
|
return $can_connect;
|
|
}
|
|
/**
|
|
* @brief connect the user and set the $_SESSION variables if not set thanks the $_REQUEST
|
|
*/
|
|
private function connect_user()
|
|
{
|
|
if (!isset($_SESSION[SESSION_KEY.'g_user']))
|
|
{
|
|
$http=new \HttpInput();
|
|
$user_login=$http->request("p_user", "string", "");
|
|
$user_password=$http->request("p_pass", "string", "");
|
|
|
|
if ($user_login!=""&&$user_password!="")
|
|
{
|
|
$_SESSION[SESSION_KEY."g_user"]=$user_login;
|
|
$_SESSION[SESSION_KEY."g_pass"]=md5($user_password);
|
|
}
|
|
else
|
|
{
|
|
echo '<h2 class="error">'._('Session expirée<br>Utilisateur déconnecté').'</h2>';
|
|
redirect('index.php', 1);
|
|
exit();
|
|
}
|
|
|
|
|
|
if (strpos($user_login, '@mobile')!=false)
|
|
{
|
|
$this->access_mode='MOBILE';
|
|
$this->login=str_ireplace("@mobile", "", $user_login);
|
|
}
|
|
else
|
|
{
|
|
$this->access_mode='PC';
|
|
$this->login=strtolower($user_login);
|
|
}
|
|
|
|
$_SESSION[SESSION_KEY."access_mode"]=$this->access_mode;
|
|
$_SESSION[SESSION_KEY.'g_user']=$this->login;
|
|
}
|
|
$this->login=$_SESSION[SESSION_KEY."g_user"];
|
|
$this->password=$_SESSION[SESSION_KEY.'g_pass'];
|
|
|
|
$this->id=-1;
|
|
$this->lang=(isset($_SESSION[SESSION_KEY.'g_lang']))?$_SESSION[SESSION_KEY.'g_lang']:'fr_FR.utf8';
|
|
$this->access_mode=$_SESSION[SESSION_KEY."access_mode"];
|
|
$cn=new Database();
|
|
|
|
// share user login with the repository
|
|
$cn->exec_sql(sprintf("select set_config('noalyss.user_login','%s',false)",
|
|
Database::escape_string($_SESSION[SESSION_KEY.'g_user'])));
|
|
|
|
if ($this->can_connect() == 0 || $this->load()==-1 )
|
|
{
|
|
echo '<h2 class="error">'._('Utilisateur ou mot de passe incorrect').'</h2>';
|
|
$sql="insert into audit_connect (ac_user,ac_ip,ac_module,ac_url,ac_state) values ($1,$2,$3,$4,$5)";
|
|
$cn->exec_sql($sql,
|
|
array($_SESSION[SESSION_KEY.'g_user'], $_SERVER["REMOTE_ADDR"], "DISCON",
|
|
$_SERVER['REQUEST_URI'], 'FAIL'));
|
|
$this->clean_session();
|
|
redirect('logout.php', 1);
|
|
exit();
|
|
}
|
|
|
|
$this->load_global_pref();
|
|
|
|
$_SESSION[SESSION_KEY.'g_lang']=$this->lang;
|
|
$this->valid=(isset($_SESSION[SESSION_KEY.'isValid']))?1:0;
|
|
if (isset($_SESSION[SESSION_KEY.'g_theme']))
|
|
{
|
|
$this->theme=$_SESSION[SESSION_KEY.'g_theme'];
|
|
}
|
|
$_SESSION[SESSION_KEY.'use_admin']=$this->admin;
|
|
$_SESSION[SESSION_KEY.'use_name']=$this->name;
|
|
$_SESSION[SESSION_KEY.'use_first_name']=$this->first_name;
|
|
}
|
|
|
|
/**
|
|
* @brief access_mode tells what mode must be used : pc or mobile
|
|
*/
|
|
public function get_access_mode()
|
|
{
|
|
return $this->access_mode;
|
|
}
|
|
|
|
/**
|
|
* @brief access_mode tells what mode must be used : pc or mobile
|
|
*/
|
|
public function set_access_mode($access_mode): object
|
|
{
|
|
$this->access_mode=$access_mode;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* @return int|mixed
|
|
*/
|
|
public function getId(): int
|
|
{
|
|
return $this->id;
|
|
}
|
|
|
|
/**
|
|
* @param int|mixed $id
|
|
*/
|
|
public function setId(int $id): void
|
|
{
|
|
$this->id=$id;
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getDb()
|
|
{
|
|
return $this->db;
|
|
}
|
|
|
|
/**
|
|
* @param mixed $db
|
|
*/
|
|
public function setDb($db): void
|
|
{
|
|
$this->db=$db;
|
|
}
|
|
|
|
/**
|
|
* @return default|int|mixed|string|string[]|null
|
|
*/
|
|
public function getAdmin()
|
|
{
|
|
return $this->admin;
|
|
}
|
|
|
|
/**
|
|
* @param default|int|mixed|string|string[]|null $admin
|
|
*/
|
|
public function setAdmin($admin): void
|
|
{
|
|
$this->admin=$admin;
|
|
}
|
|
|
|
/**
|
|
* @return int
|
|
*/
|
|
public function getValid(): int
|
|
{
|
|
return $this->valid;
|
|
}
|
|
|
|
/**
|
|
* @param int $valid
|
|
*/
|
|
public function setValid(int $valid): void
|
|
{
|
|
$this->valid=$valid;
|
|
}
|
|
|
|
/**
|
|
* @return default|mixed|string|string[]|null
|
|
*/
|
|
public function getFirstName()
|
|
{
|
|
return $this->first_name;
|
|
}
|
|
|
|
/**
|
|
* @param default|mixed|string|string[]|null $first_name
|
|
*/
|
|
public function setFirstName($first_name): void
|
|
{
|
|
$this->first_name=$first_name;
|
|
}
|
|
|
|
/**
|
|
* @return default|mixed|string|string[]|null
|
|
*/
|
|
public function getName()
|
|
{
|
|
return $this->name;
|
|
}
|
|
|
|
/**
|
|
* @param default|mixed|string|string[]|null $name
|
|
*/
|
|
public function setName($name): void
|
|
{
|
|
$this->name=$name;
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getActive()
|
|
{
|
|
return $this->active;
|
|
}
|
|
|
|
/**
|
|
* @param mixed $active
|
|
*/
|
|
public function setActive($active): void
|
|
{
|
|
$this->active=$active;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getLogin(): string
|
|
{
|
|
return $this->login;
|
|
}
|
|
|
|
/**
|
|
* @param string $login
|
|
*/
|
|
public function setLogin(string $login): void
|
|
{
|
|
$this->login=$login;
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getPassword()
|
|
{
|
|
return $this->password;
|
|
}
|
|
|
|
/**
|
|
* @param mixed $password
|
|
*/
|
|
public function setPassword($password): void
|
|
{
|
|
$this->password=$password;
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getEmail()
|
|
{
|
|
return $this->email;
|
|
}
|
|
|
|
/**
|
|
* @param mixed $email
|
|
*/
|
|
public function setEmail($email): void
|
|
{
|
|
$this->email=$email;
|
|
}
|
|
|
|
/* * \brief load data from database.
|
|
* if this->id == -1, it is unknown so we have to retrieve it
|
|
from the database by the login
|
|
* return -1 if nothing is found or the use_id
|
|
*/
|
|
|
|
function load():int
|
|
{
|
|
/* if this->id == -1, it is unknown so we have to retrieve it from
|
|
the database thanks it login */
|
|
if ($this->id<0)
|
|
{
|
|
$sql_cond=" where lower(use_login)=lower($1)";
|
|
$sql_array=array($this->login);
|
|
}
|
|
else
|
|
{
|
|
$sql_cond=" where use_id=$1";
|
|
$sql_array=array($this->id);
|
|
}
|
|
$sql="select use_id,
|
|
use_first_name,
|
|
use_name,
|
|
use_login,
|
|
use_active,
|
|
use_admin,
|
|
use_pass,
|
|
use_email,
|
|
use_auth_method,
|
|
use_otp_secret
|
|
from ac_users ";
|
|
$cn=new Database();
|
|
$Res=$cn->exec_sql($sql.$sql_cond, $sql_array);
|
|
if (($Max=Database::num_row($Res))==0)
|
|
return -1;
|
|
$row=Database::fetch_array($Res, 0);
|
|
$this->id=$row['use_id'];
|
|
$this->first_name=$row['use_first_name'];
|
|
$this->last_name=$row['use_name'];
|
|
$this->name=$row['use_name'];
|
|
$this->active=$row['use_active'];
|
|
$this->login=strtolower($row['use_login']);
|
|
$this->admin=$row['use_admin'];
|
|
$this->password=$row['use_pass'];
|
|
$this->email=$row['use_email'];
|
|
$this->authent_method=$row['use_auth_method'];
|
|
$this->otp_secret=$row['use_otp_secret'];
|
|
return $this->id;
|
|
}
|
|
|
|
function save()
|
|
{
|
|
if ( $this->authent_method != 0 && $this->otp_secret == null) {
|
|
$this->generate_otp();
|
|
}
|
|
$Sql="update ac_users set use_first_name=$1, use_name=$2
|
|
,use_active=$3,use_admin=$4,use_pass=$5 ,use_email = $7
|
|
, use_auth_method=$8,use_otp_secret=$9
|
|
where use_id=$6";
|
|
$cn=new Database();
|
|
$Res=$cn->exec_sql($Sql,
|
|
array($this->first_name //1
|
|
, $this->last_name // 2
|
|
, $this->active //3
|
|
, $this->admin //4
|
|
, $this->password //5
|
|
, $this->id //6
|
|
, $this->email //7
|
|
, $this->authent_method //8
|
|
, $this->otp_secret //9
|
|
));
|
|
}
|
|
|
|
function insert()
|
|
{
|
|
|
|
$Sql="INSERT INTO ac_users(
|
|
use_first_name, use_name, use_login, use_active,
|
|
use_admin, use_pass, use_email)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7) returning use_id";
|
|
|
|
$cn=new Database();
|
|
$this->id=$cn->get_value($Sql,
|
|
array($this->first_name, $this->last_name, $this->login, 1, $this->admin,
|
|
$this->password, $this->email));
|
|
}
|
|
|
|
/**
|
|
* \brief Check if user is active and exists in therepository
|
|
* Automatically redirect, it doesn't check if a user can access a folder
|
|
* \param $silent false, echo an error message and exit, true : exit without warning
|
|
* default is false
|
|
*
|
|
++ */
|
|
function Check($silent=false, $from='')
|
|
{
|
|
|
|
$res=0;
|
|
$pass5=$this->password;
|
|
|
|
$cn=new Database();
|
|
$sql="select ac_users.use_login,ac_users.use_active, ac_users.use_pass,
|
|
use_admin,use_first_name,use_name
|
|
from ac_users
|
|
where ac_users.use_id=$1
|
|
and ac_users.use_active=1
|
|
and ac_users.use_pass=$2";
|
|
$ret=$cn->exec_sql($sql, array($this->id, $pass5));
|
|
$res=Database::num_row($ret);
|
|
if ($res>0)
|
|
{
|
|
$r=Database::fetch_array($ret, 0);
|
|
$_SESSION[SESSION_KEY.'use_admin']=$r['use_admin'];
|
|
$_SESSION[SESSION_KEY.'use_name']=$r['use_name'];
|
|
$_SESSION[SESSION_KEY.'use_first_name']=$r['use_first_name'];
|
|
$_SESSION[SESSION_KEY.'isValid']=1;
|
|
|
|
$this->admin=$_SESSION[SESSION_KEY.'use_admin'];
|
|
$this->name=$_SESSION[SESSION_KEY.'use_name'];
|
|
$this->first_name=$_SESSION[SESSION_KEY.'use_first_name'];
|
|
$this->load_global_pref();
|
|
}
|
|
$sql="insert into audit_connect (ac_user,ac_ip,ac_module,ac_url,ac_state) values ($1,$2,$3,$4,$5)";
|
|
|
|
if ($res==0 || $this->can_connect() == 0)
|
|
{
|
|
$cn->exec_sql($sql,
|
|
array($_SESSION[SESSION_KEY.'g_user'], $_SERVER["REMOTE_ADDR"],
|
|
$from, $_SERVER['REQUEST_URI'], 'FAIL'));
|
|
if (!$silent)
|
|
{
|
|
echo '<script> alert(\''._('Utilisateur ou mot de passe incorrect').'\')</script>';
|
|
redirect('index.html');
|
|
}
|
|
$this->valid=0;
|
|
session_unset();
|
|
exit-1;
|
|
}
|
|
else
|
|
{
|
|
if ($from=='LOGIN' || $from=='PORTAL')
|
|
{
|
|
$cn->exec_sql($sql,
|
|
array($_SESSION[SESSION_KEY.'g_user'], $_SERVER["REMOTE_ADDR"], $from,
|
|
$_SERVER['REQUEST_URI'], 'SUCCESS'));
|
|
}
|
|
$this->valid=1;
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* \brief return the access to a folder,
|
|
* \param $p_dossier id if it is == 0 then we take the value from $_SESSION
|
|
* \return the priv_priv
|
|
* - X no access
|
|
* - R has access (normal user)
|
|
|
|
*
|
|
*/
|
|
function get_folder_access($p_dossier=0)
|
|
{
|
|
|
|
if ($p_dossier==0)
|
|
$p_dossier=dossier::id();
|
|
if ($this->admin==1)
|
|
return 'R';
|
|
$cn=new Database();
|
|
|
|
$sql="select 'R' from jnt_use_dos where use_id=$1 and dos_id=$2";
|
|
|
|
$res=$cn->get_value($sql, array($this->id, $p_dossier));
|
|
|
|
if ($cn->get_affected()==0)
|
|
return 'X';
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* \brief save the access of a folder
|
|
* \param $db_id the dossier id
|
|
* \param $priv boolean, true then it is granted, false it is removed
|
|
*/
|
|
function set_folder_access($db_id, $priv)
|
|
{
|
|
|
|
$cn=new Database();
|
|
if ($priv)
|
|
{
|
|
// the access is granted
|
|
$jnt=$cn->get_value("select jnt_id from jnt_use_dos where dos_id=$1 and use_id=$2", array($db_id, $this->id));
|
|
|
|
if ($cn->size()==0)
|
|
{
|
|
|
|
$Res=$cn->exec_sql("insert into jnt_use_dos(dos_id,use_id) values($1,$2)", array($db_id, $this->id));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Access is revoked
|
|
$cn->exec_sql('delete from jnt_use_dos where use_id = $1 and dos_id = $2 ', array($this->id, $db_id));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief check that a user is valid and the access to the folder
|
|
* \param $p_ledger the ledger to check
|
|
* \return the priv_priv
|
|
* - O only predefined operation
|
|
* - W write
|
|
* - R read only
|
|
* - X no access
|
|
*
|
|
*
|
|
*/
|
|
function get_ledger_access($p_ledger)
|
|
{
|
|
if ($this->admin==1||
|
|
$this->is_local_admin(dossier::id())==1||$this->get_status_security_ledger()==0)
|
|
return 'W';
|
|
|
|
$sql="select uj_priv from user_sec_jrn where uj_login=$1 and uj_jrn_id=$2";
|
|
$res=$this->db->get_value($sql, array($this->login, $p_ledger));
|
|
|
|
if ($res=='')
|
|
$res='X';
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* \brief get all the available ledgers for the current user
|
|
* \param $p_type = ALL or the type of the ledger (ACH,VEN,FIN,ODS)
|
|
* \param $p_access =3 for Read or WRITE, 2 write, 1 for readonly
|
|
* \param (boolean) $all if true show also inactive
|
|
* \return a double array of available ledgers
|
|
@verbatim
|
|
[0] => [jrn_def_id]
|
|
[jrn_def_type]
|
|
[jrn_def_name]
|
|
[jrn_def_class_deb]
|
|
[jrn_def_class_cred]
|
|
[jrn_type_id]
|
|
[jrn_desc]
|
|
[uj_priv]
|
|
@endverbatim
|
|
*/
|
|
function get_ledger($p_type='ALL', $p_access=3, $disable=TRUE)
|
|
{
|
|
$p_type=strtoupper($p_type);
|
|
if (!in_array($p_type, ["FIN", "ALL", "ODS", "VEN", 'ACH']))
|
|
{
|
|
record_log(sprintf("UGL1, p_type %s", $p_type));
|
|
throw new Exception("UGL1"._("Type incorrecte"));
|
|
}
|
|
if ($disable==TRUE)
|
|
{
|
|
$sql_enable="";
|
|
}
|
|
else
|
|
{
|
|
$sql_enable="and jrn_enable=1";
|
|
}
|
|
if ($this->admin!=1&&$this->is_local_admin()!=1&&$this->get_status_security_ledger()==1)
|
|
{
|
|
$sql_type=($p_type=='ALL')?'':"and jrn_def_type=upper('".sql_string($p_type)."')";
|
|
switch ($p_access)
|
|
{
|
|
case 3:
|
|
$sql_access=" and uj_priv!= 'X' ";
|
|
break;
|
|
case 2:
|
|
$sql_access=" and uj_priv = 'W' and jrn_enable=1 ";
|
|
break;
|
|
|
|
case 1:
|
|
$sql_access=" and ( uj_priv = 'R' or uj_priv='W') ";
|
|
break;
|
|
}
|
|
|
|
$sql="select jrn_def_id,jrn_def_type,jrn_def_code,
|
|
jrn_def_name,jrn_def_class_deb,jrn_def_class_cred,jrn_type_id,jrn_desc,uj_priv,
|
|
jrn_deb_max_line,jrn_cred_max_line,jrn_def_description,jrn_enable
|
|
from jrn_def join jrn_type on jrn_def_type=jrn_type_id
|
|
join user_sec_jrn on uj_jrn_id=jrn_def_id
|
|
where
|
|
uj_login='".$this->login."'".
|
|
$sql_type.$sql_access.$sql_enable.
|
|
" order by jrn_Def_name";
|
|
}
|
|
else
|
|
{
|
|
$sql_type=($p_type=='ALL')?' '.$sql_enable:"where jrn_def_type=upper('".sql_string($p_type)."') ".$sql_enable;
|
|
$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,
|
|
jrn_type_id,jrn_desc,'W' as uj_priv,jrn_def_description,jrn_enable
|
|
from jrn_def join jrn_type on jrn_def_type=jrn_type_id
|
|
$sql_type
|
|
order by jrn_Def_name";
|
|
}
|
|
$res=$this->db->exec_sql($sql);
|
|
if (Database::num_row($res)==0)
|
|
return null;
|
|
$array=Database::fetch_all($res);
|
|
return $array;
|
|
}
|
|
|
|
/**
|
|
* \brief return an sql condition for filtering the permitted ledger
|
|
* \param $p_type = ALL or the type of the ledger (ACH,VEN,FIN,ODS)
|
|
* \param $p_access =3 for READ or WRITE, 2 READ and write, 1 for readonly
|
|
*
|
|
* \return sql condition like = jrn_def_id in (...)
|
|
*/
|
|
function get_ledger_sql($p_type='ALL', $p_access=3)
|
|
{
|
|
$aLedger=$this->get_ledger($p_type, $p_access);
|
|
if (empty($aLedger))
|
|
return ' jrn_def_id < 0 ';
|
|
$sql=" jrn_def_id in (";
|
|
foreach ($aLedger as $row)
|
|
{
|
|
$sql.=$row['jrn_def_id'].',';
|
|
}
|
|
$sql.='-1)';
|
|
return $sql;
|
|
}
|
|
|
|
/**
|
|
* @brief synomym for isAdmin,
|
|
* @deprecated
|
|
*/
|
|
function Admin():int
|
|
{
|
|
return $this->isAdmin();
|
|
}
|
|
|
|
/**
|
|
* @brief Check if an user is an admin and check also his password
|
|
*
|
|
* @return 1 for yes 0 for no
|
|
*/
|
|
function isAdmin():int
|
|
{
|
|
$this->admin=0;
|
|
$pass5=$this->password;
|
|
$sql="select count(*) from ac_users where use_login=$1
|
|
and use_active=1 and use_admin=1 and use_pass=$2 ";
|
|
|
|
$cn=new Database();
|
|
$this->admin=$cn->get_value($sql, array($this->login,$pass5));
|
|
return $this->admin;
|
|
}
|
|
|
|
/**
|
|
* \brief Set the selected periode in the user's preferences
|
|
*
|
|
* \param $p_periode periode
|
|
* \param - $p_user
|
|
*
|
|
*/
|
|
function set_periode($p_periode)
|
|
{
|
|
$sql="update user_local_pref set parameter_value=$1 where user_id=$2 and parameter_type='PERIODE'";
|
|
$Res=$this->db->exec_sql($sql, [$p_periode, $this->id]);
|
|
}
|
|
|
|
private function set_default_periode()
|
|
{
|
|
|
|
/* get the first periode */
|
|
$sql='select min(p_id) as pid '
|
|
.' from parm_periode '
|
|
.' where p_closed = false and p_start = (select min(p_start) from parm_periode)';
|
|
$Res=$this->db->exec_sql($sql);
|
|
|
|
$pid=Database::fetch_result($Res, 0, 0);
|
|
/* if all the periode are closed, then we use the last closed period */
|
|
if ($pid==null)
|
|
{
|
|
$sql='select min(p_id) as pid '
|
|
.'from parm_periode '
|
|
.'where p_start = (select max(p_start) from parm_periode)';
|
|
$Res2=$this->db->exec_sql($sql);
|
|
$pid=Database::fetch_result($Res2, 0, 0);
|
|
if ($pid==null)
|
|
{
|
|
throw new Exception(_("Aucune période trouvéee !!!"));
|
|
}
|
|
|
|
$pid=Database::fetch_result($Res2, 0, 0);
|
|
}
|
|
|
|
$sql=sprintf("insert into user_local_pref (user_id,parameter_value,parameter_type)
|
|
values ('%s','%d','PERIODE')", $this->id, $pid);
|
|
$Res=$this->db->exec_sql($sql);
|
|
}
|
|
|
|
/**
|
|
* \brief Get the default periode from the user's preferences
|
|
*
|
|
* \return the default periode
|
|
*
|
|
*
|
|
*/
|
|
function get_periode()
|
|
{
|
|
|
|
$array=$this->get_preference();
|
|
if (!isset($array['PERIODE']))
|
|
{
|
|
$this->set_default_periode();
|
|
$array=$this->get_preference();
|
|
}
|
|
return $array['PERIODE'];
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Save the preference , the scope is global, the settings are saved
|
|
* into account_repository
|
|
* @param $key THEME, LANG , PAGESIZE
|
|
* @param $value value of the key
|
|
*/
|
|
function save_global_preference($key, $value)
|
|
{
|
|
$repo=new Database();
|
|
$count=$repo->get_value("select count(*)
|
|
from
|
|
user_global_pref
|
|
where
|
|
parameter_type=$1 and user_id=$2", array($key, $this->login));
|
|
if ($count==1)
|
|
{
|
|
$repo->exec_sql("update user_global_pref set parameter_value=$1
|
|
where parameter_type=$2 and user_id=$3", array($value, $key, $this->login));
|
|
}
|
|
elseif ($count==0)
|
|
{
|
|
$repo->exec_sql("insert into user_global_pref(user_id,parameter_type,parameter_value)
|
|
values($1,$2,$3)", array($this->login, $key, $value));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Get the default user's preferences
|
|
* \return array of (parameter_type => parameter_value)
|
|
*/
|
|
function get_preference()
|
|
{
|
|
$sql="select parameter_type,parameter_value from user_local_pref where user_id=$1";
|
|
$Res=$this->db->exec_sql($sql, array($this->id));
|
|
$l_array=array();
|
|
for ($i=0; $i<Database::num_row($Res); $i++)
|
|
{
|
|
$row=Database::fetch_array($Res, $i);
|
|
$type=$row['parameter_type'];
|
|
$l_array[$type]=$row['parameter_value'];
|
|
}
|
|
$repo=new Database();
|
|
$a_global_pref=$repo->get_array("select parameter_type,parameter_value from user_global_pref
|
|
where
|
|
upper(user_id) = upper($1)", [$this->login]);
|
|
$nb_global=count($a_global_pref);
|
|
for ($i=0; $i<$nb_global; $i++)
|
|
{
|
|
$idx=$a_global_pref[$i]['parameter_type'];
|
|
$value=$a_global_pref[$i]['parameter_value'];
|
|
$l_array[$idx]=$value;
|
|
}
|
|
|
|
return $l_array;
|
|
}
|
|
/**
|
|
* @brief Check if an user can access a module, return 1 if yes, otherwise 0
|
|
* record in audit log
|
|
* This function works only if user is connected to a Folder
|
|
* @param string $p_module menu_ref.me_code
|
|
* @returns 0 for FORBIDDEN, 1 for GRANTED
|
|
*/
|
|
function check_module($p_module)
|
|
{
|
|
if ( $this->access_mode == "PC") {
|
|
|
|
$acc=$this->db->get_value("select count(*) from v_all_menu where p_id = $1
|
|
and me_code=$2", array($this->get_profile(), $p_module));
|
|
} elseif ($this->access_mode=="MOBILE") {
|
|
$acc=$this->db->get_value("select count(*) from profile_mobile where p_id=$1 and me_code=$2",
|
|
array($this->get_profile(), $p_module));
|
|
} else {
|
|
throw new Exception("USER:823:ACCESS_MODE INCONNU");
|
|
}
|
|
if ($acc==0)
|
|
{
|
|
$this->audit("FAIL", $p_module);
|
|
return 0;
|
|
}
|
|
$this->audit("SUCCESS", $p_module);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* \brief Check if an user is allowed to do an action
|
|
* \param p_action_id
|
|
* \return
|
|
* - 0 no priv
|
|
* - 1 priv granted
|
|
* @see constant.security.php
|
|
*/
|
|
function check_action($p_action_id)
|
|
{
|
|
/* save it into the log */
|
|
global $audit;
|
|
if ($this->Admin()==1)
|
|
return 1;
|
|
if ($this->is_local_admin(dossier::id())==1)
|
|
return 1;
|
|
if ($this->get_status_security_action()==0)
|
|
return 1;
|
|
$Res=$this->db->exec_sql(
|
|
"select * from user_sec_act where ua_login=$1 and ua_act_id=$2", array($this->login, $p_action_id));
|
|
$Count=Database::num_row($Res);
|
|
if ($Count==0)
|
|
{
|
|
if (isset($audit)&&$audit==true)
|
|
{
|
|
$cn=new Database();
|
|
$sql="insert into audit_connect (ac_user,ac_ip,ac_module,ac_url,ac_state) values ($1,$2,$3,$4,$5)";
|
|
$cn->exec_sql($sql,
|
|
array($_SESSION[SESSION_KEY.'g_user'], $_SERVER["REMOTE_ADDR"], $p_action_id, $_SERVER['REQUEST_URI'],
|
|
'FAIL'));
|
|
}
|
|
return 0;
|
|
}
|
|
if ($Count==1)
|
|
return 1;
|
|
echo_error(_("Action invalide"));
|
|
record_log("User:check_action".sprintf("login %s ua_act_id %s", $this->login, $p_action_id));
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
* \brief Get the global preferences from user_global_pref
|
|
* in the account_repository db
|
|
*
|
|
* \note set $SESSION[g_variable]
|
|
*/
|
|
function load_global_pref()
|
|
{
|
|
$cn=new Database();
|
|
// Load everything in an array
|
|
$Res=$cn->exec_sql("select parameter_type,parameter_value from
|
|
user_global_pref
|
|
where user_id=$1", [$this->login]);
|
|
$Max=Database::num_row($Res);
|
|
if ($Max==0)
|
|
{
|
|
$this->insert_default_global_pref();
|
|
$this->load_global_pref();
|
|
return;
|
|
}
|
|
// Load value into array
|
|
$line=array();
|
|
for ($i=0; $i<$Max; $i++)
|
|
{
|
|
$row=Database::fetch_array($Res, $i);
|
|
$type=$row['parameter_type'];
|
|
$line[$type]=$row['parameter_value'];
|
|
}
|
|
// save array into g_ variable
|
|
$array_pref=array('g_theme'=>'THEME',
|
|
'g_pagesize'=>'PAGESIZE',
|
|
'g_topmenu'=>'TOPMENU',
|
|
'g_lang'=>'LANG',
|
|
'csv_fieldsep'=>'csv_fieldsep',
|
|
'csv_decimal'=>'csv_decimal',
|
|
'csv_encoding'=>'csv_encoding',
|
|
'first_week_day'=>'first_week_day');
|
|
|
|
foreach ($array_pref as $name=> $parameter)
|
|
{
|
|
if (!isset($line[$parameter]))
|
|
{
|
|
$this->insert_default_global_pref($parameter);
|
|
$this->load_global_pref();
|
|
return;
|
|
}
|
|
$_SESSION[SESSION_KEY.$name]=$line[$parameter];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief insert default pref
|
|
* if no parameter are given insert all the existing
|
|
* parameter otherwise only the requested
|
|
* \param $p_type parameter's type or nothing
|
|
* \param $p_value parameter value
|
|
*
|
|
*/
|
|
function insert_default_global_pref($p_type="", $p_value="")
|
|
{
|
|
|
|
$default_parameter=array("THEME"=>"classic",
|
|
"PAGESIZE"=>"50",
|
|
'TOPMENU'=>'TEXT',
|
|
'LANG'=>'fr_FR.utf8',
|
|
'csv_fieldsep'=>'0',
|
|
'csv_decimal'=>'0',
|
|
'csv_encoding'=>'utf8',
|
|
'first_week_day'=>1
|
|
);
|
|
$cn=new Database();
|
|
$sql="insert into user_global_pref(user_id,parameter_type,parameter_value)
|
|
values ($1,$2,$3)";
|
|
if ($p_type=="")
|
|
{
|
|
foreach ($default_parameter as $name=> $value)
|
|
{
|
|
$cn->exec_sql($sql, array($this->login, $name, $value));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$value=($p_value=="")?$default_parameter[$p_type]:$p_value;
|
|
if ( $cn->get_value("select count(*) from user_global_pref where user_id=$1 and parameter_type=$2",
|
|
array($this->login,$p_type)) == 1)
|
|
{
|
|
$cn->exec_sql("update user_global_pref set parameter_value=$1 where user_id=$2 and parameter_type=$3",
|
|
array($value,$this->login,$p_type));
|
|
} else {
|
|
$cn->exec_sql($sql, array($this->login, $p_type, $value));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief update default pref
|
|
* if value is not given then use the default value
|
|
*
|
|
* \param $p_type parameter's type
|
|
* \param $p_value parameter's value value of the type
|
|
*/
|
|
function update_global_pref($p_type, $p_value="")
|
|
{
|
|
$default_parameter=array("THEME"=>"classic",
|
|
"PAGESIZE"=>"50",
|
|
"LANG"=>'fr_FR.utf8',
|
|
'TOPMENU'=>'SELECT',
|
|
'csv_fieldsep'=>'0',
|
|
'csv_decimal'=>'0',
|
|
'csv_encoding'=>'utf8',
|
|
'first_week_day'=>1
|
|
);
|
|
$cn=new Database();
|
|
$Sql="update user_global_pref set parameter_value=$1
|
|
where parameter_type=$2 and
|
|
user_id=$3";
|
|
$value=($p_value=="")?$default_parameter[$p_type]:$p_value;
|
|
$cn->exec_sql($Sql, array($value, $p_type, $this->login));
|
|
}
|
|
|
|
//end function
|
|
/**
|
|
* \brief Return the year of current Periode
|
|
* it is the parm_periode.p_exercice col
|
|
* if an error occurs return 0
|
|
*/
|
|
|
|
function get_exercice()
|
|
{
|
|
$sql="select p_exercice from parm_periode where p_id=$1";
|
|
$Ret=$this->db->exec_sql($sql,[$this->get_periode()]);
|
|
if (Database::num_row($Ret)==1)
|
|
{
|
|
$r=Database::fetch_array($Ret, 0);
|
|
return $r['p_exercice'];
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* \brief Check if the user can access
|
|
* otherwise warn and exit
|
|
* \param $p_action requested action
|
|
* \param $p_js = 1 javascript, or 0 just a text or 2 to log it silently
|
|
* \return nothing the program exits automatically
|
|
*/
|
|
|
|
function can_request($p_action, $p_js=0)
|
|
{
|
|
if ($this->check_action($p_action)==0)
|
|
{
|
|
$this->audit('FAIL');
|
|
if ($p_js==1)
|
|
{
|
|
echo create_script("alert_box(content[59])");
|
|
}
|
|
elseif ($p_js==2)
|
|
{
|
|
record_log(_("Access invalid").$p_action);
|
|
}
|
|
else
|
|
{
|
|
echo '<h2 class="error">',
|
|
htmlspecialchars(_("Cette action ne vous est pas autorisée Contactez votre responsable")),
|
|
'</h2>';
|
|
echo '</div>';
|
|
}
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Check if the user can print (in menu_ref p_type_display=p)
|
|
* otherwise warn and exit
|
|
* @param $p_action requested action
|
|
* @return nothing the program exits automatically
|
|
*/
|
|
function check_print($p_action)
|
|
{
|
|
global $audit, $cn;
|
|
$this->audit('AUDIT', $p_action);
|
|
if ($this->Admin()==1)
|
|
return 1;
|
|
|
|
$res=$cn->get_value("select count(*) from profile_menu
|
|
join profile_user using (p_id)
|
|
where user_name=$1 and me_code=$2 ", array($this->login, $p_action));
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* \brief Check if the user can print (in menu_ref p_type_display=p)
|
|
* otherwise warn and exit
|
|
* \param $p_action requested action
|
|
* \return nothing the program exits automatically
|
|
*/
|
|
|
|
function can_print($p_action, $p_js=0)
|
|
{
|
|
if ($this->check_print($p_action)==0)
|
|
{
|
|
$this->audit('FAIL');
|
|
if ($p_js==1)
|
|
{
|
|
echo create_script("alert_box(content[59])");
|
|
}
|
|
else
|
|
{
|
|
echo '<div class="redcontent">';
|
|
echo '<h2 class="error">',
|
|
htmlspecialchars(_("Cette action ne vous est pas autorisée Contactez votre responsable")),
|
|
'</h2>';
|
|
echo '</div>';
|
|
}
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* \brief Check if an user is an local administrator
|
|
* @deprecated since version 6.7
|
|
*
|
|
*
|
|
* \param $p_dossier : dossier_id
|
|
*
|
|
* \return
|
|
* - 0 if no
|
|
* - 1 if yes
|
|
*
|
|
*/
|
|
function is_local_admin($p_dossier=-1)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* @brief return array of available repository
|
|
*
|
|
* @param $p_access R for read W for write
|
|
* @return an array
|
|
*/
|
|
function get_available_repository($p_access='R')
|
|
{
|
|
$profile=$this->get_profile();
|
|
$r=array();
|
|
if ($p_access=='R')
|
|
{
|
|
$r=$this->db->get_array("select distinct u.r_id,r_name
|
|
from
|
|
profile_sec_repository as u
|
|
join stock_repository as s on(u.r_id=s.r_id)
|
|
where
|
|
p_id =$1
|
|
and ur_right='W'
|
|
order by 2
|
|
", array($profile));
|
|
}
|
|
if ($p_access=='W')
|
|
{
|
|
$r=$this->db->get_array("select distinct u.r_id,r_name
|
|
from
|
|
profile_sec_repository as u
|
|
join stock_repository as s on(u.r_id=s.r_id)
|
|
where
|
|
p_id =$1 order by 2
|
|
", array($profile));
|
|
}
|
|
return $r;
|
|
}
|
|
|
|
/**
|
|
* \brief return an array with all the active users who can access
|
|
* $p_dossier including the global admin.
|
|
* The user must be activated
|
|
*
|
|
* \param $p_dossier dossier
|
|
* \return an array of user's object
|
|
* array indices
|
|
* - use_id (id )
|
|
* - use_login (login of the user)
|
|
* - use_name
|
|
* - use_first_name
|
|
*
|
|
* \exception throw an exception if nobody can access
|
|
*/
|
|
static function get_list($p_dossier)
|
|
{
|
|
$sql="select distinct use_id,use_login,use_first_name,use_name from ac_users
|
|
left outer join jnt_use_dos using (use_id)
|
|
where
|
|
(dos_id=$1 and use_active=1) or (use_active=1 and use_admin=1)
|
|
order by use_login,use_name";
|
|
|
|
$repo=new Database();
|
|
$array=$repo->get_array($sql, array($p_dossier));
|
|
if ($repo->size()==0)
|
|
throw new Exception('Error inaccessible folder');
|
|
return $array;
|
|
}
|
|
|
|
/**
|
|
* \brief check the access of an user on a ledger
|
|
*
|
|
* \param $p_jrn the ledger id
|
|
* \return
|
|
* - O only predefined operation
|
|
* - W write
|
|
* - R read only
|
|
* - X no access
|
|
*
|
|
*/
|
|
function check_jrn($p_jrn)
|
|
{
|
|
return $this->get_ledger_access($p_jrn);
|
|
}
|
|
|
|
/**
|
|
* \brief check if an user can access a folder, if he cannot display a dialog box
|
|
* and exit
|
|
* \param the folder if
|
|
* \param $silent false, echo an error message and exit, true : exit without warning
|
|
* default is false
|
|
* \return
|
|
* - L for administrator (local and global)
|
|
* - X no access
|
|
* - R regular user
|
|
*/
|
|
function check_dossier($p_dossier_id, $silent=false)
|
|
{
|
|
$this->Admin();
|
|
if ($this->admin==1||$this->is_local_admin($p_dossier_id)==1)
|
|
return 'L';
|
|
$cn=new Database();
|
|
|
|
$dossier=$cn->get_value("select 'R' from jnt_use_dos where dos_id=$1 and use_id=$2",
|
|
array($p_dossier_id, $this->id));
|
|
$dossier=($dossier=='')?'X':$dossier;
|
|
if ($dossier=='X')
|
|
{
|
|
$this->audit('FAIL', "Access folder ");
|
|
if (!$silent)
|
|
{
|
|
alert(_('Dossier non accessible'));
|
|
exit();
|
|
}
|
|
}
|
|
return $dossier;
|
|
}
|
|
|
|
/**
|
|
* @brief return the first date and the last date of the current exercice for the current user
|
|
* @return and array ([0] => start_date,[1] => end_date)
|
|
*/
|
|
function get_limit_current_exercice()
|
|
{
|
|
$current_exercice=$this->get_exercice();
|
|
$periode=new Periode($this->db);
|
|
list($per_start, $per_end)=$periode->get_limit($current_exercice);
|
|
$start=$per_start->first_day();
|
|
$end=$per_end->last_day();
|
|
return array($start, $end);
|
|
}
|
|
|
|
/**
|
|
* \brief Show all the available folder for the users
|
|
* at the login page. For the special case 'E'
|
|
* go directly to extension and bypasse the dashboard
|
|
* \param $p_filtre user
|
|
*
|
|
* \return table in HTML
|
|
*
|
|
*/
|
|
function show_dossier($p_filtre="")
|
|
{
|
|
$p_array=$this->get_available_folder($p_filtre);
|
|
|
|
$result="";
|
|
|
|
$result.="<TABLE id=\"folder\" class=\"result\">";
|
|
$result.="<tr>";
|
|
$result.="<th>";
|
|
$result.=_("Id");
|
|
$result.="</th>";
|
|
$result.="<th>";
|
|
$result.=_("Nom");
|
|
$result.="</th>";
|
|
$result.="<th>";
|
|
$result.=_("Description");
|
|
$result.="</th>";
|
|
$result.="</tr>";
|
|
if ($p_array==0)
|
|
{
|
|
$result.="<tr>";
|
|
$result.='<td style="width:auto" colspan=3>';
|
|
$result.=_("Aucun dossier disponible");
|
|
$result.='</td>';
|
|
$result.="</tr>";
|
|
return $result;
|
|
}
|
|
|
|
for ($i=0; $i<sizeof($p_array); $i++)
|
|
{
|
|
|
|
$id=$p_array[$i]['dos_id'];
|
|
$name=$p_array[$i]['dos_name'];
|
|
$desc=$p_array[$i]['dos_description'];
|
|
if ($i%2==0)
|
|
$tr="odd";
|
|
else
|
|
$tr="even";
|
|
$target="do.php?gDossier=$id";
|
|
|
|
$result.="<TR class=\"$tr\">";
|
|
|
|
$result.=td($id, ' class="num" ');
|
|
$result.="<TD class=\"$tr\">";
|
|
$result.="<A class=\"dossier\" HREF=\"$target\">";
|
|
$result.=" <B>".h($name)."</B>";
|
|
$result.="</A>";
|
|
$result.="</TD>";
|
|
$desc=($desc=="")?"<i>Aucune description</i>":h($desc);
|
|
$desc="<A class=\"dossier\" HREF=\"$target\">$desc</A>";
|
|
$result.="<TD class=\"$tr\" >".$desc;
|
|
$result.="</TD>";
|
|
$result.="</TR>";
|
|
}
|
|
$result.="</TABLE>";
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* \brief Get all the available folders
|
|
* for the users, checked with the security
|
|
*
|
|
* \param $p_filter
|
|
* \return array containing
|
|
* - ac_dossier.dos_id
|
|
* - ac_dossier.dos_name
|
|
* - ac_dossier.dos_description
|
|
*
|
|
*/
|
|
function get_available_folder($p_filter="")
|
|
{
|
|
$cn=new Database();
|
|
$filter="";
|
|
if ($this->admin==0)
|
|
{
|
|
// show only available folders
|
|
// if user is not an admin
|
|
$Res=$cn->exec_sql("select
|
|
distinct dos_id,dos_name,dos_description
|
|
from ac_users
|
|
natural join jnt_use_dos
|
|
natural join ac_dossier
|
|
where
|
|
use_login= $1
|
|
and use_active = 1
|
|
and ( dos_name ilike '%' || $2 || '%' or dos_description ilike '%' || $2 || '%' )
|
|
order by dos_name", array($this->login, $p_filter));
|
|
}
|
|
else
|
|
{
|
|
$Res=$cn->exec_sql("select
|
|
distinct dos_id,dos_name,dos_description from ac_dossier
|
|
where
|
|
dos_name ilike '%' || $1|| '%' or dos_description ilike '%' || $1 || '%'
|
|
order by dos_name", array($p_filter));
|
|
}
|
|
|
|
$max=Database::num_row($Res);
|
|
if ($max==0)
|
|
return 0;
|
|
|
|
for ($i=0; $i<$max; $i++)
|
|
{
|
|
$array[]=Database::fetch_array($Res, $i);
|
|
}
|
|
return $array;
|
|
}
|
|
|
|
/**
|
|
* @brief Audit action from the administration menu
|
|
* @param $p_module description of the action
|
|
*/
|
|
static function audit_admin($p_module)
|
|
{
|
|
$cn=new Database();
|
|
$sql="insert into audit_connect (ac_user,ac_ip,ac_module,ac_url,ac_state) values ($1,$2,$3,$4,$5)";
|
|
|
|
$cn->exec_sql($sql,
|
|
array(
|
|
$_SESSION[SESSION_KEY.'g_user'],
|
|
$_SERVER["REMOTE_ADDR"],
|
|
$p_module,
|
|
$_SERVER['REQUEST_URI'],
|
|
'ADMIN'));
|
|
}
|
|
|
|
function audit($action='AUDIT', $p_module="")
|
|
{
|
|
global $audit;
|
|
if ($audit)
|
|
{
|
|
if ($p_module==""&&isset($_REQUEST['ac']))
|
|
{
|
|
$p_module=$_REQUEST['ac'];
|
|
}
|
|
$cn=new Database();
|
|
if (isset($_REQUEST['gDossier']))
|
|
$p_module.=" dossier : ".$_REQUEST['gDossier'];
|
|
$sql="insert into audit_connect (ac_user,ac_ip,ac_module,ac_url,ac_state) values ($1,$2,$3,$4,$5)";
|
|
|
|
$cn->exec_sql($sql,
|
|
array(
|
|
$_SESSION[SESSION_KEY.'g_user'],
|
|
$_SERVER["REMOTE_ADDR"],
|
|
$p_module,
|
|
$_SERVER['REQUEST_URI'],
|
|
$action));
|
|
}
|
|
}
|
|
|
|
function save_profile($p_id)
|
|
{
|
|
$count=$this->db->get_value("select count(*) from profile_user where user_name=$1", array($this->login));
|
|
if ($count==0)
|
|
{
|
|
$this->db->exec_sql("insert into profile_user(p_id,user_name)
|
|
values ($1,$2)", array($p_id, $this->login));
|
|
}
|
|
else
|
|
{
|
|
$this->db->exec_sql("update profile_user set p_id=$1 where user_name=$2", array($p_id, $this->login));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief return the profile (p_id)
|
|
* @return profile.p_id
|
|
*/
|
|
function get_profile()
|
|
{
|
|
$profile=$this->db->get_value("select p_id from profile_user where
|
|
lower(user_name)=lower($1) ", array($this->login));
|
|
return $profile;
|
|
}
|
|
|
|
/**
|
|
* @brief Compute the SQL string for the writable profile,
|
|
* the subselect for p_id , example
|
|
* p_id in $g_user->sql_writable_profile.
|
|
* The administrator can access all the profiles
|
|
* R = Read Only W = Write and delete O = write and not delete
|
|
* @return SQL string with the subselect for p_id
|
|
*/
|
|
function sql_writable_profile()
|
|
{
|
|
if ($this->admin!=1)
|
|
{
|
|
$sql=" (select p_granted "
|
|
." from user_sec_action_profile "
|
|
." where ua_right in ('W','O') and p_id=".$this->get_profile().") ";
|
|
}
|
|
else
|
|
{
|
|
$sql="(select p_id p_granted from profile)";
|
|
}
|
|
return $sql;
|
|
}
|
|
/**
|
|
* @brief return array of writable action_profile
|
|
*
|
|
*/
|
|
function get_writable_profile()
|
|
{
|
|
$value=$this->db->get_array("select p_granted from ".$this->sql_writable_profile()." as m") ;
|
|
$aGranted=array_column($value,"p_granted");
|
|
return $aGranted;
|
|
}
|
|
/**
|
|
* @brief return array of readable action_profile
|
|
*
|
|
*/
|
|
function get_readable_profile()
|
|
{
|
|
$value=$this->db->get_array("select p_granted from ".$this->sql_readable_profile()." as m") ;
|
|
$aGranted=array_column($value,"p_granted");
|
|
return $aGranted;
|
|
}
|
|
/**
|
|
*@brief Compute the SQL string for the readable profile,
|
|
* the subselect for p_id , example
|
|
* p_id in $g_user->sql_readable_profile.
|
|
* The administrator can read all the profiles
|
|
* @return SQL string with the subselect for p_id
|
|
*/
|
|
function sql_readable_profile()
|
|
{
|
|
if ($this->admin!=1)
|
|
{
|
|
$sql=" (select p_granted "
|
|
." from user_sec_action_profile "
|
|
." where ua_right in ('W','R','O') and p_id=".$this->get_profile().") ";
|
|
}
|
|
else
|
|
{
|
|
$sql="(select p_id p_granted from profile)";
|
|
}
|
|
return $sql;
|
|
}
|
|
|
|
/**
|
|
* @brief Check if the current user can add an action in the profile given
|
|
* in parameter
|
|
* @param type $p_profile profile.p_id = action_gestion.ag_dest
|
|
* @return boolean
|
|
*/
|
|
function can_add_action($p_profile)
|
|
{
|
|
|
|
$r=$this->db->get_value(' select count(*)
|
|
from user_sec_action_profile
|
|
where p_granted=$2
|
|
and p_id=$1', array($this->get_profile(), $p_profile));
|
|
if ($r==0)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Check if the profile of the user can write for this profile
|
|
* @param $dtoc action_gestion.ag_id
|
|
* @return true if he can write otherwise false
|
|
*/
|
|
function can_write_action($dtoc)
|
|
{
|
|
if ($this->Admin()==1)
|
|
return TRUE;
|
|
if ($this->get_status_security_action()==0)
|
|
return TRUE;
|
|
$profile=$this->get_profile();
|
|
$r=$this->db->get_value(" select count(*) from action_gestion where ag_id=$1 and ag_dest in
|
|
(select p_granted from user_sec_action_profile where ua_right in ('W','O') and p_id=$2) ", array($dtoc, $profile));
|
|
if ($r==0)
|
|
return FALSE;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Check if the profile of the user can write AND delete for this profile
|
|
* @param $dtoc action_gestion.ag_id
|
|
* @return true if he can write otherwise false
|
|
*/
|
|
function can_delete_action($dtoc)
|
|
{
|
|
if ($this->Admin()==1)
|
|
return TRUE;
|
|
if ($this->get_status_security_action()==0)
|
|
return TRUE;
|
|
$profile=$this->get_profile();
|
|
$r=$this->db->get_value(" select count(*) from action_gestion where ag_id=$1 and ag_dest in
|
|
(select p_granted from user_sec_action_profile where ua_right='W' and p_id=$2) ", array($dtoc, $profile));
|
|
if ($r==0)
|
|
return FALSE;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Check if the profile of the user can write for this profile
|
|
* @param $dtoc action_gestion.ag_id
|
|
* @return true if he can write otherwise false
|
|
*/
|
|
function can_read_action($dtoc)
|
|
{
|
|
if ($this->Admin()==1)
|
|
return true;
|
|
$profile=$this->get_profile();
|
|
$r=$this->db->get_value(" select count(*) from action_gestion where ag_id=$1 and (ag_dest in
|
|
(select p_granted from user_sec_action_profile where p_id=$2) or ag_owner=$3)",
|
|
array($dtoc, $profile, $this->login));
|
|
if ($r==0)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Check if the profile of the user can write for this repository
|
|
* @param $p_repo stock_repository.r_id
|
|
* @return true if he can write otherwise false
|
|
*/
|
|
function can_write_repo($p_repo)
|
|
{
|
|
if ($this->Admin()==1)
|
|
return true;
|
|
$profile=$this->get_profile();
|
|
$r=$this->db->get_value("select count(*)
|
|
from profile_sec_repository
|
|
where
|
|
r_id=$1
|
|
and p_id =$2
|
|
and ur_right='W'", array($p_repo, $profile));
|
|
if ($r==0)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief Check if the profile of the user can read for this repository
|
|
* @param $p_repo stock_repository.r_id
|
|
* @return true if he read write otherwise false
|
|
*/
|
|
function can_read_repo($p_repo)
|
|
{
|
|
if ($this->Admin()==1)
|
|
return true;
|
|
$profile=$this->get_profile();
|
|
$r=$this->db->get_value("select count(*)
|
|
from profile_sec_repository
|
|
where
|
|
r_id=$1
|
|
and p_id =$2
|
|
", array($p_repo, $profile));
|
|
if ($r==0)
|
|
return false;
|
|
return true;
|
|
}
|
|
/**
|
|
* @brief store the password in session
|
|
*/
|
|
function password_to_session()
|
|
{
|
|
$_SESSION[SESSION_KEY.'g_pass']=$this->getPassword();
|
|
}
|
|
/**
|
|
* @brief Save the password of the current user
|
|
* @param string $p_pass1 password (clear)
|
|
* @param string $p_pass2 for confirming password (clear)
|
|
* @see check_password_strength()
|
|
* @return true : password successfully changed otherwise false
|
|
*/
|
|
function save_password($p_pass1, $p_pass2)
|
|
{
|
|
if ($p_pass1==$p_pass2 && count(check_password_strength($p_pass1)['msg'])==0)
|
|
{
|
|
$repo=new Database();
|
|
$l_pass=md5($p_pass1);
|
|
$this->setPassword($l_pass);
|
|
$repo->exec_sql("update ac_users set use_pass=$1 where use_login=$2",
|
|
array($l_pass, $this->login));
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Save the password from PREFERENCE MODULE
|
|
* @param type $p_email
|
|
*/
|
|
function save_email($p_email)
|
|
{
|
|
$repo=new Database();
|
|
$repo->exec_sql("update ac_users set use_email=$1 where use_login=$2",
|
|
array($p_email, $_SESSION[SESSION_KEY.'g_user']));
|
|
}
|
|
|
|
/**
|
|
*@brief Remove a user and all his privileges
|
|
* So it cannot connect anymore and all his privileges are removed from
|
|
* the dossier
|
|
*
|
|
*/
|
|
static function revoke_access($p_login, $p_dossier)
|
|
{
|
|
// connect to the repository
|
|
$repo_cnx=new Database();
|
|
|
|
// Retrieve the user
|
|
$user=$repo_cnx->get_array('select use_id,use_login from ac_users where use_login=$1', array($p_login));
|
|
if (!$user)
|
|
return false;
|
|
|
|
// remove him from jnt_use_dos
|
|
$repo_cnx->exec_sql("delete from jnt_use_dos WHERE use_id=$1 and dos_id=$2",
|
|
array($user[0]['use_id'], $p_dossier));
|
|
|
|
// Remove user from user's dossier
|
|
$cn_dossier=new Database($p_dossier);
|
|
$cn_dossier->exec_sql("delete from profile_user where user_name=$1", array($p_login));
|
|
$cn_dossier->exec_sql("delete from user_sec_act where ua_login=$1", array($p_login));
|
|
}
|
|
|
|
/**
|
|
* @brief Grant access to folder, grant administrator profile , all the ledgers and all the action
|
|
*
|
|
*/
|
|
static function grant_admin_access($p_login, $p_dossier)
|
|
{
|
|
$repo_cnx=new Database();
|
|
$user=$repo_cnx->get_array("select use_id,use_login
|
|
from ac_users
|
|
where use_login=$1", array($p_login));
|
|
|
|
if (!$user)
|
|
return false;
|
|
$cn_dossier=new Database($p_dossier);
|
|
// if not access to DB
|
|
if (
|
|
$repo_cnx->get_value("select count(*) from jnt_use_dos where use_id=$1 and dos_id=$2",
|
|
array($user[0]['use_id'], $p_dossier))==0
|
|
)
|
|
{
|
|
$repo_cnx->exec_sql("insert into jnt_use_dos(use_id,dos_id) values ($1,$2)",
|
|
array($user[0]['use_id'], $p_dossier));
|
|
}
|
|
//------ Give him the admin menu
|
|
if ($cn_dossier->get_value("select count(*) from profile_user where user_name=$1", array($user[0]['use_login']))==0)
|
|
{
|
|
$cn_dossier->exec_sql('insert into profile_user(user_name,p_id) values($1,1)', array($user[0]['use_login']));
|
|
}
|
|
// Grant all action + ledger to him
|
|
$cn_dossier->exec_sql("delete from user_sec_act where ua_login=$1", array($p_login));
|
|
|
|
$cn_dossier->exec_sql("insert into user_sec_act (ua_login,ua_act_id)"
|
|
." select $1 ,ac_id from action ", array($p_login));
|
|
|
|
$cn_dossier->exec_sql("delete from user_sec_jrn where uj_login=$1", array($p_login));
|
|
$cn_dossier->exec_sql("insert into user_sec_jrn(uj_login,uj_jrn_id,uj_priv)"
|
|
." select $1,jrn_def_id,'W' from jrn_def", array($p_login));
|
|
}
|
|
|
|
static function remove_inexistant_user($p_dossier)
|
|
{
|
|
$cnx_repo=new Database();
|
|
$name=$cnx_repo->format_name($p_dossier, 'dos');
|
|
if ($cnx_repo->exist_database($name)==0)
|
|
return;
|
|
$cnx_dossier=new Database($p_dossier);
|
|
if ($cnx_dossier->exist_table('profile_user'))
|
|
$a_user=$cnx_dossier->get_array('select user_name from profile_user');
|
|
else
|
|
return;
|
|
|
|
if (!$a_user)
|
|
return;
|
|
$nb=count($a_user);
|
|
for ($i=0; $i<$nb; $i++)
|
|
{
|
|
if ($cnx_repo->get_value('select count(*) from ac_users where use_login=$1', array($a_user[$i]['user_name']))==0)
|
|
{
|
|
if ($cnx_dossier->exist_table('user_sec_jrn'))
|
|
$cnx_dossier->exec_sql("delete from user_sec_jrn where uj_login=$1", array($a_user[$i]['user_name']));
|
|
$cnx_dossier->exec_sql("delete from profile_user where user_name=$1", array($a_user[$i]['user_name']));
|
|
if ($cnx_dossier->exist_table('user_sec_act'))
|
|
$cnx_dossier->exec_sql("delete from user_sec_act where ua_login=$1", array($a_user[$i]['user_name']));
|
|
if ($cnx_dossier->exist_table('user_sec_jrn'))
|
|
$cnx_dossier->exec_sql("delete from user_sec_jrn where uj_login=$1", array($a_user[$i]['user_name']));
|
|
if ($cnx_dossier->exist_table('user_active_security'))
|
|
$cnx_dossier->exec_sql("delete from user_active_security where us_login=$1",
|
|
array($a_user[$i]['user_name']));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Check the security on ledger for the user , it returns 1 if the security
|
|
* on ledgers is enabled, otherwise 0
|
|
*/
|
|
function get_status_security_ledger()
|
|
{
|
|
$security=$this->db->get_value("select us_ledger from user_active_security
|
|
where
|
|
us_login=$1", [$this->login]);
|
|
$n_security=($security=="Y")?1:0;
|
|
return $n_security;
|
|
}
|
|
|
|
/**
|
|
* @brief Set the flag in the table user_active_security
|
|
* @param int $p_value 1==enable , 0 = disable
|
|
* @exceptions invalid value
|
|
*/
|
|
function set_status_security_ledger($p_value)
|
|
{
|
|
if ($p_value!=0&&$p_value!=1)
|
|
throw new Exception(_("Valeur invalide"));
|
|
$exist=$this->db->get_value("select count(*) from user_active_security where us_login=$1", [$this->login]);
|
|
$flag=($p_value==1)?"Y":"N";
|
|
if ($exist==0)
|
|
{
|
|
$this->db->exec_sql("insert into user_active_security (us_login,us_ledger,us_action) values ($1,$2,$3)",
|
|
[$this->login, $flag, 'Y']);
|
|
}
|
|
else
|
|
{
|
|
$this->db->exec_sql("update user_active_security set us_ledger=$1 where us_login = $2",
|
|
[$flag, $this->login]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check the security on ledger for the user , it returns 1 if the security
|
|
* on ledgers is enabled, otherwise 0
|
|
*/
|
|
function get_status_security_action()
|
|
{
|
|
$security=$this->db->get_value("select us_action from user_active_security
|
|
where
|
|
us_login=$1", [$this->login]);
|
|
$n_security=($security=="Y")?1:0;
|
|
return $n_security;
|
|
}
|
|
|
|
/**
|
|
* Set the flag in the table user_active_security
|
|
* @param int $p_value 1==enable , 0 = disable
|
|
* @exceptions invalid value
|
|
*/
|
|
function set_status_security_action($p_value)
|
|
{
|
|
if ($p_value!=0&&$p_value!=1)
|
|
throw new Exception(_("Valeur invalide"));
|
|
$exist=$this->db->get_value("select count(*) from user_active_security where us_login=$1", [$this->login]);
|
|
$flag=($p_value==1)?"Y":"N";
|
|
if ($exist==0)
|
|
{
|
|
$this->db->exec_sql("insert into user_active_security (us_login,us_action,us_ledger) values ($1,$2,$3)",
|
|
[$this->login, $flag, 'Y']);
|
|
}
|
|
else
|
|
{
|
|
$this->db->exec_sql("update user_active_security set us_action=$1 where us_login = $2",
|
|
[$flag, $this->login]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*@brief first day in calendar
|
|
* @see IDate::set_firstDate(
|
|
*/
|
|
function get_first_week_day()
|
|
{
|
|
$repocn=new Database();
|
|
$result=$repocn->get_value("select parameter_value from user_global_pref where parameter_type=$1 and user_id=$2 ",
|
|
array("first_week_day", $this->login));
|
|
if ($repocn->count()==0)
|
|
{
|
|
$this->save_global_preference("first_week_day", 1);
|
|
return 1;
|
|
}
|
|
return $result;
|
|
}
|
|
/**
|
|
* @brief clean the sessions
|
|
*/
|
|
static function clean_session()
|
|
{
|
|
|
|
$aSession=$_SESSION;
|
|
foreach($aSession as $key => $value) {
|
|
if(DEBUGNOALYSS>1) { echo "[$key]=>[$value]";}
|
|
|
|
if ( strpos($key,SESSION_KEY) === 0) {
|
|
unset($_SESSION[$key]);
|
|
if(DEBUGNOALYSS>1) { echo "=> [$key] cleaned";}
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
*@brief Get preference , either the user see the numeric id for VAT or its code, if the preference doesn't exist
|
|
* by default , 0 is saved in ACCOUNT_REPOSITORY
|
|
* @see ITva_Popup::set_vat_code()
|
|
* @see ITva_Popup
|
|
*/
|
|
function get_vat_code_preference():int
|
|
{
|
|
$repocn=new Database();
|
|
$result=$repocn->get_value("select parameter_value from user_global_pref where parameter_type=$1 and user_id=$2 ",
|
|
array("vat_code", $this->login));
|
|
if ($repocn->count()==0)
|
|
{
|
|
$this->save_global_preference("vat_code", 0);
|
|
return 0;
|
|
}
|
|
return $result;
|
|
}
|
|
/**
|
|
* @brief generate OTP
|
|
*/
|
|
function generate_otp()
|
|
{
|
|
$otp=new \Noalyss\OTP();
|
|
$this->otp_secret=$otp->build_secret();
|
|
}
|
|
|
|
public function get_authent_method() {
|
|
return $this->authent_method;
|
|
}
|
|
|
|
public function get_otp_secret() {
|
|
return $this->otp_secret;
|
|
}
|
|
|
|
|
|
public function set_authent_method($authent_method) {
|
|
$this->authent_method = $authent_method;
|
|
return $this;
|
|
}
|
|
|
|
public function set_otp_secret($otp_secret) {
|
|
$this->otp_secret = $otp_secret;
|
|
return $this;
|
|
}
|
|
public function set_identified()
|
|
{
|
|
$_SESSION[SESSION_KEY."db_auth"]='ok';
|
|
}
|
|
/**
|
|
* @brief check is the double authentication has been successful
|
|
* @return bool
|
|
*/
|
|
public function is_double_identified() {
|
|
|
|
if ( $this->authent_method == 0 )
|
|
{
|
|
$_SESSION[SESSION_KEY."db_auth"]='ok';
|
|
return true;
|
|
}
|
|
if ( ! isset($_SESSION[SESSION_KEY."db_auth"])) {
|
|
return false;
|
|
}
|
|
if ($_SESSION[SESSION_KEY."db_auth"] == "ok") {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
/**
|
|
* @brief send a code to the user and save the expected code + UUID in
|
|
* a table OTP_SEND_SECRET
|
|
* @return bool false if fails true if succeeds
|
|
* @throws \Exception
|
|
*/
|
|
public function send_code_otp()
|
|
{
|
|
if ( $this->authent_method !=1 ) { return false; }
|
|
$mail=new \Sendmail();
|
|
$mail->set_from(ADMIN_WEB);
|
|
$mail->mailto($this->getEmail());
|
|
$mail->set_subject(_("NOALYSS : votre code secret "));
|
|
$noalyss_url=NOALYSS_URL;
|
|
|
|
|
|
if ( strlen(trim($this->otp_secret??"")) == 0 ) {
|
|
throw new \Exception("noalyss_user.send_code_otp:secret empty",1945);
|
|
}
|
|
$otp=new \Noalyss\OTP();
|
|
$code=$otp->compute_code($this->otp_secret);
|
|
$message="Bonjour,
|
|
|
|
Voici votre code secret pour NOALYSS : $code
|
|
|
|
|
|
";
|
|
try {
|
|
$uuid= guidv4();
|
|
$repository=new \Database();
|
|
// remove old for this user
|
|
$repository->exec_sql("delete from otp_send_secret where use_id=$1"
|
|
,[$this->id]);
|
|
// remove also old one
|
|
$repository->exec_sql("delete from otp_send_secret where os_valid_time < now()");
|
|
$now=new \DateTime();
|
|
$valid=new \DateTime();
|
|
$valid->modify('+20 minutes');
|
|
|
|
$otp_send_secret=new Otp_Send_Secret_SQL($repository);
|
|
$otp_send_secret->set("use_id",$this->id)
|
|
->set('os_request',$uuid)
|
|
->set("os_code",$code)
|
|
->set('os_valid_time',$valid->format('d.m.Y H:i:s'));
|
|
$otp_send_secret->save();
|
|
$mail->set_message($message);
|
|
$mail->compose();
|
|
$mail->send();
|
|
return $uuid;
|
|
} catch (Exception $ex) {
|
|
\record_log ($ex);
|
|
throw new \Exception("noalyss_user.send_code_otp",1963,$ex);
|
|
}
|
|
}
|
|
/**
|
|
* @brief send an email with link to the user
|
|
*/
|
|
function send_link_otp() {
|
|
$mail = new \Sendmail();
|
|
$mail->set_from(ADMIN_WEB);
|
|
$mail->mailto($this->getEmail());
|
|
$mail->set_subject(_("NOALYSS : Double authentification lien pour 2FA: OTP"));
|
|
$noalyss_url = NOALYSS_URL;
|
|
$uuid = guidv4();
|
|
$id = $this->getId();
|
|
/**
|
|
* save in DB first
|
|
*/
|
|
$message = "Bonjour,
|
|
|
|
Afin de pouvoir utiliser la double authentification avec 2FA: OTP, pourriez-vous
|
|
suivre ce lien et scanner le QRCode avec votre application android freeOTP ou Google Authenticator.
|
|
|
|
Ce lien ne sera actif que 12 heures.
|
|
|
|
|
|
{$noalyss_url}/index.php?otp={$uuid}
|
|
|
|
Merci d'utiliser NOALYSS
|
|
|
|
Bien cordialement,
|
|
|
|
|
|
";
|
|
try {
|
|
$repository = new \Database();
|
|
// remove old for this user
|
|
$repository->exec_sql("delete from otp_send_secret where use_id=$1"
|
|
,[$this->id]);
|
|
// remove also old one
|
|
$repository->exec_sql("delete from otp_send_secret where os_valid_time < now()");
|
|
$valid_time=new \DateTime();
|
|
$valid_time->add(new \DateInterval('PT12H'));
|
|
$otp_send_secret_sql = new \Otp_Send_Secret_SQL($repository);
|
|
$otp_send_secret_sql->set('use_id', $id)
|
|
->set('os_valid_time',$valid_time->format('d-m-Y H:i'))
|
|
->set('os_request', $uuid);
|
|
|
|
$otp_send_secret_sql->save();
|
|
$mail->set_message($message);
|
|
$mail->compose();
|
|
$mail->send();
|
|
return $uuid;
|
|
} catch (Exception $ex) {
|
|
\record_log($ex);
|
|
throw new \Exception("noalyss_user.send_link_otp",1998,$ex);
|
|
}
|
|
}
|
|
/**
|
|
* @brief FORM to enter the 6 digit enter by OTP
|
|
* @param $uuid (string UUID) UUID in the message, null if there is no message
|
|
*/
|
|
function input_otp($uuid="",$url="")
|
|
{
|
|
require_once NOALYSS_TEMPLATE."/noalyss_user-input_otp.php" ;
|
|
}
|
|
/**
|
|
* @brief check that the OTP code is the one on smartphone
|
|
* returns false if the given does not match the OTP
|
|
*/
|
|
function check_otp($code)
|
|
{
|
|
$otp=new \Noalyss\OTP();
|
|
|
|
if ( $otp->compute_code($this->otp_secret) == $code ) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
?>
|