/*!
* GJframework
* model/User.class.php
* v1.1.0 (07/08/2019)
*
* Created by Guillaume Juncker on 24/08/2018.
* Copyright © Guillaume Juncker. All rights reserved.
*/
/**
* User
* Classe de gestion des utilisateurs du site
*/
class User extends DB {
private $min_password_len = 8,
$max_password_try = 5;
public $id = "",
$first_name = "",
$last_name = "",
$email = "",
$password = "",
$accreditation = 0,
$login_date = "";
const ACCREDITATION_NONE = 0,
ACCREDITATION_GUEST = 1,
ACCREDITATION_MEMBRE = 2,
ACCREDITATION_MODERATOR = 3,
ACCREDITATION_ADMINISTRATOR = 4,
ACCREDITATION_DEVELOPER = 5,
ACCREDITATION_GJ = 99;
/*------------------------------------------------------------------------------------------------------------------------------*/
/**
* __construct
* Construit un objet User
* [@param mixed $vars: un id, un email ou un tableau de clés => valeurs à rechercher]
* @return User: un objet User
*/
public function __construct($vars = NULL) {
if(!is_array($vars) AND !is_numeric($vars)) { $vars = array("email" => $vars);}
parent::__construct($vars);
}
/*------------------------------------------------------------------------------------------------------------------------------*/
/**
* initRequiredVars
* Implémentation de la fonction parente
* @return void
*/
protected function initRequiredVars() {
$this->required_vars = array("first_name", "last_name", "email", "password");
}
/**
* initUniqueVars
* Implémentation de la fonction parente
* @return void
*/
protected function initUniqueVars() {
$this->unique_vars = array("email");
}
/**
* initErrors
* Surcharge de la fonction parente pour personnaliser les messages
* @return void
*/
protected function initErrors() {
parent::initErrors();
$this->Errors['I_SUCCESS']->message = "Votre compte a bien été créer, bienvenue";
$this->Errors['I_MISSING']->message = "Veuillez renseigner tous les champs obligatoires";
$this->Errors['I_EXISTS']->message = "Vous semblez être déjà inscrit avec cette adresse e-mail, vous pouvez vous connecter";
$this->Errors['I_PASSWORD_LEN'] = new CustomError("warning", "Par sécurité pour vos données personnelles, votre mot de passe doit comporter au minimum ".$this->min_password_len." caractères");
$this->Errors['I_ERROR']->message = "Une erreur s'est produite lors de la création de votre compte, veuillez réessayer";
$this->Errors['L_SUCCESS'] = new CustomError("success", "Bonjour ".$this->first_name);
if((new Datime())->hour > 18) { $this->Errors['L_SUCCESS']->message = "Bonsoir ".$this->first_name;}
$this->Errors['L_MISSING'] = new CustomError("warning", "Veuillez renseigner tous les champs obligatoires");
$this->Errors['L_FAILURE'] = new CustomError("danger", "Identifiant ou mot de passe invalide, ".($this->max_password_try - ($_SESSION['failures']))." tentative(s) restante(s)");
$this->Errors['U_SUCCESS']->message = "Vos informations personnelles ont bien été modifiées";
$this->Errors['U_MISSING']->message = "Veuillez renseigner tous les champs obligatoires";
$this->Errors['U_EXISTS']->message = "Cette adresse e-mail est déjà utilisée par un autre compte";
$this->Errors['U_ERROR']->message = "Une erreur s'est produite lors de la modification de vos informations personnelles, veuillez réessayer";
$this->Errors['UP_SUCCESS'] = new CustomError("success", "Votre mot de passe a bien été modifié");
$this->Errors['UP_INVALID'] = new CustomError("danger", "Le mot de passe actuel est invalide");
$this->Errors['UP_ERROR'] = new CustomError("danger", "Une erreur s'est produite lors de la modification de votre mot de passe, veuillez réessayer");
$this->Errors['FP_SUCCESS'] = new CustomError("success", "Un code de sécurité à six chiffres vous a été envoyé par e-mail, veuillez le renseigner ici pour choisir votre nouveau mot de passe");
$this->Errors['FP_INVALID'] = new CustomError("danger", "Identifiant invalide");
$this->Errors['SC_INVALID'] = new CustomError("danger", "Code de sécurité invalide ou périmé, ".($this->max_password_try - ($_SESSION['failures']))." tentative(s) restante(s)");
$this->Errors['FP_ERROR'] = new CustomError("danger", "Une erreur s'est produite lors de l'envoi du code de sécurité, veuillez réessayer");
$this->Errors['D_SUCCESS']->message = "Votre compte et toutes vos données personnelles ont bien été effacées";
$this->Errors['D_ERROR']->message = "Une erreur s'est produite lors de la suppression de votre compte, veuillez réessayer";
}
/*------------------------------------------------------------------------------------------------------------------------------*/
/**
* getByEmail
* Version réservée à l'e-mail de la fonction getBy()
* @param string $email: l'adresse e-mail à rechercher
* @return mixed: l'Objet chargé s'il existe, FALSE sinon
*/
public function getByEmail(string $email) {
return $this->getBy(array("email" => $email));
}
/**
* getAll
* Surcharge de la fonction parente pour vérifier que l'utilisateur actif peut voir tous les utilisateurs
* @return array: un tableau de tous les Objets
*/
public function getAll(string $req = "") {
if($this->accreditation>= self::ACCREDITATION_ADMINISTRATOR) {
if(!$req) { $req = "WHERE accreditation <= '".$this->accreditation."'";}
return parent::getAll($req);
}
}
/**
* name
* Met en forme le nom complet de l'utilisateur
* [@param string $format: le format d'affichage du nom complet]
* @return string: le nom de l'utilisateur formaté
*/
public function name($format = "first last") {
if($this->id) {
return preg_replace(array("#\bfirst\b#", "#\bf\b#", "#\blast\b#", "#\bl\b#"),
array($this->first_name, $this->first_name[0], $this->last_name, $this->last_name[0]),
$format);
}
return "";
}
/**
* accreditations
* Liste l'ensemble des accréditations disponibles
* @return array: le tableau des accréditations possibles
*/
public function accreditations() {
return array(self::ACCREDITATION_NONE => "Aucune",
self::ACCREDITATION_GUEST => "Invité",
self::ACCREDITATION_MEMBRE => "Membre",
self::ACCREDITATION_MODERATOR => "Modérateur",
self::ACCREDITATION_ADMINISTRATOR => "Administrateur",
self::ACCREDITATION_DEVELOPER => "Développeur",
self::ACCREDITATION_GJ => "GJ");
}
/**
* accreditation
* Met en forme l'accréditation de l'utilisateur
* @return string: l'accréditation de l'utilisateur formaté
*/
public function accreditation() {
return $this->accreditations()[$this->accreditation];
}
/*------------------------------------------------------------------------------------------------------------------------------*/
/**
* insert
* Surcharge de la fonction parente pour ajouter un utilisateur après vérification et modifications de certaines données
* @return CustomError: l'erreur déclenchée à l'exécution
*/
public function insert(array &$vars) {
if(strlen($vars['password'])>= $this->min_password_len) {
$vars['first_name'] = ucwords(strtolower($vars['first_name']));
$vars['last_name'] = ucwords(strtolower($vars['last_name']));
$vars['email'] = strtolower($vars['email']);
$vars['password'] = password_hash($vars['password'], PASSWORD_DEFAULT);
return parent::insert($vars);
}
else { return $this->Errors['I_PASSWORD_LEN'];}
}
/**
* invite
* Ajout d'un utilisateur par un autre utilisateur de niveau ADMINISTRATEUR ou plus
* @param array $vars: un tableau de clés => valeurs à insérer
* @return CustomError: l'erreur déclenchée à l'exécution
*/
public function invite(array $vars) {
if($this->accreditation > $vars['accreditation']) {
$password_clear = $vars['password'];
if(($insertError = $this->insert($vars))->bool()) {
$emailBody = " Bonjour ".$vars['first_name'].",
Nous vous informons qu'un compte vous a été créer sur le site de base_url."\">".$GLOBALS['_SITE']->name.".
Vous pouvez vous y connecter dès maintenant avec les éléments suivants :
";
$GLOBALS['_SITE']->Email->send($vars['email'], "Bienvenue sur le site de ".$GLOBALS['_SITE']->name, $emailBody);
}
return $insertError;
}
else { return $GLOBALS['_SITE']->Errors['ACCESS'];}
}
/**
* login
* Vérifie et connecte l'utilisateur à son compte
* @param string $password: le mot de passe entré à la connexion
* @return CustomError: l'erreur déclenchée à l'exécution
*/
public function login(string $password) {
if(password_verify($password, $this->password)) {
$req = $this->pdo()->prepare("UPDATE ".$this->db_table." SET login_date = NOW() WHERE id = :id");
$req->execute(array("id" => $this->id));
$_SESSION['user_id'] = $this->id;
unset($_SESSION['failures']);
return $this->Errors['L_SUCCESS'];
}
else {
$_SESSION['failures']++;
return $this->Errors['L_FAILURE'];
}
}
/**
* auth
* Permet la connexion au compte invité
* @param array $vars: le tableau renvoyé par le formulaire d'authentification
* @return CustomError: l'erreur déclenchée à l'exécution
*/
public function auth($vars) {
if($GLOBALS['_SITE']->reCaptcha($_POST['g-recaptcha-response'])) {
$_SESSION['auth'] = $vars['ref'];
unset($_SESSION['failures']);
return $this->Errors['L_SUCCESS'];
}
$_SESSION['failures']++;
return $this->Errors['L_FAILURE'];
}
/**
* update
* Surcharge de la fonction parente pour modifier un utilisateur après modifications de certaines données
* @return CustomError: l'erreur déclenchée à l'exécution
*/
public function update(array $vars) {
if($this->id!= $GLOBALS['_USER']->id AND $GLOBALS['_USER']->accreditation<= $vars['accreditation']) {
return $GLOBALS['_SITE']->Errors['ACCESS'];
}
$vars['first_name'] = ucwords(strtolower($vars['first_name']));
$vars['last_name'] = ucwords(strtolower($vars['last_name']));
$vars['email'] = strtolower($vars['email']);
return parent::update($vars);
}
/**
* setPassword
* Modifie le mot de passe de l'utilisateur
* @param string $password: le mot de passe actuel
* @param string $new_password: le nouveau mot de passe
* @return CustomError: l'erreur déclenchée à l'exécution
*/
public function setPassword(string $password, string $new_password) {
if(password_verify($password, $this->password)) {
if(strlen($new_password)>= $this->min_password_len) {
$new_password = password_hash($new_password, PASSWORD_DEFAULT);
$req = $this->pdo()->prepare("UPDATE ".$this->db_table." SET password = :password WHERE id = :id");
if($req->execute(array("id" => $this->id,
"password" => $new_password))) {
return $this->Errors['UP_SUCCESS'];
}
else { return $this->Errors['UP_ERROR'];}
}
else { return $this->Errors['I_PASSWORD_LEN'];}
}
else { return $this->Errors['UP_INVALID'];}
}
/**
* forgotPassword
* Envoi d'un code de sécurité par e-mail pour modifier un mot de passe oublié
* @return CustomError: l'erreur déclenchée à l'exécution
*/
public function forgotPassword() {
if($this->id) {
$forgotpassword_securitykey = $GLOBALS['_SITE']->strRand(6, FALSE, TRUE, FALSE);
setcookie("forgotpassword_securitykey", password_hash($forgotpassword_securitykey, PASSWORD_DEFAULT), time() + 60/*min*/ * 60/*sec*/, "/", NULL, FALSE, TRUE);
$emailBody = "Bonjour,
Vous avez oublié votre mot de passe … pas de panique.
Voici le code de sécurité nécessaire à la suite de la procédure : $forgotpassword_securitykey.
Si vous n'êtes pas l'auteur de cette demande ou si vous avez retrouvé votre mot de passe, vous pouvez simplement ignorer cet e-mail, votre mot de passe reste inchangé.
";
if($GLOBALS['_SITE']->Email->send($this->email, "Code de sécurité", $emailBody)) {
$_SESSION['forgotpassword_login'] = $this->email;
return $this->Errors['FP_SUCCESS'];
}
else { return $this->Errors['FP_ERROR'];}
}
else { return $this->Errors['FP_INVALID'];}
}
/**
* forgotPasswordSecurity
* Modification du mot de passe oublié après vérification du code de sécurité
* @param int $code: le code de sécurité
* @param string $new_password: le nouveau mot de passe
* @return CustomError: l'erreur déclenchée à l'exécution
*/
public function forgotPasswordSecurity(int $code, string $new_password) {
if(password_verify($code, $_COOKIE['forgotpassword_securitykey'])) {
if(strlen($new_password)>= $this->min_password_len) {
$new_password = password_hash($new_password, PASSWORD_DEFAULT);
$req = $this->pdo()->prepare("UPDATE ".$this->db_table." SET password = :password WHERE id = :id");
if($req->execute(array("id" => $this->id,
"password" => $new_password))) {
setcookie("forgotpassword_securitykey", "", time() - 1, "/", NULL, FALSE, TRUE);
unset($_SESSION['forgotpassword_login'], $_SESSION['failures']);
return $this->Errors['UP_SUCCESS'];
}
else { return $this->Errors['UP_ERROR'];}
}
else { return $this->Errors['I_PASSWORD_LEN'];}
}
else {
$_SESSION['failures']++;
return $this->Errors['SC_INVALID'];
}
}
/*------------------------------------------------------------------------------------------------------------------------------*/
public function __toString() {
// if($this-id== $GLOBALS['_USER']->id) { return "vous";}
return $this->name();
}
}