diff --git a/VERSIONS_HOTLINE/47906 b/VERSIONS_HOTLINE/47906 new file mode 100644 index 0000000000000000000000000000000000000000..925f166fdb8537d38ed68139c43f318697d16b47 --- /dev/null +++ b/VERSIONS_HOTLINE/47906 @@ -0,0 +1 @@ + - ticket #47906 : Authentification : correction de l'authentification des abonnés SIGB qui ont des id_sigb identiques dans un réseau \ No newline at end of file diff --git a/cosmogramme/php/classes/classe_abonne.php b/cosmogramme/php/classes/classe_abonne.php index bbd292c9ee5bd4f40b1ff96a33945aa5051706c1..19cf19ed34b6ee6f4c8e60cf69199dd67f8e414c 100644 --- a/cosmogramme/php/classes/classe_abonne.php +++ b/cosmogramme/php/classes/classe_abonne.php @@ -1,4 +1,4 @@ -<?PHP +<?php /** * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved. * @@ -101,7 +101,7 @@ class abonne if (isset($enreg['MAIL'])) $enreg['MAIL'] = $this->clean_email($enreg['MAIL']); - $this->saveorUpdateInDB($enreg); + $this->saveOrUpdateInDB($enreg); } @@ -145,8 +145,11 @@ class abonne protected function saveOrUpdateInDB($data){ - if(!$user = $this->findMatchingUserInDB($data)) - $user= new Class_Users(); + $new_user = Class_Users::newInstance($data); + $bib = Class_IntBib::find($this->id_bib); + + if(!$user = Class_Users::findMatchingPatron($new_user,$bib)) + $user = $new_user; $user ->updateAttributes($data) @@ -156,33 +159,17 @@ class abonne } - protected function findMatchingUserInDB($data) { - if (isset($data['ID_SIGB']) - && ($data['ID_SIGB']) - && ($user = Class_Users::findFirstBy(['id_sigb' => $data['ID_SIGB']]))) - return $user; - - $params_existing_user = ['login'=>$data["LOGIN"], - 'id_site'=>$data['ID_SITE']]; - - if (isset($data['ORDREABON'])) - $params_existing_user['ordreabon'] = $data['ORDREABON']; - - return Class_Users::findFirstBy($params_existing_user); - } - - private function changeAccents($chaine) { if(!trim($chaine)) return $chaine; switch($this->type_accents) { - case 2: // Windows - return utf8_encode($chaine); - case 3: // Dos - for($i=0; $i < strlen($chaine); $i++) $new.=$this->dosDecode($chaine[$i]); - return utf8_encode($new); - default: return $chaine; + case 2: // Windows + return utf8_encode($chaine); + case 3: // Dos + for($i=0; $i < strlen($chaine); $i++) $new.=$this->dosDecode($chaine[$i]); + return utf8_encode($new); + default: return $chaine; } } @@ -191,28 +178,27 @@ class abonne { switch($char) { - case 0xe9: $result = 'é'; break ; - case 0xe8: $result = 'è'; break ; - case 0xeb: $result = 'ë'; break ; - case 0xe4: $result = 'ä'; break ; - case 0xe2: $result = 'â'; break ; - case 0xef: $result = 'ï'; break ; - case 0xcf: $result = 'Ã'; break ; - case 0xee: $result = 'î'; break ; - case 0xce: $result = 'ÃŽ'; break ; - case 0xf4: $result = 'ô'; break ; - case 0xf6: $result = 'ö'; break ; - case 0xd6: $result = 'Ö'; break ; - case 0xfc: $result = 'ü'; break ; - case 0xdc: $result = 'Ãœ'; break ; - case 0xfb: $result = 'û'; break ; - case 0xe7: $result = 'ç'; break ; - case 0xc7: $result = 'Ç'; break ; - default: $result = $char; break; + case 0xe9: $result = 'é'; break ; + case 0xe8: $result = 'è'; break ; + case 0xeb: $result = 'ë'; break ; + case 0xe4: $result = 'ä'; break ; + case 0xe2: $result = 'â'; break ; + case 0xef: $result = 'ï'; break ; + case 0xcf: $result = 'Ã'; break ; + case 0xee: $result = 'î'; break ; + case 0xce: $result = 'ÃŽ'; break ; + case 0xf4: $result = 'ô'; break ; + case 0xf6: $result = 'ö'; break ; + case 0xd6: $result = 'Ö'; break ; + case 0xfc: $result = 'ü'; break ; + case 0xdc: $result = 'Ãœ'; break ; + case 0xfb: $result = 'û'; break ; + case 0xe7: $result = 'ç'; break ; + case 0xc7: $result = 'Ç'; break ; + default: $result = $char; break; } return $result; } - } ?> \ No newline at end of file diff --git a/cosmogramme/tests/php/classes/AbonneIntegrationTest.php b/cosmogramme/tests/php/classes/AbonneIntegrationTest.php index 4e75bbe0df6483827ed5a92a3adf5c103b4fec6f..56d375400ac89a1019d402406e999add8b160eea 100644 --- a/cosmogramme/tests/php/classes/AbonneIntegrationTest.php +++ b/cosmogramme/tests/php/classes/AbonneIntegrationTest.php @@ -25,11 +25,16 @@ require_once 'ModelTestCase.php'; abstract class AbonneIntegrationTestCase extends ModelTestCase { - protected $abon_config; + protected $abon_config, + $_storm_default_to_volatile = true; public function setup(){ parent::setup(); - Storm_Model_Loader::defaultToVolatile(); + + $this->fixture('Class_IntBib', + ['id' => 2, + 'id_bib' => 2]); + $this->abon_config = new abonne(); $this->abon_config->setIdBib(2); } @@ -221,6 +226,8 @@ class AbonneIntegrationASCIIWithRoutoInDbTest extends AbonneIntegrationTestCase ['id' => 5, 'nom'=>'Routo', 'prenom'=>'Pierre', + 'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB, + 'idabon' => '123456', 'login'=>'5 5', 'id_site' => 2, 'pseudo' => 'riri', @@ -445,7 +452,7 @@ class AbonneIntegrationXMLWithRoutoInDbTest extends AbonneIntegrationXMLTestCase $this->abon_config->importFicheXml($champs_sigb_xml); $this->zozio_after_import = Class_Users::findFirstby(['login'=>'0100 3080', - 'id_site' => 2]); + 'id_site' => 2]); } /** @test **/ diff --git a/library/Class/Users.php b/library/Class/Users.php index 23a0f7a453e95feed9a3e7edd499dfb53271983e..8a17e0f4ff06d13207616c0c07b183b54402ac99 100644 --- a/library/Class/Users.php +++ b/library/Class/Users.php @@ -43,6 +43,34 @@ class UsersLoader extends Storm_Model_Loader { } + public function findMatchingPatron($patron, $bib) { + if (!$patron || !$bib) + return null; + + if (($ordreabon = $patron->getOrdreabon()) + && ($user = Class_Users::findFirstBy(['login' => $patron->getLogin(), + 'ordreabon' => $ordreabon, + 'id_site' => $bib->getIdBib()]))) + return $user; + + if ($user = Class_Users::findFirstBy(['login' => $patron->getLogin(), + 'id_sigb' => $patron->getIdSigb(), + 'id_site' => $bib->getIdBib()])) + return $user; + + if ($user = Class_Users::findFirstBy(['login' => $patron->getLogin(), + 'id_site' => $bib->getIdBib()])) + return $user; + + if (($id_sigb = $patron->getIdSigb()) + && ($user = Class_Users::findFirstBy(['id_site' => $bib->getIdBib(), + 'id_sigb' => $patron->getIdSigb()]))) + return $user; + + return null; + } + + public function findAllLike($search, $by_right = null, $limit = 500) { $sql_template = 'select bib_admin_users.* from bib_admin_users '; diff --git a/library/ZendAfi/Auth/Adapter/CommSigb.php b/library/ZendAfi/Auth/Adapter/CommSigb.php index 490508be9d0dc7dfe5338fbebb2880bf20f88533..3e478cbb1dce8c5118d01d1315162e08199c9870 100644 --- a/library/ZendAfi/Auth/Adapter/CommSigb.php +++ b/library/ZendAfi/Auth/Adapter/CommSigb.php @@ -16,13 +16,14 @@ * * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE * along with BOKEH; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ class ZendAfi_Auth_Adapter_CommSigb implements Zend_Auth_Adapter_Interface { protected $_identity = null; protected $_credential = null; protected $_authenticated_user = null; + protected $_bib = null; /** @@ -49,39 +50,36 @@ class ZendAfi_Auth_Adapter_CommSigb implements Zend_Auth_Adapter_Interface { * @return Zend_Auth_Result */ public function authenticate() { - return + return $this->authResult( - $this->matchingProcessSIGBUserInDB( - $this->getUserFromSigb(Class_Users::newInstance(['login' => $this->_identity, - 'password' => $this->_credential])))); + $this->matchingProcessSIGBUserInDB( + $this->getUserFromSigb(Class_Users::newInstance(['login' => $this->_identity, + 'password' => $this->_credential])))); } - + public function matchingProcessSIGBUserInDB($user_from_sigb) { if(!$user_from_sigb) return null; - $users_in_db = []; + return $this->_getUserToSave($user_from_sigb) + ->beAbonneSIGB() + ->setLogin($this->_identity) + ->setPassword($this->_credential) + ->updateUser($user_from_sigb); + } + - if ($user_from_sigb->getIdSigb()) - $users_in_db = Class_Users::findAllBy(['id_sigb' => $user_from_sigb->getIdSigb()]); - if (count($users_in_db) != 1) { - $users_in_db = Class_Users::findAllBy(['login' => $user_from_sigb->getLogin()]); - if(1 < count($users_in_db)) - $users_in_db = Class_Users::findAllBy(['login' => $user_from_sigb->getLogin(), - 'id_sigb' => $user_from_sigb->getIdSigb()]); - } + protected function _getUserToSave($user_from_sigb) { + $new_user = Class_Users::newInstance()->setLogin($this->_identity); - if (1 == count($users_in_db)) - $user_to_save = $users_in_db[0]; - else - $user_to_save = Class_Users::newInstance()->setLogin($this->_identity); - - return $user_to_save - ->beAbonneSIGB() - ->setLogin($this->_identity) - ->setPassword($this->_credential) - ->updateUser($user_from_sigb); + if (!$this->_bib) + return $new_user; + + if ($user = Class_Users::findMatchingPatron($user_from_sigb, $this->_bib)) + return $user; + + return $new_user; } @@ -89,6 +87,7 @@ class ZendAfi_Auth_Adapter_CommSigb implements Zend_Auth_Adapter_Interface { $bibs = $this->getBibsToAuthenticateTo($user); foreach($bibs as $bib) { + $this->_bib = $bib; if (!$emprunteur = $bib->getSIGBComm()->getEmprunteur($user)) continue; @@ -101,6 +100,7 @@ class ZendAfi_Auth_Adapter_CommSigb implements Zend_Auth_Adapter_Interface { $emprunteur->updateUser($user); return $user->setIdSite($bib->getId()); } + $this->_bib = null; return null; } @@ -115,16 +115,16 @@ class ZendAfi_Auth_Adapter_CommSigb implements Zend_Auth_Adapter_Interface { if (!$user_in_db->isAbonne() || (!$bib = $user_in_db->getIntBib()) || (!$bib->getSIGBComm())) return []; - return [$bib]; + return [$bib]; } public function authResult($user) { $result = new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $this->_identity); - + if(!$user) return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND, $this->_identity); - + if(!$user->save()) $result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND, $this->_identity); diff --git a/tests/application/modules/opac/controllers/AuthControllerTest.php b/tests/application/modules/opac/controllers/AuthControllerTest.php index b6d91596f32ef7c646d0060c22e05de498379537..eb6590d40ae4e16d09ad508796a2ff90e1451106 100644 --- a/tests/application/modules/opac/controllers/AuthControllerTest.php +++ b/tests/application/modules/opac/controllers/AuthControllerTest.php @@ -2418,4 +2418,83 @@ class AuthControllerKohaPreRegistrationSuccessDispatchTest extends AuthControlle public function dateofBirthShouldBeDisbled() { $this->assertXPath('//form//input[@name="dateofbirth"][@type="text"][@disabled="disabled"][@value="15/09/1940"]'); } +} + + + +class AuthControllerPostWithSameIdSigbTest extends AbstractControllerTestCase { + protected $_storm_default_to_volatile = true; + + public function setUp() { + parent::setUp(); + + ZendAfi_Auth::getInstance()->clearIdentity(); + + $emprunteur = Class_WebService_SIGB_Emprunteur::newInstance(789, 'koha'); + $emprunteur->setPassword('bar'); + $emprunteur->beValid(); + + $service = $this->mock() + ->whenCalled('getEmprunteur') + ->answers($emprunteur) + + ->whenCalled('isConnected') + ->answers(true); + + $params = ['url_serveur' => 'http://mon-koha-de-test.org', + 'id_bib' => 56, + 'type' => Class_IntBib::COM_KOHA]; + + Class_WebService_SIGB_Koha::setService($params, + $service); + + $this->fixture('Class_Bib', + ['id' => 56, + 'libelle' => 'Library']); + + $this->fixture('Class_IntBib', + ['id' => 56, + 'id_bib' => 56, + 'comm_sigb' => 5, + 'comm_params' => serialize($params)]); + + $this->fixture('Class_Bib', + ['id' => 13, + 'libelle' => 'First library']); + + $this->fixture('Class_Users', + ['id' => 123456, + 'login' => 'different', + 'password' => 'yes', + 'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB, + 'idabon' => 'different', + 'id_site' => 13, + 'id_sigb' => 789]); + + $this->fixture('Class_Users', + ['id' => 5, + 'login' => 'foo', + 'password' => 'bar', + 'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB, + 'idabon' => 'foo', + 'id_site' => 56, + 'id_sigb' => null]); + + $this->postDispatch('/opac/auth/login', + ['username' => 'foo', + 'password' => 'bar']); + } + + + /** @test */ + public function userDifferentShouldNotBeUpdated() { + $this->assertEquals('different', Class_Users::find(123456)->getLogin()); + } + + + /** @test */ + public function userFooShouldBeLogged() { + $this->assertNotNull(Class_Users::getIdentity()); + $this->assertEquals('foo', Class_Users::getIdentity()->getLogin()); + } } \ No newline at end of file diff --git a/tests/library/ZendAfi/Auth/Adapter/AuthCommSigbTest.php b/tests/library/ZendAfi/Auth/Adapter/AuthCommSigbTest.php index c129489b944f0883fb8dc414bca5cf5e11643ff2..baa6540765bb3050dc5a72c29a8690c988588b86 100644 --- a/tests/library/ZendAfi/Auth/Adapter/AuthCommSigbTest.php +++ b/tests/library/ZendAfi/Auth/Adapter/AuthCommSigbTest.php @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE * along with BOKEH; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ abstract class AuthCommSigbTestCase extends Storm_Test_ModelTestCase { @@ -25,7 +25,7 @@ abstract class AuthCommSigbTestCase extends Storm_Test_ModelTestCase { Class_Users::beVolatile(); Class_IntBib::beVolatile(); - + $this->_zork = $this->fixture('Class_Users', ['id' => 4, 'date_fin' => '2010-10-23', @@ -34,7 +34,7 @@ abstract class AuthCommSigbTestCase extends Storm_Test_ModelTestCase { 'idabon' => '98475', 'id_site' => 2, 'password' => 'xzy']); - + Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Users'); Storm_Test_ObjectWrapper::onLoaderOfModel('Class_IntBib'); } @@ -95,7 +95,7 @@ abstract class AuthCommSigbWithWebServicesAndAbonneZorkTestCase extends AuthComm ->setEndDate('2015-12-25') ->setPassword('secret') ->beValid()); - $this->_zork->setIdSite(74); + $this->_zork->setIdSite(74)->save(); return $this; } @@ -112,8 +112,8 @@ class AuthCommSigbSuccessfullAuthenticationTest extends AuthCommSigbWithWebServi ->whenCalled('save') ->willDo( function($user) { - $user->setId(23); - return true; + $user->setId(23); + return true; }); $this->_adapter = (new ZendAfi_Auth_Adapter_CommSigb()) @@ -122,7 +122,7 @@ class AuthCommSigbSuccessfullAuthenticationTest extends AuthCommSigbWithWebServi $this->_authenticate_result = $this->_adapter->authenticate(); } - + /** @test */ public function authenticateZorkShouldReturnValidResult() { @@ -142,7 +142,7 @@ class AuthCommSigbSuccessfullAuthenticationTest extends AuthCommSigbWithWebServi $this->assertTrue($user->isAbonne()); } - + /** @test */ public function resultObjectShouldBeSetUp() { $result = $this->_adapter->getResultObject(); @@ -169,14 +169,14 @@ class AuthCommSigbSuccessfullAuthenticationWithExistingUserTest extends AuthComm $this->_authenticate_result = $this->_adapter->authenticate(); } - + /** @test */ public function authenticateZorkShouldReturnValidResult() { $this->assertTrue($this->_authenticate_result->isValid()); } - + /** @test */ public function zorkShouldHaveBeenSaved() { $this->assertEquals($this->_zork, Class_Users::getFirstAttributeForLastCallOn('save')); @@ -192,13 +192,13 @@ class AuthCommSigbSuccessfullAuthenticationWithExistingUserTest extends AuthComm /** @test */ public function zorkDateFinShouldBeUpdatedTo2015_12_25() { - $this->assertEquals('2015-12-25', $this->_zork->getDateFin()); + $this->assertEquals('2015-12-25', $this->_zork->getDateFin()); } /** @test */ public function zorkPasswordShouldBeSecret() { - $this->assertEquals('secret', $this->_zork->getPassword()); + $this->assertEquals('secret', $this->_zork->getPassword()); } } @@ -213,7 +213,7 @@ class AuthCommSigbSuccessfullAuthenticationWithExistingUserButWrongPasswordTest ::whenCalled('findAllBy') ->with(['login' => 'zork_sigb']) ->answers([$this->_zork]); - + $this->_adapter = (new ZendAfi_Auth_Adapter_CommSigb()) ->setIdentity('zork_sigb') ->setCredential('oups'); @@ -234,7 +234,7 @@ class AuthCommSigbSuccessfullAuthenticationWithExistingUserButWrongPasswordTest class AuthCommSigbErrorsTest extends AuthCommSigbWithWebServicesAndAbonneZorkTestCase { public function setUp() { parent::setUp(); - + $this->_adapter = (new ZendAfi_Auth_Adapter_CommSigb()) ->setIdentity('zork_sigb') ->setCredential('blabla'); @@ -265,7 +265,7 @@ class AuthCommSigbErrorsTest extends AuthCommSigbWithWebServicesAndAbonneZorkTes class AuthCommSigbSuccessfullAuthenticationWithExistingFamilleUserTest extends AuthCommSigbWithWebServicesAndAbonneZorkTestCase { protected $_zowife, $_zork_boy, $_zork_girl; - + public function setUp() { parent::setUp(); @@ -274,19 +274,20 @@ class AuthCommSigbSuccessfullAuthenticationWithExistingFamilleUserTest extends A $this->_zowife = $this->fixture('Class_Users', ['id' => 45, - 'password' => 'zowife', + 'password' => 'zowife', 'login' => 'zork_sigb']); $this->_zork_boy = $this->fixture('Class_Users', ['id' => 65, - 'password' => 'zorkboy', + 'password' => 'zorkboy', 'login' => 'zork_sigb']); - + $this->_zork_girl = $this->fixture('Class_Users', ['id' => 85, - 'password' => 'zorkgirl', + 'password' => 'zorkgirl', 'login' => 'zork_sigb', - 'id_sigb' => '001234']); + 'id_sigb' => '001234', + 'id_site' => 74]); $this->opsys ->whenCalled('getEmprunteur') @@ -297,15 +298,15 @@ class AuthCommSigbSuccessfullAuthenticationWithExistingFamilleUserTest extends A ->setPassword('zorkgirl') ->beValid()); - + $this->_adapter = (new ZendAfi_Auth_Adapter_CommSigb()) ->setIdentity('zork_sigb') ->setCredential('zorkgirl'); $this->_authenticate_result = $this->_adapter->authenticate(); } - - + + /** @test **/ public function zorkGirlShouldHaveBeenSave() { $this->assertTrue(Class_Users::methodHasBeenCalledWithParams('save', [$this->_zork_girl])); @@ -336,15 +337,15 @@ class AuthCommSigbSuccessfullAuthenticationWithNewLoginTest extends AuthCommSigb ->setPassword('xzyz') ->beValid()); - + $this->_adapter = (new ZendAfi_Auth_Adapter_CommSigb()) ->setIdentity('new_login') ->setCredential('xzyz'); $this->_authenticate_result = $this->_adapter->authenticate(); } - - + + /** @test */ public function authenticateZorkShouldBeValid() { $this->assertTrue($this->_authenticate_result->isValid()); @@ -382,15 +383,15 @@ class AuthCommSigbErrorAuthenticationWithNewLoginTest extends AuthCommSigbWithWe ->setCodeBarres('1234') ->beValid()); - + $this->_adapter = (new ZendAfi_Auth_Adapter_CommSigb()) ->setIdentity('new_login') ->setCredential('xzyz'); $this->_authenticate_result = $this->_adapter->authenticate(); } - - + + /** @test */ public function authenticateZorkShouldBeValid() { $this->assertTrue($this->_authenticate_result->isValid()); @@ -431,14 +432,15 @@ class AuthCommSigbAuthenticationSetupInvalidUserTest extends AuthCommSigbWithWeb /** @test */ public function authenticateZorkShouldNotBeValid() { $this->assertFalse($this->_authenticate_result->isValid()); - } + } /** @test */ - public function noUserShouldHaveBeenSaved() { - $this->assertFalse(Class_Users::methodHasBeenCalled('save')); + public function noUserShouldHaveBeenAdded() { + $this->assertCount(1, Class_Users::findAll()); } + /** @test */ public function zorkPasswordShouldRemainXZY() { $this->assertEquals('xzy', $this->_zork->getPassword());