Bonjour,
je viens mettre ma solution à mon problème qui était :
Prestashop 1.7.4.2
Permettre à un client de se logger avec un identifiant client unique. Le client pouvant avoir plusieurs comptes prestashop mais UNE SEULE adresse email (la même pour tous ses comptes).
Je tiens une table customer_cptes contenant id_customer (celui de prestashop) et num_compte (numéro du compte client chez mon client)
- je modifie la classe /classes/Customer.php (ou override si certains y arrivent, mais pour moi ça ne veut pas marcher...)
=> dans la fonction getByEmail je rajoute un else :
if (Validate::isEmail($email)){
//----------- code original de la fonction
if (!Validate::isEmail($email) || ($plaintextPassword && !Validate::isPasswd($plaintextPassword))) {
die(Tools::displayError());
}
$shopGroup = Shop::getGroupFromShop(Shop::getContextShopID(), false);
$sql = new DbQuery();
$sql->select('c.`passwd`');
$sql->from('customer', 'c');
$sql->where('c.`email` = \''.pSQL($email).'\'');
if (Shop::getContext() == Shop::CONTEXT_SHOP && $shopGroup['share_customer']) {
$sql->where('c.`id_shop_group` = '.(int) Shop::getContextShopGroupID());
} else {
$sql->where('c.`id_shop` IN ('.implode(', ', Shop::getContextListShopID(Shop::SHARE_CUSTOMER)).')');
}
if ($ignoreGuest) {
$sql->where('c.`is_guest` = 0');
}
$sql->where('c.`deleted` = 0');
$passwordHash = Db::getInstance()->getValue($sql);
try {
// @var \PrestaShop\PrestaShop\Core\Crypto\Hashing $crypto
$crypto = ServiceLocator::get('\\PrestaShop\\PrestaShop\\Core\\Crypto\\Hashing');
} catch (CoreException $e) {
return false;
}
$shouldCheckPassword = !is_null($plaintextPassword);
if ($shouldCheckPassword && !$crypto->checkHash($plaintextPassword, $passwordHash)) {
return false;
}
$sql = new DbQuery();
$sql->select('c.*');
$sql->from('customer', 'c');
$sql->where('c.`email` = \''.pSQL($email).'\'');
if (Shop::getContext() == Shop::CONTEXT_SHOP && $shopGroup['share_customer']) {
$sql->where('c.`id_shop_group` = '.(int) Shop::getContextShopGroupID());
} else {
$sql->where('c.`id_shop` IN ('.implode(', ', Shop::getContextListShopID(Shop::SHARE_CUSTOMER)).')');
}
if ($ignoreGuest) {
$sql->where('c.`is_guest` = 0');
}
$sql->where('c.`deleted` = 0');
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql);
if (!$result) {
return false;
}
$this->id = $result['id_customer'];
foreach ($result as $key => $value) {
if (property_exists($this, $key)) {
$this->{$key} = $value;
}
}
if ($shouldCheckPassword && !$crypto->isFirstHash($plaintextPassword, $passwordHash)) {
$this->passwd = $crypto->hash($plaintextPassword);
$this->update();
}
return $this;
}else{
//--------------------------------------------------------------------------
//-- complement par CSID
//-- ce n'est pas un email qui a été saisi on presume que c'est un id client
//-- on va lire l'id du client pour recupérer l'id PS correspondant
//-- puis on va traiter comme normal en changeant les select pour les faire
//-- sur l'id customer et non sur l'email
if ($plaintextPassword && !Validate::isPasswd($plaintextPassword)) {
die(Tools::displayError());
}
$shopGroup = Shop::getGroupFromShop(Shop::getContextShopID(), false);
//-- recherche l'id_customer dans ps_customer_cptes à partir de l'identifiant saisi
if ($cust = Db::getInstance()->getRow("select * from "._DB_PREFIX_."customer_cptes a,"._DB_PREFIX_."customer c where a.num_compte='".pSQL($email)."' and c.id_customer=a.id_customer") ){
$id_customer=$cust['id_customer'];
$email=$cust['email'];
}else{
return false;
}
//-- lecture et vérification du password
$sql = new DbQuery();
$sql->select('c.`passwd`');
$sql->from('customer', 'c');
$sql->where('c.`id_customer` = \''.pSQL($id_customer).'\'');
if (Shop::getContext() == Shop::CONTEXT_SHOP && $shopGroup['share_customer']) {
$sql->where('c.`id_shop_group` = '.(int) Shop::getContextShopGroupID());
} else {
$sql->where('c.`id_shop` IN ('.implode(', ', Shop::getContextListShopID(Shop::SHARE_CUSTOMER)).')');
}
if ($ignoreGuest) {
$sql->where('c.`is_guest` = 0');
}
$sql->where('c.`deleted` = 0');
$passwordHash = Db::getInstance()->getValue($sql);
try {
// @var \PrestaShop\PrestaShop\Core\Crypto\Hashing $crypto
$crypto = ServiceLocator::get('\\PrestaShop\\PrestaShop\\Core\\Crypto\\Hashing');
} catch (CoreException $e) {
return false;
}
$shouldCheckPassword = !is_null($plaintextPassword);
if ($shouldCheckPassword && !$crypto->checkHash($plaintextPassword, $passwordHash)) {
return false;
}
//-- lecture du customer
$sql = new DbQuery();
$sql->select('c.*');
$sql->from('customer', 'c');
$sql->where('c.`id_customer` = \''.pSQL($id_customer).'\'');
if (Shop::getContext() == Shop::CONTEXT_SHOP && $shopGroup['share_customer']) {
$sql->where('c.`id_shop_group` = '.(int) Shop::getContextShopGroupID());
} else {
$sql->where('c.`id_shop` IN ('.implode(', ', Shop::getContextListShopID(Shop::SHARE_CUSTOMER)).')');
}
if ($ignoreGuest) {
$sql->where('c.`is_guest` = 0');
}
$sql->where('c.`deleted` = 0');
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql);
if (!$result) {
return false;
}
$this->id = $result['id_customer'];
foreach ($result as $key => $value) {
if (property_exists($this, $key)) {
$this->{$key} = $value;
}
}
if ($shouldCheckPassword && !$crypto->isFirstHash($plaintextPassword, $passwordHash)) {
$this->passwd = $crypto->hash($plaintextPassword);
$this->update();
}
return $this;
}
- puis j'ai besoin que le formulaire ne me bloque pas si on saisi autre chose qu'un email.
=> je modifie la classe /classes/form/CustomerLoginFormatter.php (même remarque que précédemment : ou override pour être propre)
je change le type obligatoire du champ email et j'enleve la contrainte "isEmail"
public function getFormat()
{
return [
'back' => (new FormField)
->setName('back')
->setType('hidden'),
'email' => (new FormField)
->setName('email')
// ->setType('email')
->setType('text')
->setRequired(true)
->setLabel($this->translator->trans(
'Email', [], 'Shop.Forms.Labels'
))
// ->addConstraint('isEmail'),
,
'password' => (new FormField)
->setName('password')
->setType('password')
->setRequired(true)
->setLabel($this->translator->trans(
'Password', [], 'Shop.Forms.Labels'
))
->addConstraint('isPasswd'),
];
}
!!! Attention !!! je reste persuadé que ce genre de manip peut être problématique. En effet dans mon cas il sous entend qu'on peut avoir plusieurs lignes dans ps_customer avec la même adresse email. Or j'ai vu à plusieurs reprises des modules et des fonctions de PS qui utilisent l'adresse email comme identifiant unique. Le risque est donc grand que dans certains cas le compte client lu ne soit pas le bon...
Et il n'est pas bon de modifier les classes directement. Faut-il le rappeler?
A vous de voir si c'est jouable ou pas.
Si ce post vous permet au moins d'avoir des pistes c'est déjà ça !
.png.022b5452a8f28f552bc9430097a16da2.png)