+ Date et heure :
+ =$date->format('d/m/Y h:i')?>
+
+
+ Entrez le code que vous avez reçu par email ou sur votre application OTP.
+
+
+ Rafraichissez la page pour recevoir un nouveau code.
+
+
+
\ No newline at end of file
diff --git a/include/user.inc.php b/include/user.inc.php
index 2b340adc8..69addd3de 100644
--- a/include/user.inc.php
+++ b/include/user.inc.php
@@ -40,13 +40,14 @@ if ( isset ($_POST["ADD"]) )
$new_user=new Noalyss_user($cn,0);
$new_user->first_name=$http->post('FNAME');
$new_user->last_name=$http->post('LNAME');
+ $new_user->setAdmin(0);
$login=$http->post('LOGIN');
$login=str_replace("'","",$login);
$login=str_replace('"',"",$login);
$login=str_replace(" ","",$login);
$login=strtolower($login);
$new_user->login=$login;
-
+ //$new_user->auth_method=
$new_user->email=$http->post('EMAIL',"string",'');
if ( trim($login)=="" || strlen($login)<5)
{
@@ -104,6 +105,7 @@ if ($sbaction == "save")
$UserChange->active = $http->post('Actif');
$UserChange->admin = $http->post('Admin');
$UserChange->email = $http->post('email');
+ $UserChange->authent_method = $http->post('auth_method',"number");
if ($UserChange->active ==-1 || $UserChange->admin ==-1)
{
die ('Missing data');
@@ -118,15 +120,36 @@ if ($sbaction == "save")
$msg.="$result ";
}
alert($msg);
+ require_once NOALYSS_INCLUDE.'/user_detail.inc.php';
+ return;
} else {
$UserChange->setPassword(md5($_POST['password']));
- $UserChange->save();
+
}
}
- else
- {
- $UserChange->save();
- }
+ // if request new secret for OTP
+ if ( $http->post("generate_otp","number",0)==1){
+
+ $UserChange->generate_otp();
+ }
+
+ // save user change
+ $UserChange->save();
+ if ( $UserChange->authent_method !=0 && filter_var($UserChange->email, FILTER_VALIDATE_EMAIL) === false ) {
+ echo_warning(_("Email invalide"));
+ require_once NOALYSS_INCLUDE.'/user_detail.inc.php';
+ return;
+ }
+ // send a email with link if authen_method !=0 (freeOTP)
+ if ( $UserChange->authent_method !=0
+ && filter_var($UserChange->email, FILTER_VALIDATE_EMAIL) == true
+ && $http->post('email_otp','number',0) == 1
+ ) {
+ // delete previous send for this user
+ $cn->exec_sql('delete from otp_send_secret where use_id=$1',[$UserChange->getId()]);
+ // send a email with a link to the qcode
+ $UserChange->send_link_otp();
+ }
}
}
@@ -185,9 +208,9 @@ if ( isset($_REQUEST['det']) && $sbaction=="")
-
-
-
+
+
+
=\Icon_Action::tips("Mot de passe : longueur minimale = 8 dont au moins 1 majuscule, 1 minuscule,1 chiffre et 1 car.spécial")?>
@@ -195,10 +218,16 @@ if ( isset($_REQUEST['det']) && $sbaction=="")
+
+
+
+
add(_("Login"), $url," order by use_login asc", "order by use_login desc","la", "ld");
-$header->add(_("Nom"), $url," order by use_name asc,use_first_name asc", "order by use_name desc,use_first_name desc","na", "nd");
-$header->add(_('Dossier'),$url,' order by ag_dossier asc','order by ag_dossier desc',
+$header->add(_("Login"), $url," order by use_login asc", "order by use_login desc","la", "ld"); // 0
+$header->add(_("Nom"), $url," order by use_name asc,use_first_name asc", "order by use_name desc,use_first_name desc","na", "nd"); // 1
+$header->add(_("Authentification"), $url," order by use_auth_method asc,use_login asc", "order by use_auth_method desc ,use_login asc","auth", "nauth"); // 2
+$header->add(_('Dossier'),$url,' order by ag_dossier asc','order by ag_dossier desc', //3
'da','dd');
-$header->add(_("Actif"), $url," order by use_active asc", "order by use_active desc","aa", "ad");
-$header->add(_("Email"), $url," order by use_email asc,use_name asc,use_first_name asc", "order by use_email desc,use_name desc,use_first_name desc","na", "nd");
-$ord=(isset($_REQUEST['ord']))?$_REQUEST['ord']:'la';
+$header->add(_("Actif"), $url," order by use_active asc", "order by use_active desc","aa", "ad"); // 4
+$header->add(_("Email"), $url," order by use_email asc,use_name asc,use_first_name asc", "order by use_email desc,use_name desc,use_first_name desc","na", "nd"); //5
+$ord=$http->request("ord","string","la");
$sql=$header->get_sql_order($ord);
-
$a_user=$repo->get_user_folder($sql);
if ( !empty ($a_user) )
@@ -268,12 +297,14 @@ if ( !empty ($a_user) )
echo '
+
+ =_("Renouveller clef secrète")?>
+
+
+ =_("envoyer email pour 2FA avec OTP ")?>
+ =_("Un email sera envoyé avec un lien pour initialiser 2FA avec OTP")?>>
+
+
+
diff --git a/sql/ac_upgrade.sql b/sql/ac_upgrade.sql
index 9beca2b3e..25ec82709 100644
--- a/sql/ac_upgrade.sql
+++ b/sql/ac_upgrade.sql
@@ -1,12 +1,30 @@
+ALTER TABLE public.ac_users ADD use_auth_method int2 DEFAULT 0 NULL;
+COMMENT ON COLUMN public.ac_users.use_auth_method IS '0 = plain text, 1 = OTP , digit sent by email, 2=freeOTP';
+ALTER TABLE public.ac_users ADD use_otp_secret text NULL;
+COMMENT ON COLUMN public.ac_users.use_otp_secret IS 'string base32 generated for OTP';
+ALTER TABLE public.ac_users ADD CONSTRAINT ac_users_unique UNIQUE (use_otp_secret);
+update public.ac_users set use_auth_method=0;
+ALTER TABLE public.ac_users ALTER COLUMN use_auth_method SET NOT NULL;
-begin;
-ALTER TABLE ac_dossier drop COLUMN dos_jnt_user ;
-delete from jnt_use_dos where jnt_id in (select priv_jnt from priv_user where priv_priv='X');
-delete from jnt_use_dos where use_id in (select use_id from ac_users where use_admin=1 or use_active=0);
-ALTER TABLE ac_users ADD COLUMN use_email text;
-COMMENT ON COLUMN ac_users.use_email IS 'Email of the user';
-drop table priv_user;
-select upgrade_repo(16);
-alter table
-rollback;
+
+CREATE TABLE public.otp_send_secret (
+ os_id int8 GENERATED ALWAYS AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL, -- PK
+ os_timestamp timestamptz DEFAULT now() NOT NULL, -- Timestamp of the email sent
+ os_request text NULL, -- Unique identifier when request to scan qrcode
+ use_id int4 NOT NULL, -- FK to ac_users
+ os_code varchar(8) NULL,
+ os_valid_time timestamp NOT NULL,
+ CONSTRAINT otp_send_secret_pk PRIMARY KEY (os_id),
+ CONSTRAINT otp_send_secret_unique UNIQUE (use_id)
+);
+COMMENT ON TABLE public.otp_send_secret IS 'sent to user for scanning a QRCODE for FreeOTP
+or digit to connect, depends of ac_users use_auth_method.';
+
+-- Column comments
+
+COMMENT ON COLUMN public.otp_send_secret.os_id IS 'PK';
+COMMENT ON COLUMN public.otp_send_secret.os_timestamp IS 'Timestamp of the email sent';
+COMMENT ON COLUMN public.otp_send_secret.os_request IS 'Unique identifier when request to scan qrcode';
+COMMENT ON COLUMN public.otp_send_secret.os_code IS 'contains code sent by email';
+COMMENT ON COLUMN public.otp_send_secret.use_id IS 'FK to ac_users';
\ No newline at end of file
diff --git a/unit-test/include/class/NoalyssUserTest.php b/unit-test/include/class/NoalyssUserTest.php
index 290c81677..2f5c8cb99 100644
--- a/unit-test/include/class/NoalyssUserTest.php
+++ b/unit-test/include/class/NoalyssUserTest.php
@@ -23,6 +23,7 @@ class NoalyssUserTest extends TestCase
* @var User
*/
protected $object;
+ private $cn;
/**
* Sets up the fixture, for example, opens a network connection.
@@ -239,4 +240,21 @@ class NoalyssUserTest extends TestCase
$_SESSION[SESSION_KEY.'use_admin']=1;
$user->admin=1;
}
+
+ /**
+ * @testdox Generate OTP : check key length and uniqueness
+ */
+ function testGenerateOTP()
+ {
+ $this->object->generate_otp();
+ $secret=$this->object->get_otp_secret();
+ $this->assertTrue(strlen($secret) == 52,"Fails to generate OTP 32 char ".$secret." len = ".strlen($secret));
+
+ for ($i=0;$i<100;$i++){
+ $this->object->generate_otp();
+ $this->assertTrue($secret != $this->object->get_otp_secret(),"Generate twice the same secret");
+ }
+
+ }
+
}