2018-04-02 08:29:19 +02:00
< ? php
/**
* This file is part of Zwii .
* For full copyright and license information , please see the LICENSE
* file that was distributed with this source code .
*
* @ author Rémi Jean < remi . jean @ outlook . com >
* @ copyright Copyright ( C ) 2008 - 2018 , Rémi Jean
2021-02-17 13:49:58 +01:00
* @ author Frédéric Tempez < frederic . tempez @ outlook . com >
* @ copyright Copyright ( C ) 2018 - 2021 , Frédéric Tempez
2018-04-02 08:29:19 +02:00
* @ license GNU General Public License , version 3
2020-09-01 20:48:40 +02:00
* @ link http :// zwiicms . fr /
2018-04-02 08:29:19 +02:00
*/
class user extends common {
public static $actions = [
'add' => self :: GROUP_ADMIN ,
'delete' => self :: GROUP_ADMIN ,
2020-10-04 17:14:15 +02:00
'import' => self :: GROUP_ADMIN ,
'index' => self :: GROUP_ADMIN ,
2018-04-02 08:29:19 +02:00
'edit' => self :: GROUP_MEMBER ,
2020-10-04 17:14:15 +02:00
'logout' => self :: GROUP_MEMBER ,
2018-04-02 08:29:19 +02:00
'forgot' => self :: GROUP_VISITOR ,
'login' => self :: GROUP_VISITOR ,
'reset' => self :: GROUP_VISITOR
];
2020-08-09 16:35:03 +02:00
2018-04-02 08:29:19 +02:00
public static $users = [];
2020-07-10 16:57:21 +02:00
//Paramètres pour choix de la signature
2020-07-02 19:53:52 +02:00
public static $signature = [
2020-07-10 16:57:21 +02:00
self :: SIGNATURE_ID => 'Identifiant' ,
self :: SIGNATURE_PSEUDO => 'Pseudo' ,
self :: SIGNATURE_FIRSTLASTNAME => 'Prénom Nom' ,
self :: SIGNATURE_LASTFIRSTNAME => 'Nom Prénom'
2020-07-02 19:53:52 +02:00
];
2020-08-09 16:35:03 +02:00
public static $userId = '' ;
2020-08-10 09:10:20 +02:00
public static $userLongtime = false ;
2020-07-02 19:53:52 +02:00
2020-10-05 16:56:30 +02:00
public static $separators = [
';' => ';' ,
',' => ',' ,
':' => ':'
];
2018-04-02 08:29:19 +02:00
/**
* Ajout
*/
public function add () {
// Soumission du formulaire
if ( $this -> isPost ()) {
2019-05-26 17:07:03 +02:00
$check = true ;
2018-04-02 08:29:19 +02:00
// L'identifiant d'utilisateur est indisponible
$userId = $this -> getInput ( 'userAddId' , helper :: FILTER_ID , true );
if ( $this -> getData ([ 'user' , $userId ])) {
self :: $inputNotices [ 'userAddId' ] = 'Identifiant déjà utilisé' ;
2019-05-26 17:07:03 +02:00
$check = false ;
2018-04-02 08:29:19 +02:00
}
// Double vérification pour le mot de passe
if ( $this -> getInput ( 'userAddPassword' , helper :: FILTER_STRING_SHORT , true ) !== $this -> getInput ( 'userAddConfirmPassword' , helper :: FILTER_STRING_SHORT , true )) {
self :: $inputNotices [ 'userAddConfirmPassword' ] = 'Incorrect' ;
2019-05-26 17:07:03 +02:00
$check = false ;
2020-05-28 15:19:32 +02:00
}
2018-04-02 08:29:19 +02:00
// Crée l'utilisateur
$userFirstname = $this -> getInput ( 'userAddFirstname' , helper :: FILTER_STRING_SHORT , true );
$userLastname = $this -> getInput ( 'userAddLastname' , helper :: FILTER_STRING_SHORT , true );
$userMail = $this -> getInput ( 'userAddMail' , helper :: FILTER_MAIL , true );
2020-09-24 18:01:34 +02:00
2020-09-24 11:34:26 +02:00
// Stockage des données
$this -> setData ([
'user' ,
$userId ,
[
'firstname' => $userFirstname ,
'forgot' => 0 ,
'group' => $this -> getInput ( 'userAddGroup' , helper :: FILTER_INT , true ),
'lastname' => $userLastname ,
2020-10-31 17:55:54 +01:00
'pseudo' => $this -> getInput ( 'userAddPseudo' , helper :: FILTER_STRING_SHORT , true ),
'signature' => $this -> getInput ( 'userAddSignature' , helper :: FILTER_INT , true ),
2020-09-24 11:34:26 +02:00
'mail' => $userMail ,
'password' => $this -> getInput ( 'userAddPassword' , helper :: FILTER_PASSWORD , true ),
2021-05-20 21:52:09 +02:00
" connectFail " => null ,
" connectTimeout " => null ,
" accessUrl " => null ,
" accessTimer " => null ,
2021-06-07 18:09:38 +02:00
" accessCsrf " => null ,
" files " => $this -> getInput ( 'userAddFiles' , helper :: FILTER_BOOLEAN )
2020-09-24 11:34:26 +02:00
]
]);
2019-05-26 17:07:03 +02:00
// Envoie le mail
2018-04-02 08:29:19 +02:00
$sent = true ;
2019-05-26 17:07:03 +02:00
if ( $this -> getInput ( 'userAddSendMail' , helper :: FILTER_BOOLEAN ) && $check === true ) {
2018-04-02 08:29:19 +02:00
$sent = $this -> sendMail (
$userMail ,
2020-11-21 15:09:10 +01:00
'Compte créé sur ' . $this -> getData ([ 'locale' , 'title' ]),
2018-04-02 08:29:19 +02:00
'Bonjour <strong>' . $userFirstname . ' ' . $userLastname . '</strong>,<br><br>' .
2020-11-21 15:09:10 +01:00
'Un administrateur vous a créé un compte sur le site ' . $this -> getData ([ 'locale' , 'title' ]) . '. Vous trouverez ci-dessous les détails de votre compte.<br><br>' .
2018-04-02 08:29:19 +02:00
'<strong>Identifiant du compte :</strong> ' . $this -> getInput ( 'userAddId' ) . '<br>' .
2020-07-11 17:18:18 +02:00
'<small>Nous ne conservons pas les mots de passe, en conséquence nous vous conseillons de conserver ce message tant que vous ne vous êtes pas connecté. Vous pourrez modifier votre mot de passe après votre première connexion.</small>' ,
2020-02-26 23:45:49 +01:00
null
2018-04-02 08:29:19 +02:00
);
}
// Valeurs en sortie
$this -> addOutput ([
'redirect' => helper :: baseUrl () . 'user' ,
2019-05-25 18:38:25 +02:00
'notification' => $sent === true ? 'Utilisateur créé' : $sent ,
'state' => $sent === true ? true : null
2018-04-02 08:29:19 +02:00
]);
}
// Valeurs en sortie
$this -> addOutput ([
'title' => 'Nouvel utilisateur' ,
'view' => 'add'
]);
}
/**
* Suppression
*/
public function delete () {
// Accès refusé
if (
// L'utilisateur n'existe pas
2019-01-15 13:51:30 +01:00
$this -> getData ([ 'user' , $this -> getUrl ( 2 )]) === null
2018-04-02 08:29:19 +02:00
// Groupe insuffisant
2020-10-14 19:17:13 +02:00
AND ( $this -> getUrl ( 'group' ) < self :: GROUP_MODERATOR )
2018-04-02 08:29:19 +02:00
) {
// Valeurs en sortie
$this -> addOutput ([
'access' => false
]);
}
2019-01-08 17:55:18 +01:00
// Jeton incorrect
2019-01-15 13:51:30 +01:00
elseif ( $this -> getUrl ( 3 ) !== $_SESSION [ 'csrf' ]) {
2019-01-08 17:55:18 +01:00
// Valeurs en sortie
$this -> addOutput ([
'redirect' => helper :: baseUrl () . 'user' ,
2019-01-16 16:17:17 +01:00
'notification' => 'Action non autorisée'
2019-01-08 17:55:18 +01:00
]);
2020-05-28 15:19:32 +02:00
}
2018-04-02 08:29:19 +02:00
// Bloque la suppression de son propre compte
2019-01-15 13:51:30 +01:00
elseif ( $this -> getUser ( 'id' ) === $this -> getUrl ( 2 )) {
2018-04-02 08:29:19 +02:00
// Valeurs en sortie
$this -> addOutput ([
'redirect' => helper :: baseUrl () . 'user' ,
'notification' => 'Impossible de supprimer votre propre compte'
]);
}
// Suppression
else {
2019-01-15 13:51:30 +01:00
$this -> deleteData ([ 'user' , $this -> getUrl ( 2 )]);
2018-04-02 08:29:19 +02:00
// Valeurs en sortie
$this -> addOutput ([
'redirect' => helper :: baseUrl () . 'user' ,
'notification' => 'Utilisateur supprimé' ,
'state' => true
]);
}
}
/**
* Édition
*/
public function edit () {
2019-02-12 14:38:56 +01:00
if ( $this -> getUrl ( 3 ) !== $_SESSION [ 'csrf' ] &&
2020-05-28 15:19:32 +02:00
$this -> getUrl ( 4 ) !== $_SESSION [ 'csrf' ]) {
2019-02-06 20:31:54 +01:00
// Valeurs en sortie
$this -> addOutput ([
'redirect' => helper :: baseUrl () . 'user' ,
'notification' => 'Action non autorisée'
]);
2020-05-28 15:19:32 +02:00
}
2018-04-02 08:29:19 +02:00
// Accès refusé
if (
// L'utilisateur n'existe pas
$this -> getData ([ 'user' , $this -> getUrl ( 2 )]) === null
// Droit d'édition
AND (
// Impossible de s'auto-éditer
(
$this -> getUser ( 'id' ) === $this -> getUrl ( 2 )
AND $this -> getUrl ( 'group' ) <= self :: GROUP_VISITOR
)
// Impossible d'éditer un autre utilisateur
2020-10-14 19:17:13 +02:00
OR ( $this -> getUrl ( 'group' ) < self :: GROUP_MODERATOR )
2018-04-02 08:29:19 +02:00
)
) {
// Valeurs en sortie
$this -> addOutput ([
'access' => false
]);
}
// Accès autorisé
else {
// Soumission du formulaire
if ( $this -> isPost ()) {
// Double vérification pour le mot de passe
$newPassword = $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'password' ]);
if ( $this -> getInput ( 'userEditNewPassword' )) {
// L'ancien mot de passe est correct
if ( password_verify ( $this -> getInput ( 'userEditOldPassword' ), $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'password' ]))) {
// La confirmation correspond au mot de passe
if ( $this -> getInput ( 'userEditNewPassword' ) === $this -> getInput ( 'userEditConfirmPassword' )) {
$newPassword = $this -> getInput ( 'userEditNewPassword' , helper :: FILTER_PASSWORD , true );
// Déconnexion de l'utilisateur si il change le mot de passe de son propre compte
if ( $this -> getUser ( 'id' ) === $this -> getUrl ( 2 )) {
helper :: deleteCookie ( 'ZWII_USER_ID' );
helper :: deleteCookie ( 'ZWII_USER_PASSWORD' );
}
}
else {
self :: $inputNotices [ 'userEditConfirmPassword' ] = 'Incorrect' ;
}
}
else {
self :: $inputNotices [ 'userEditOldPassword' ] = 'Incorrect' ;
}
}
// Modification du groupe
if (
$this -> getUser ( 'group' ) === self :: GROUP_ADMIN
AND $this -> getUrl ( 2 ) !== $this -> getUser ( 'id' )
) {
$newGroup = $this -> getInput ( 'userEditGroup' , helper :: FILTER_INT , true );
}
else {
$newGroup = $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'group' ]);
}
2020-07-02 19:53:52 +02:00
// Modification de nom Prénom
if ( $this -> getUser ( 'group' ) === self :: GROUP_ADMIN ){
$newfirstname = $this -> getInput ( 'userEditFirstname' , helper :: FILTER_STRING_SHORT , true );
$newlastname = $this -> getInput ( 'userEditLastname' , helper :: FILTER_STRING_SHORT , true );
}
else {
$newfirstname = $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'firstname' ]);
$newlastname = $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'lastname' ]);
}
2018-04-02 08:29:19 +02:00
// Modifie l'utilisateur
$this -> setData ([
'user' ,
$this -> getUrl ( 2 ),
[
2020-07-02 19:53:52 +02:00
'firstname' => $newfirstname ,
2018-04-02 08:29:19 +02:00
'forgot' => 0 ,
'group' => $newGroup ,
2020-07-02 19:53:52 +02:00
'lastname' => $newlastname ,
'pseudo' => $this -> getInput ( 'userEditPseudo' , helper :: FILTER_STRING_SHORT , true ),
'signature' => $this -> getInput ( 'userEditSignature' , helper :: FILTER_INT , true ),
2018-04-02 08:29:19 +02:00
'mail' => $this -> getInput ( 'userEditMail' , helper :: FILTER_MAIL , true ),
2020-06-19 11:09:24 +02:00
'password' => $newPassword ,
'connectFail' => $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'connectFail' ]),
'connectTimeout' => $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'connectTimeout' ]),
'accessUrl' => $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'accessUrl' ]),
'accessTimer' => $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'accessTimer' ]),
2021-06-07 18:09:38 +02:00
'accessCsrf' => $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'accessCsrf' ]),
'files' => $this -> getInput ( 'userEditFiles' , helper :: FILTER_BOOLEAN )
2018-04-02 08:29:19 +02:00
]
]);
// Redirection spécifique si l'utilisateur change son mot de passe
if ( $this -> getUser ( 'id' ) === $this -> getUrl ( 2 ) AND $this -> getInput ( 'userEditNewPassword' )) {
$redirect = helper :: baseUrl () . 'user/login/' . str_replace ( '/' , '_' , $this -> getUrl ());
}
// Redirection si retour en arrière possible
2020-11-24 08:29:53 +01:00
elseif ( $this -> getUser ( 'group' ) === 3 ) {
2018-04-02 08:29:19 +02:00
$redirect = helper :: baseUrl () . 'user' ;
}
// Redirection normale
else {
2020-11-24 08:29:53 +01:00
$redirect = helper :: baseUrl ();
2018-04-02 08:29:19 +02:00
}
// Valeurs en sortie
$this -> addOutput ([
'redirect' => $redirect ,
'notification' => 'Modifications enregistrées' ,
'state' => true
]);
}
// Valeurs en sortie
$this -> addOutput ([
'title' => $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'firstname' ]) . ' ' . $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'lastname' ]),
'view' => 'edit'
]);
}
}
/**
* Mot de passe perdu
*/
public function forgot () {
// Soumission du formulaire
if ( $this -> isPost ()) {
$userId = $this -> getInput ( 'userForgotId' , helper :: FILTER_ID , true );
if ( $this -> getData ([ 'user' , $userId ])) {
// Enregistre la date de la demande dans le compte utilisateur
$this -> setData ([ 'user' , $userId , 'forgot' , time ()]);
// Crée un id unique pour la réinitialisation
$uniqId = md5 ( json_encode ( $this -> getData ([ 'user' , $userId ])));
// Envoi le mail
$sent = $this -> sendMail (
$this -> getData ([ 'user' , $userId , 'mail' ]),
'Réinitialisation de votre mot de passe' ,
'Bonjour <strong>' . $this -> getData ([ 'user' , $userId , 'firstname' ]) . ' ' . $this -> getData ([ 'user' , $userId , 'lastname' ]) . '</strong>,<br><br>' .
'Vous avez demandé à changer le mot de passe lié à votre compte. Vous trouverez ci-dessous un lien vous permettant de modifier celui-ci.<br><br>' .
'<a href="' . helper :: baseUrl () . 'user/reset/' . $userId . '/' . $uniqId . '" target="_blank">' . helper :: baseUrl () . 'user/reset/' . $userId . '/' . $uniqId . '</a><br><br>' .
2020-02-26 23:45:49 +01:00
'<small>Si nous n\'avez pas demandé à réinitialiser votre mot de passe, veuillez ignorer ce mail.</small>' ,
null
2018-04-02 08:29:19 +02:00
);
// Valeurs en sortie
$this -> addOutput ([
'notification' => ( $sent === true ? 'Un mail vous a été envoyé afin de continuer la réinitialisation' : $sent ),
'state' => ( $sent === true ? true : null )
]);
}
// L'utilisateur n'existe pas
else {
// Valeurs en sortie
$this -> addOutput ([
'notification' => 'Cet utilisateur n\'existe pas'
]);
}
}
// Valeurs en sortie
$this -> addOutput ([
'display' => self :: DISPLAY_LAYOUT_LIGHT ,
'title' => 'Mot de passe oublié' ,
'view' => 'forgot'
]);
}
/**
* Liste des utilisateurs
*/
public function index () {
$userIdsFirstnames = helper :: arrayCollumn ( $this -> getData ([ 'user' ]), 'firstname' );
ksort ( $userIdsFirstnames );
foreach ( $userIdsFirstnames as $userId => $userFirstname ) {
2020-04-07 17:36:24 +02:00
if ( $this -> getData ([ 'user' , $userId , 'group' ])) {
self :: $users [] = [
$userId ,
$userFirstname . ' ' . $this -> getData ([ 'user' , $userId , 'lastname' ]),
self :: $groups [ $this -> getData ([ 'user' , $userId , 'group' ])],
template :: button ( 'userEdit' . $userId , [
'href' => helper :: baseUrl () . 'user/edit/' . $userId . '/back/' . $_SESSION [ 'csrf' ],
'value' => template :: ico ( 'pencil' )
]),
template :: button ( 'userDelete' . $userId , [
'class' => 'userDelete buttonRed' ,
'href' => helper :: baseUrl () . 'user/delete/' . $userId . '/' . $_SESSION [ 'csrf' ],
'value' => template :: ico ( 'cancel' )
])
];
}
2018-04-02 08:29:19 +02:00
}
// Valeurs en sortie
$this -> addOutput ([
'title' => 'Liste des utilisateurs' ,
'view' => 'index'
]);
}
/**
* Connexion
*/
public function login () {
// Soumission du formulaire
2021-01-03 18:41:25 +01:00
$logStatus = '' ;
2018-04-02 08:29:19 +02:00
if ( $this -> isPost ()) {
2020-12-30 17:41:27 +01:00
// Lire Id du compte
$userId = $this -> getInput ( 'userLoginId' , helper :: FILTER_ID , true );
// Check le captcha
2020-09-29 19:03:35 +02:00
if (
2020-10-06 18:28:21 +02:00
$this -> getData ([ 'config' , 'connect' , 'captcha' ])
AND password_verify ( $this -> getInput ( 'userLoginCaptcha' , helper :: FILTER_INT ), $this -> getInput ( 'userLoginCaptchaResult' ) ) === false )
2020-09-29 19:03:35 +02:00
{
2021-01-03 18:41:25 +01:00
$captcha = false ;
2020-10-09 08:37:34 +02:00
} else {
2021-01-03 18:41:25 +01:00
$captcha = true ;
}
/**
* Aucun compte existant
*/
if ( ! $this -> getData ([ 'user' , $userId ])) {
$logStatus = 'Compte inconnu' ;
//Stockage de l'IP
$this -> setData ([
'blacklist' ,
$userId ,
[
'connectFail' => $this -> getData ([ 'blacklist' , $userId , 'connectFail' ]) + 1 ,
'lastFail' => time (),
'ip' => helper :: getIp ()
]
]);
// Verrouillage des IP
$ipBlackList = helper :: arrayCollumn ( $this -> getData ([ 'blacklist' ]), 'ip' );
if ( $this -> getData ([ 'blacklist' , $userId , 'connectFail' ]) >= $this -> getData ([ 'config' , 'connect' , 'attempt' ])
AND in_array ( $this -> getData ([ 'blacklist' , $userId , 'ip' ]), $ipBlackList ) ) {
$logStatus = 'Compte inconnu verrouillé' ;
// Valeurs en sortie
$this -> addOutput ([
'notification' => 'Compte verrouillé' ,
'redirect' => helper :: baseUrl (),
'state' => false
2020-06-27 16:21:22 +02:00
]);
2021-01-03 18:41:25 +01:00
} else {
// Valeurs en sortie
$this -> addOutput ([
'notification' => 'Captcha, identifiant ou mot de passe incorrects'
]);
}
/**
* Le compte existe
*/
} else {
// Cas 4 : le délai de blocage est dépassé et le compte est au max - Réinitialiser
if ( $this -> getData ([ 'user' , $userId , 'connectTimeout' ]) + $this -> getData ([ 'config' , 'connect' , 'timeout' ]) < time ()
AND $this -> getData ([ 'user' , $userId , 'connectFail' ]) === $this -> getData ([ 'config' , 'connect' , 'attempt' ]) ) {
$this -> setData ([ 'user' , $userId , 'connectFail' , 0 ]);
$this -> setData ([ 'user' , $userId , 'connectTimeout' , 0 ]);
}
// Check la présence des variables et contrôle du blocage du compte si valeurs dépassées
// Vérification du mot de passe et du groupe
if (
( $this -> getData ([ 'user' , $userId , 'connectTimeout' ]) + $this -> getData ([ 'config' , 'connect' , 'timeout' ]) ) < time ()
AND $this -> getData ([ 'user' , $userId , 'connectFail' ]) < $this -> getData ([ 'config' , 'connect' , 'attempt' ])
AND password_verify ( $this -> getInput ( 'userLoginPassword' , helper :: FILTER_STRING_SHORT , true ), $this -> getData ([ 'user' , $userId , 'password' ]))
AND $this -> getData ([ 'user' , $userId , 'group' ]) >= self :: GROUP_MEMBER
AND $captcha === true
) {
// RAZ
$this -> setData ([ 'user' , $userId , 'connectFail' , 0 ]);
$this -> setData ([ 'user' , $userId , 'connectTimeout' , 0 ]);
// Expiration
$expire = $this -> getInput ( 'userLoginLongTime' ) ? strtotime ( " +1 year " ) : 0 ;
$c = $this -> getInput ( 'userLoginLongTime' , helper :: FILTER_BOOLEAN ) === true ? 'true' : 'false' ;
setcookie ( 'ZWII_USER_ID' , $userId , $expire , helper :: baseUrl ( false , false ) , '' , helper :: isHttps (), true );
setcookie ( 'ZWII_USER_PASSWORD' , $this -> getData ([ 'user' , $userId , 'password' ]), $expire , helper :: baseUrl ( false , false ), '' , helper :: isHttps (), true );
setcookie ( 'ZWII_USER_LONGTIME' , $c , $expire , helper :: baseUrl ( false , false ), '' , helper :: isHttps (), true );
// Accès multiples avec le même compte
$this -> setData ([ 'user' , $userId , 'accessCsrf' , $_SESSION [ 'csrf' ]]);
// Valeurs en sortie lorsque le site est en maintenance et que l'utilisateur n'est pas administrateur
if (
$this -> getData ([ 'config' , 'maintenance' ])
AND $this -> getData ([ 'user' , $userId , 'group' ]) < self :: GROUP_ADMIN
) {
2020-07-17 17:27:34 +02:00
$this -> addOutput ([
2021-01-03 18:41:25 +01:00
'notification' => 'Seul un administrateur peut se connecter lors d\'une maintenance' ,
2020-07-17 17:27:34 +02:00
'redirect' => helper :: baseUrl (),
'state' => false
]);
2020-07-02 19:53:52 +02:00
} else {
2021-01-03 18:41:25 +01:00
$logStatus = 'Connexion réussie' ;
2020-07-17 17:27:34 +02:00
// Valeurs en sortie
$this -> addOutput ([
2021-01-03 18:41:25 +01:00
'notification' => 'Bienvenue ' . $this -> getData ([ 'user' , $userId , 'firstname' ]) . ' ' . $this -> getData ([ 'user' , $userId , 'lastname' ]) ,
'redirect' => helper :: baseUrl () . str_replace ( '_' , '/' , str_replace ( '__' , '#' , $this -> getUrl ( 2 ))),
'state' => true
2020-07-17 17:27:34 +02:00
]);
2020-07-02 19:38:52 +02:00
}
2021-01-03 18:41:25 +01:00
// Sinon notification d'échec
} else {
$notification = 'Captcha, identifiant ou mot de passe incorrects' ;
$logStatus = $captcha === true ? 'Erreur de mot de passe' : 'Erreur de captcha' ;
// Cas 1 le nombre de connexions est inférieur aux tentatives autorisées : incrément compteur d'échec
if ( $this -> getData ([ 'user' , $userId , 'connectFail' ]) < $this -> getData ([ 'config' , 'connect' , 'attempt' ])) {
$this -> setData ([ 'user' , $userId , 'connectFail' , $this -> getdata ([ 'user' , $userId , 'connectFail' ]) + 1 ]);
2020-07-17 17:27:34 +02:00
}
2021-01-03 18:41:25 +01:00
// Cas 2 la limite du nombre de connexion est atteinte : placer le timer
if ( $this -> getdata ([ 'user' , $userId , 'connectFail' ]) == $this -> getData ([ 'config' , 'connect' , 'attempt' ]) ) {
$this -> setData ([ 'user' , $userId , 'connectTimeout' , time ()]);
2020-07-17 17:27:34 +02:00
}
2021-01-03 18:41:25 +01:00
// Cas 3 le délai de bloquage court
if ( $this -> getData ([ 'user' , $userId , 'connectTimeout' ]) + $this -> getData ([ 'config' , 'connect' , 'timeout' ]) > time () ) {
$notification = 'Accès bloqué ' . ( $this -> getData ([ 'config' , 'connect' , 'timeout' ]) / 60 ) . ' minutes.' ;
}
// Valeurs en sortie
$this -> addOutput ([
'notification' => $notification
]);
2020-07-02 19:53:52 +02:00
}
2018-04-02 08:29:19 +02:00
}
}
2021-01-03 18:41:25 +01:00
// Journalisation
$dataLog = mb_detect_encoding ( strftime ( '%d/%m/%y' , time ()), 'UTF-8' , true )
? strftime ( '%d/%m/%y' , time ()) . ';' . strftime ( '%R' , time ()) . ';'
: utf8_encode ( strftime ( '%d/%m/%y' , time ())) . ';' . utf8_encode ( strftime ( '%R' , time ())) . ';' ;
$dataLog .= helper :: getIp () . ';' ;
2021-01-04 17:33:38 +01:00
$dataLog .= $this -> getInput ( 'userLoginId' , helper :: FILTER_ID ) . ';' ;
2021-01-03 18:41:25 +01:00
$dataLog .= $this -> getUrl () . ';' ;
$dataLog .= $logStatus ;
$dataLog .= PHP_EOL ;
if ( $this -> getData ([ 'config' , 'connect' , 'log' ])) {
file_put_contents ( self :: DATA_DIR . 'journal.log' , $dataLog , FILE_APPEND );
}
// Stockage des cookies
2020-08-09 16:35:03 +02:00
if ( ! empty ( $_COOKIE [ 'ZWII_USER_ID' ])) {
self :: $userId = $_COOKIE [ 'ZWII_USER_ID' ];
}
2020-08-10 09:10:20 +02:00
if ( ! empty ( $_COOKIE [ 'ZWII_USER_LONGTIME' ])) {
2020-08-10 09:16:28 +02:00
self :: $userLongtime = $_COOKIE [ 'ZWII_USER_LONGTIME' ] == 'true' ? true : false ;
2020-08-10 09:10:20 +02:00
}
2018-04-02 08:29:19 +02:00
// Valeurs en sortie
$this -> addOutput ([
'display' => self :: DISPLAY_LAYOUT_LIGHT ,
'title' => 'Connexion' ,
'view' => 'login'
]);
}
/**
* Déconnexion
*/
public function logout () {
2020-08-09 16:35:03 +02:00
// Ne pas effacer l'identifiant mais seulement le mot de passe
2020-09-12 09:05:57 +02:00
if ( array_key_exists ( 'ZWII_USER_LONGTIME' , $_COOKIE )
AND $_COOKIE [ 'ZWII_USER_LONGTIME' ] !== 'true' ) {
2020-08-10 09:10:20 +02:00
helper :: deleteCookie ( 'ZWII_USER_ID' );
helper :: deleteCookie ( 'ZWII_USER_LONGTIME' );
}
2018-04-02 08:29:19 +02:00
helper :: deleteCookie ( 'ZWII_USER_PASSWORD' );
2019-01-13 17:54:42 +01:00
session_destroy ();
2018-04-02 08:29:19 +02:00
// Valeurs en sortie
$this -> addOutput ([
'notification' => 'Déconnexion réussie' ,
'redirect' => helper :: baseUrl ( false ),
'state' => true
]);
}
/**
* Réinitialisation du mot de passe
*/
public function reset () {
// Accès refusé
if (
// L'utilisateur n'existe pas
$this -> getData ([ 'user' , $this -> getUrl ( 2 )]) === null
// Lien de réinitialisation trop vieux
OR $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'forgot' ]) + 86400 < time ()
// Id unique incorrecte
OR $this -> getUrl ( 3 ) !== md5 ( json_encode ( $this -> getData ([ 'user' , $this -> getUrl ( 2 )])))
) {
// Valeurs en sortie
$this -> addOutput ([
'access' => false
]);
}
// Accès autorisé
else {
// Soumission du formulaire
if ( $this -> isPost ()) {
// Double vérification pour le mot de passe
if ( $this -> getInput ( 'userResetNewPassword' )) {
// La confirmation ne correspond pas au mot de passe
if ( $this -> getInput ( 'userResetNewPassword' , helper :: FILTER_STRING_SHORT , true ) !== $this -> getInput ( 'userResetConfirmPassword' , helper :: FILTER_STRING_SHORT , true )) {
$newPassword = $this -> getData ([ 'user' , $this -> getUrl ( 2 ), 'password' ]);
self :: $inputNotices [ 'userResetConfirmPassword' ] = 'Incorrect' ;
}
else {
$newPassword = $this -> getInput ( 'userResetNewPassword' , helper :: FILTER_PASSWORD , true );
}
// Modifie le mot de passe
$this -> setData ([ 'user' , $this -> getUrl ( 2 ), 'password' , $newPassword ]);
// Réinitialise la date de la demande
$this -> setData ([ 'user' , $this -> getUrl ( 2 ), 'forgot' , 0 ]);
2020-11-22 18:56:14 +01:00
// Réinitialise le blocage
$this -> setData ([ 'user' , $this -> getUrl ( 2 ), 'connectFail' , 0 ]);
$this -> setData ([ 'user' , $this -> getUrl ( 2 ), 'connectTimeout' , 0 ]);
2018-04-02 08:29:19 +02:00
// Valeurs en sortie
$this -> addOutput ([
'notification' => 'Nouveau mot de passe enregistré' ,
2020-11-22 18:56:14 +01:00
//'redirect' => helper::baseUrl() . 'user/login/' . str_replace('/', '_', $this->getUrl()),
'redirect' => helper :: baseUrl (),
2018-04-02 08:29:19 +02:00
'state' => true
]);
}
}
// Valeurs en sortie
$this -> addOutput ([
2020-10-07 19:01:57 +02:00
'display' => self :: DISPLAY_LAYOUT_LIGHT ,
2018-04-02 08:29:19 +02:00
'title' => 'Réinitialisation du mot de passe' ,
'view' => 'reset'
]);
}
}
2020-10-04 17:14:15 +02:00
/**
* Importation CSV d ' utilisateurs
*/
public function import () {
2020-10-04 18:34:34 +02:00
// Soumission du formulaire
2020-10-06 15:56:49 +02:00
$notification = '' ;
$success = true ;
2020-10-04 18:34:34 +02:00
if ( $this -> isPost ()) {
// Lecture du CSV et construction du tableau
2020-10-05 16:56:30 +02:00
$file = $this -> getInput ( 'userImportCSVFile' , helper :: FILTER_STRING_SHORT , true );
2020-10-06 08:29:14 +02:00
$filePath = self :: FILE_DIR . 'source/' . $file ;
2020-10-08 10:33:53 +02:00
if ( $file AND file_exists ( $filePath )) {
2020-10-08 21:16:28 +02:00
// Analyse et extraction du CSV
2020-10-05 16:56:30 +02:00
$rows = array_map ( function ( $row ) { return str_getcsv ( $row , $this -> getInput ( 'userImportSeparator' ) ); }, file ( $filePath ));
$header = array_shift ( $rows );
$csv = array ();
foreach ( $rows as $row ) {
$csv [] = array_combine ( $header , $row );
2020-10-04 18:34:34 +02:00
}
2020-10-08 21:16:28 +02:00
// Traitement des données
2020-10-05 16:56:30 +02:00
foreach ( $csv as $item ) {
2020-10-08 21:16:28 +02:00
// Données valides
2020-12-04 20:57:02 +01:00
if ( array_key_exists ( 'id' , $item )
AND array_key_exists ( 'prenom' , $item )
2020-10-08 21:16:28 +02:00
AND array_key_exists ( 'nom' , $item )
2020-12-04 20:57:02 +01:00
AND array_key_exists ( 'groupe' , $item )
2020-10-19 09:22:56 +02:00
AND array_key_exists ( 'email' , $item )
2020-10-19 09:53:28 +02:00
AND $item [ 'nom' ]
2020-10-19 09:22:56 +02:00
AND $item [ 'prenom' ]
2020-12-04 20:57:02 +01:00
AND $item [ 'id' ]
2020-10-19 09:53:28 +02:00
AND $item [ 'email' ]
2020-12-04 20:57:02 +01:00
AND $item [ 'groupe' ]
2020-10-19 09:53:28 +02:00
) {
2020-12-04 20:57:02 +01:00
// Validation du groupe
$item [ 'groupe' ] = ( int ) $item [ 'groupe' ];
$item [ 'groupe' ] = ( $item [ 'groupe' ] >= self :: GROUP_BANNED AND $item [ 'groupe' ] <= self :: GROUP_ADMIN )
? $item [ 'groupe' ] : 1 ;
2020-10-08 21:16:28 +02:00
// L'utilisateur existe
if ( $this -> getData ([ 'user' , helper :: filter ( $item [ 'id' ] , helper :: FILTER_ID )]))
{
// Notification du doublon
$item [ 'notification' ] = template :: ico ( 'cancel' );
// Création du tableau de confirmation
self :: $users [] = [
helper :: filter ( $item [ 'id' ] , helper :: FILTER_ID ),
$item [ 'nom' ],
$item [ 'prenom' ],
self :: $groups [ $item [ 'groupe' ]],
$item [ 'prenom' ],
2020-12-03 14:06:12 +01:00
helper :: filter ( $item [ 'email' ] , helper :: FILTER_MAIL ),
2020-10-08 21:16:28 +02:00
$item [ 'notification' ]
];
// L'utilisateur n'existe pas
} else {
// Nettoyage de l'identifiant
$userId = helper :: filter ( $item [ 'id' ] , helper :: FILTER_ID );
// Enregistre le user
2020-10-18 17:19:20 +02:00
$create = $this -> setData ([
2020-10-08 21:16:28 +02:00
'user' ,
$userId , [
'firstname' => $item [ 'prenom' ],
'forgot' => 0 ,
2020-10-19 09:53:28 +02:00
'group' => $item [ 'groupe' ] ,
2020-10-08 21:16:28 +02:00
'lastname' => $item [ 'nom' ],
'mail' => $item [ 'email' ],
'pseudo' => $item [ 'prenom' ],
'signature' => 1 , // Pseudo
'password' => uniqid (), // A modifier à la première connexion
2021-05-20 21:52:09 +02:00
" connectFail " => null ,
" connectTimeout " => null ,
" accessUrl " => null ,
" accessTimer " => null ,
" accessCsrf " => null
2020-10-08 21:16:28 +02:00
]]);
// Icône de notification
2020-10-18 17:19:20 +02:00
$item [ 'notification' ] = $create ? template :: ico ( 'check' ) : template :: ico ( 'cancel' );
2020-10-08 21:16:28 +02:00
// Envoi du mail
2020-10-18 17:19:20 +02:00
if ( $create
AND $this -> getInput ( 'userImportNotification' , helper :: FILTER_BOOLEAN ) === true ) {
2020-10-08 21:16:28 +02:00
$sent = $this -> sendMail (
$item [ 'email' ],
2020-11-21 15:09:10 +01:00
'Compte créé sur ' . $this -> getData ([ 'locale' , 'title' ]),
2020-10-08 21:16:28 +02:00
'Bonjour <strong>' . $item [ 'prenom' ] . ' ' . $item [ 'nom' ] . '</strong>,<br><br>' .
2020-11-21 15:09:10 +01:00
'Un administrateur vous a créé un compte sur le site ' . $this -> getData ([ 'locale' , 'title' ]) . '. Vous trouverez ci-dessous les détails de votre compte.<br><br>' .
2020-10-08 21:16:28 +02:00
'<strong>Identifiant du compte :</strong> ' . $userId . '<br>' .
'<small>Un mot de passe provisoire vous été attribué, à la première connexion cliquez sur Mot de passe Oublié.</small>'
);
if ( $sent === true ) {
// Mail envoyé changement de l'icône
2020-10-18 17:27:20 +02:00
$item [ 'notification' ] = template :: ico ( 'mail' ) ;
2020-10-08 21:16:28 +02:00
}
}
2020-10-18 17:19:20 +02:00
// Création du tableau de confirmation
self :: $users [] = [
$userId ,
$item [ 'nom' ],
$item [ 'prenom' ],
self :: $groups [ $item [ 'groupe' ]],
$item [ 'prenom' ],
$item [ 'email' ],
$item [ 'notification' ]
];
2020-10-08 10:33:53 +02:00
}
2020-10-05 16:56:30 +02:00
}
}
2020-10-08 12:49:09 +02:00
if ( empty ( self :: $users )) {
2020-10-08 21:16:28 +02:00
$notification = 'Rien à importer, erreur de format ou fichier incorrect' ;
2020-10-08 12:49:09 +02:00
$success = false ;
} else {
$notification = 'Importation effectuée' ;
$success = true ;
}
2020-10-05 16:56:30 +02:00
} else {
2020-10-06 15:25:12 +02:00
$notification = 'Erreur de lecture, vérifiez les permissions' ;
2020-10-05 16:56:30 +02:00
$success = false ;
2020-10-04 18:34:34 +02:00
}
}
2020-10-04 17:14:15 +02:00
// Valeurs en sortie
$this -> addOutput ([
2020-10-04 18:34:34 +02:00
'title' => 'Importation' ,
2020-10-05 16:56:30 +02:00
'view' => 'import' ,
'notification' => $notification ,
'state' => $success
2020-10-04 17:14:15 +02:00
]);
}
2020-10-04 18:34:34 +02:00
2021-06-07 18:09:38 +02:00
}