diff --git a/source/Application/Component/UserComponent.php b/source/Application/Component/UserComponent.php index 8e80e3d848..2ea5c46298 100644 --- a/source/Application/Component/UserComponent.php +++ b/source/Application/Component/UserComponent.php @@ -23,6 +23,9 @@ use OxidEsales\Eshop\Core\Form\FormFieldsTrimmer; use OxidEsales\Eshop\Core\Form\UpdatableFieldsConstructor; use OxidEsales\Eshop\Core\Registry; +use OxidEsales\EshopCommunity\Core\Di\ContainerFacade; +use OxidEsales\EshopCommunity\Internal\Domain\Authentication\Bridge\PasswordServiceBridgeInterface; + use function array_key_exists; use function is_array; @@ -512,6 +515,7 @@ public function createUser() if (!$isPrivateSales) { Registry::getSession()->setVariable('usr', $user->getId()); + $this->setSessionLoginToken((string)$user->getFieldData('oxpassword')); $this->afterLogin($user); // order remark @@ -909,4 +913,13 @@ private function removeNonAddressFields(array $addressFormData): array return $addressFormData; } + + private function setSessionLoginToken(string $passwordHash): void + { + Registry::getSession() + ->setVariable( + 'login-token', + ContainerFacade::get(PasswordServiceBridgeInterface::class)->hash($passwordHash) + ); + } } diff --git a/source/Application/Controller/Admin/LanguageMain.php b/source/Application/Controller/Admin/LanguageMain.php index 90111f3819..a3ca67683f 100644 --- a/source/Application/Controller/Admin/LanguageMain.php +++ b/source/Application/Controller/Admin/LanguageMain.php @@ -380,15 +380,9 @@ protected function addNewMultilangFieldsToDb() //creating new multilingual fields with new id over whole DB $oDbMeta = oxNew(\OxidEsales\Eshop\Core\DbMetaDataHandler::class); - $db = \OxidEsales\Eshop\Core\DatabaseProvider::getDb(); - $db->startTransaction(); try { $oDbMeta->addNewLangToDb(); - $db->commitTransaction(); } catch (Exception $oEx) { - if (!$oEx instanceof \PDOException) { - $db->rollbackTransaction(); - } //show warning $oEx = oxNew(\OxidEsales\Eshop\Core\Exception\ExceptionToDisplay::class); $oEx->setMessage('LANGUAGE_ERROR_ADDING_MULTILANG_FIELDS'); diff --git a/source/Application/Controller/ForgotPasswordController.php b/source/Application/Controller/ForgotPasswordController.php index c3c647afe3..32d6454ed5 100644 --- a/source/Application/Controller/ForgotPasswordController.php +++ b/source/Application/Controller/ForgotPasswordController.php @@ -165,8 +165,6 @@ public function isExpiredLink() } /** - * Template variable getter. Returns searched article list - * * @return string */ public function getForgotEmail() diff --git a/source/Application/Model/User.php b/source/Application/Model/User.php index 57ecb11c6d..40ddd0d564 100644 --- a/source/Application/Model/User.php +++ b/source/Application/Model/User.php @@ -1406,10 +1406,10 @@ protected function _getLoginQuery($userName, $password, $shopId, $isAdmin) // ph */ public function login($userName, $password, $setSessionCookie = false) { - $isLoginAttemptToAdminBackend = $this->isAdmin(); + $isAdmin = $this->isAdmin(); $cookie = Registry::getUtilsServer()->getOxCookie(); - if ($cookie === null && $isLoginAttemptToAdminBackend) { + if ($cookie === null && $isAdmin) { throw oxNew(CookieException::class, 'ERROR_MESSAGE_COOKIE_NOCOOKIE'); } @@ -1417,13 +1417,10 @@ public function login($userName, $password, $setSessionCookie = false) $shopId = $config->getShopId(); /** New authentication mechanism */ - $passwordHashFromDatabase = $this->getPasswordHashFromDatabase($userName, $shopId, $isLoginAttemptToAdminBackend); + $passwordHash = $this->getPasswordHashFromDatabase($userName, $shopId, $isAdmin); $passwordServiceBridge = ContainerFacade::get(PasswordServiceBridgeInterface::class); - if ($password && !$this->isLoaded()) { - $userIsAuthenticated = $passwordServiceBridge->verifyPassword($password, $passwordHashFromDatabase); - if ($userIsAuthenticated) { - $this->loadAuthenticatedUser($userName, $shopId); - } + if ($password && !$this->isLoaded() && $this->verifyHash($password, $passwordHash)) { + $this->loadAuthenticatedUser($userName, $shopId); } /** Old authentication + authorization */ @@ -1434,10 +1431,10 @@ public function login($userName, $password, $setSessionCookie = false) /** If needed, store a rehashed password with the authenticated user */ if ($password && $this->isLoaded()) { $passwordNeedsRehash = $this->isOutdatedPasswordHashAlgorithmUsed || - $passwordServiceBridge->passwordNeedsRehash($passwordHashFromDatabase); + $passwordServiceBridge->passwordNeedsRehash($passwordHash); if ($passwordNeedsRehash) { - $generatedPasswordHash = $this->hashPassword($password); - $this->oxuser__oxpassword = new Field($generatedPasswordHash, Field::T_RAW); + $passwordHash = $this->getHash($password); + $this->oxuser__oxpassword = new Field($passwordHash, Field::T_RAW); /** The use of a salt is deprecated and an empty salt will be stored */ $this->oxuser__oxpasssalt = new Field(''); $this->save(); @@ -1457,11 +1454,9 @@ public function login($userName, $password, $setSessionCookie = false) //resetting active user $this->setUser(null); - if ($isLoginAttemptToAdminBackend) { - Registry::getSession()->setVariable('auth', $this->oxuser__oxid->value); - } else { - Registry::getSession()->setVariable('usr', $this->oxuser__oxid->value); - } + $userIdParameter = $isAdmin ? 'auth' : 'usr'; + Registry::getSession()->setVariable($userIdParameter, $this->getFieldData('oxid')); + Registry::getSession()->setVariable('login-token', $this->getHash($passwordHash)); // cookie must be set ? if ($setSessionCookie && $config->getConfigParam('blShowRememberMe')) { @@ -1524,17 +1519,14 @@ private function getAuthenticatedUserId(string $userName, int $shopId, bool $isL */ public function logout() { - // deleting session info Registry::getSession()->deleteVariable('usr'); // for front end Registry::getSession()->deleteVariable('auth'); // for back end Registry::getSession()->deleteVariable('dynvalue'); Registry::getSession()->deleteVariable('paymentid'); - // Registry::getSession()->deleteVariable( 'deladrid' ); + Registry::getSession()->deleteVariable('login-token'); - // delete cookie - Registry::getUtilsServer()->deleteUserCookie(\OxidEsales\Eshop\Core\Registry::getConfig()->getShopID()); + Registry::getUtilsServer()->deleteUserCookie(Registry::getConfig()->getShopID()); - // unsetting global user $this->setUser(null); return true; @@ -1552,54 +1544,37 @@ public function loadAdminUser() } /** - * Loads active user object. If - * user is not available - returns false. - * - * @param bool $blForceAdmin (default false) + * @param bool $blForceAdmin * * @return bool */ public function loadActiveUser($blForceAdmin = false) { - $oConfig = \OxidEsales\Eshop\Core\Registry::getConfig(); - - $blAdmin = $this->isAdmin() || $blForceAdmin; - - // first - checking session info - $sUserID = $blAdmin ? Registry::getSession()->getVariable('auth') : Registry::getSession()->getVariable('usr'); + $isAdmin = $this->isAdmin() || $blForceAdmin; + $userIdParameter = $isAdmin ? 'auth' : 'usr'; + $userId = Registry::getSession()->getVariable($userIdParameter); // trying automatic login (by 'remember me' cookie) - $blFoundInCookie = false; - if (!$sUserID && !$blAdmin && $oConfig->getConfigParam('blShowRememberMe')) { - $sUserID = $this->getCookieUserId(); - $blFoundInCookie = $sUserID ? true : false; - } - - // checking user results - if ($sUserID) { - if ($this->load($sUserID)) { - // storing into session - if ($blAdmin) { - Registry::getSession()->setVariable('auth', $sUserID); - } else { - Registry::getSession()->setVariable('usr', $sUserID); - } - - // marking the way user was loaded - $this->_blLoadedFromCookie = $blFoundInCookie; - - return true; - } - } else { - // no user - if ($blAdmin) { - Registry::getSession()->deleteVariable('auth'); - } else { - Registry::getSession()->deleteVariable('usr'); - } - + $isUserIdInCookie = false; + if (!$userId && !$isAdmin && Registry::getConfig()->getConfigParam('blShowRememberMe')) { + $userId = $this->getCookieUserId(); + $isUserIdInCookie = (bool)$userId; + } + if (!$userId) { + Registry::getSession()->deleteVariable($userIdParameter); return false; } + if ($this->load($userId)) { + $loginToken = (string)Registry::getSession()->getVariable('login-token'); + $passwordHash = (string)$this->getFieldData('oxpassword'); + if ($loginToken && !$this->verifyHash($passwordHash, $loginToken)) { + $this->logout(); + return false; + } + Registry::getSession()->setVariable($userIdParameter, $userId); + $this->_blLoadedFromCookie = $isUserIdInCookie; + return true; + } } /** @@ -1613,7 +1588,6 @@ protected function getCookieUserId() $oConfig = \OxidEsales\Eshop\Core\Registry::getConfig(); $sShopID = $oConfig->getShopId(); if (($sSet = Registry::getUtilsServer()->getUserCookie($sShopID))) { - $passwordServiceBridge = ContainerFacade::get(PasswordServiceBridgeInterface::class); $oDb = \OxidEsales\Eshop\Core\DatabaseProvider::getDb(); $aData = explode('@@@', $sSet); $sUser = $aData[0]; @@ -1623,7 +1597,7 @@ protected function getCookieUserId() $rs = $oDb->select($sSelect); if ($rs != false && $rs->count() > 0) { while (!$rs->EOF) { - if ($passwordServiceBridge->verifyPassword($rs->fields[1] . static::USER_COOKIE_SALT, $sPWD)) { + if ($this->verifyHash($rs->fields[1] . static::USER_COOKIE_SALT, $sPWD)) { // found $sUserID = $rs->fields[0]; break; @@ -2000,33 +1974,21 @@ public function encodePassword($sPassword, $sSalt) return $oHasher->hash($sPassword, $sSalt); } + /** - * Sets new password for user ( save is not called) + * Sets new password for user (save is not called) * - * @param string $password password + * @param string $password */ public function setPassword($password = null) { - if (empty($password)) { - $passwordHash = ''; - } else { - $passwordHash = $this->hashPassword($password); - } - - $this->oxuser__oxpassword = new \OxidEsales\Eshop\Core\Field($passwordHash, \OxidEsales\Eshop\Core\Field::T_RAW); - $this->oxuser__oxpasssalt = new \OxidEsales\Eshop\Core\Field(''); + $this->oxuser__oxpassword = new Field( + empty($password) ? '' : $this->getHash($password), + Field::T_RAW + ); + $this->oxuser__oxpasssalt = new Field(''); } - /** - * @param string $password - * - * @return string - */ - private function hashPassword(string $password): string - { - return ContainerFacade::get(PasswordServiceBridgeInterface::class) - ->hash($password); - } /** * Checks if user entered password is the same as old @@ -2721,4 +2683,16 @@ private function getRandomToken(): string return ContainerFacade::get(RandomTokenGeneratorBridgeInterface::class) ->getAlphanumericToken(32); } + + private function getHash(string $password): string + { + return ContainerFacade::get(PasswordServiceBridgeInterface::class) + ->hash($password); + } + + private function verifyHash(string $password, string $hash): string + { + return ContainerFacade::get(PasswordServiceBridgeInterface::class) + ->verifyPassword($password, $hash); + } } diff --git a/tests/Codeception/Acceptance/Admin/NewLanguageCreationCest.php b/tests/Codeception/Acceptance/Admin/NewLanguageCreationCest.php index 1bf72b5f4c..46ea8cb019 100644 --- a/tests/Codeception/Acceptance/Admin/NewLanguageCreationCest.php +++ b/tests/Codeception/Acceptance/Admin/NewLanguageCreationCest.php @@ -10,22 +10,60 @@ namespace OxidEsales\EshopCommunity\Tests\Codeception\Acceptance\Admin; use Codeception\Attribute\Group; +use OxidEsales\Codeception\Admin\Languages; +use OxidEsales\Codeception\Module\Translation\Translator; use OxidEsales\EshopCommunity\Tests\Codeception\Support\AcceptanceTester; #[Group('admin')] final class NewLanguageCreationCest { - public function newLanguageCreation(AcceptanceTester $I): void + public function newLanguagesCreation(AcceptanceTester $I): void { - $I->wantToTest('if we can create a new language successfully'); + $I->wantToTest('if we can create four new languages successfully.'); $adminPanel = $I->loginAdmin(); $languages = $adminPanel->openLanguages(); - $languages->createNewLanguage('lt', 'Lietuviu'); + $I->amGoingTo('create the first language.'); + $this->createNewLanguage($languages, $I, 'lt', 'Lietuviu'); + + $I->amGoingTo('create the second language.'); + $this->createNewLanguage($languages, $I, 'hu', 'Hungarian'); + + $I->amGoingTo('create the third language.'); + $this->createNewLanguage($languages, $I, 'mt', 'Maltese'); + + $I->amGoingTo('create the fourth language.'); + $this->createNewLanguage($languages, $I, 'es', 'Spanish'); + + $I->amGoingTo('generate DB views.'); $tools = $adminPanel->openTools(); $tools->updateDbViews(); + $I->amGoingTo('check the new languages fields.'); + $this->checkLanguageFields($I); + } + + private function createNewLanguage(Languages $languages, AcceptanceTester $I, string $code, string $name): void + { + $languages->createNewLanguage($code, $name); + $I->amGoingTo('check extra messages.'); + $this->checkMessages($I); + } + + private function checkMessages(AcceptanceTester $I): void + { + $I->selectEditFrame(); + $I->expect('not to see the multilingual fields error message. Four language fields are predefined, + so on the addition of a fifth language, new fields should be added as well.'); + $I->dontSee(Translator::translate('LANGUAGE_ERROR_ADDING_MULTILANG_FIELDS')); + } + + private function checkLanguageFields(AcceptanceTester $I): void + { $I->retryGrabFromDatabase('oxv_oxarticles_lt', 'oxid', ['oxartnum' => '3503']); + $I->retryGrabFromDatabase('oxv_oxarticles_hu', 'oxid', ['oxartnum' => '3503']); + $I->retryGrabFromDatabase('oxv_oxarticles_mt', 'oxid', ['oxartnum' => '3503']); + $I->retryGrabFromDatabase('oxv_oxarticles_es', 'oxid', ['oxartnum' => '3503']); } } diff --git a/tests/Codeception/Acceptance/Admin/SessionHandlingCest.php b/tests/Codeception/Acceptance/Admin/SessionHandlingCest.php new file mode 100644 index 0000000000..bfb6491ac6 --- /dev/null +++ b/tests/Codeception/Acceptance/Admin/SessionHandlingCest.php @@ -0,0 +1,40 @@ +<?php + +/** + * Copyright © OXID eSales AG. All rights reserved. + * See LICENSE file for license details. + */ + +declare(strict_types=1); + +namespace OxidEsales\EshopCommunity\Tests\Codeception\Acceptance\Admin; + +use Codeception\Attribute\Group; +use Codeception\Util\Fixtures; +use OxidEsales\EshopCommunity\Tests\Codeception\Support\AcceptanceTester; + +final class SessionHandlingCest +{ + #[Group('session')] + public function adminSessionAfterPasswordChange(AcceptanceTester $I): void + { + $I->wantToTest('that admin will be logged out if someone changes his password from another active session'); + $userData = Fixtures::get('adminUser'); + $adminLoginPage = $I->openAdmin(); + $I->amGoingTo('log the existing admin in'); + $adminLoginPage->login($userData['userLoginName'], $userData['userPassword']); + + $I->amGoingTo('mock password change for this admin from another browser session'); + $I->updateInDatabase( + 'oxuser', + ['OXPASSWORD' => 'some-new-password-hash'], + ['OXUSERNAME' => $userData['userLoginName']] + ); + + $I->amGoingTo('send any page request after password change'); + $I->reloadPage(); + + $I->expect('that admin is logged out'); + $adminLoginPage->seeLoginForm(); + } +} diff --git a/tests/Codeception/Acceptance/Admin/UserCest.php b/tests/Codeception/Acceptance/Admin/UserCest.php index ae84990c1c..8e99babc8a 100644 --- a/tests/Codeception/Acceptance/Admin/UserCest.php +++ b/tests/Codeception/Acceptance/Admin/UserCest.php @@ -10,6 +10,7 @@ namespace OxidEsales\EshopCommunity\Tests\Codeception\Acceptance\Admin; use Codeception\Attribute\Group; +use Codeception\Util\Fixtures; use OxidEsales\Codeception\Admin\DataObject\AdminUser; use OxidEsales\Codeception\Admin\DataObject\AdminUserAddresses; use OxidEsales\Codeception\Admin\DataObject\AdminUserExtendedInfo; @@ -174,6 +175,28 @@ public function testCreateUserExtendedInfo(AcceptanceTester $I): void ->seeUserExtendedInformation($userOriginalExtendedInfo); } + #[Group('session')] + public function updatePassword(AcceptanceTester $I): void + { + $I->wantToTest('that admin can update his own password'); + $newPass = uniqid('new-pass-', true); + $userData = Fixtures::get('adminUser'); + $adminLoginPage = $I->openAdmin(); + $I->amGoingTo('log the existing admin in, find him in the list and update his password'); + $adminLoginPage + ->login($userData['userLoginName'], $userData['userPassword']) + ->openUsers() + ->findByUserName($userData['userId']) + ->updatePassword($newPass); + + $I->amGoingTo('send any page request after password change'); + $I->reloadPage(); + + $I->expect('that admin is logged out but can log in with the new pass'); + $adminLoginPage->seeLoginForm() + ->login($userData['userLoginName'], $newPass); + } + private function createAdminTestUser( AcceptanceTester $I, AdminUser $user, diff --git a/tests/Codeception/Acceptance/SessionHandlingCest.php b/tests/Codeception/Acceptance/SessionHandlingCest.php index bcf929e84b..6815338694 100644 --- a/tests/Codeception/Acceptance/SessionHandlingCest.php +++ b/tests/Codeception/Acceptance/SessionHandlingCest.php @@ -9,16 +9,18 @@ namespace OxidEsales\EshopCommunity\Tests\Codeception\Acceptance; +use Codeception\Attribute\Group; use Codeception\Util\Fixtures; use OxidEsales\Codeception\Module\Context; use OxidEsales\Codeception\Page\Account\UserAccount; +use OxidEsales\Codeception\Step\Basket; use OxidEsales\EshopCommunity\Tests\Codeception\Support\AcceptanceTester; +use function random_int; + +#[Group('session')] final class SessionHandlingCest { - /** - * @group session - */ public function checkForceSidWithDefaultConfig(AcceptanceTester $I): void { $I->wantToTest('that force_sid allows to access the current users session'); @@ -39,9 +41,6 @@ public function checkForceSidWithDefaultConfig(AcceptanceTester $I): void $I->openShop()->openAccountPage()->seeUserAccount($userData); } - /** - * @group session - */ public function checkForceSidWithDisabledForceSid(AcceptanceTester $I): void { $I->wantToTest('that force_sid is not working after configuration update'); @@ -65,11 +64,97 @@ public function checkForceSidWithDisabledForceSid(AcceptanceTester $I): void $I->openShop()->openUserAccountPage()->seePageOpened(); } - private function createUserSession(AcceptanceTester $I, string $userName, string $password): UserAccount + public function userSessionAfterPasswordChange(AcceptanceTester $I): void + { + $I->wantToTest('that user will be logged out if someone changes his password from another active session'); + $userData = Fixtures::get('existingUser'); + $I->amGoingTo('log the existing user in'); + $home = $I + ->openShop() + ->loginUser($userData['userLoginName'], $userData['userPassword']) + ->seeUserLoggedIn(); + + $I->amGoingTo('add some product to the shopping cart'); + (new Basket($I))->addProductToBasket('1001', 3); + $home->seeItemCountBadge('3'); + + $I->amGoingTo('mock password change for this user from admin/another browser session'); + $I->updateInDatabase( + 'oxuser', + ['OXPASSWORD' => 'some-new-password-hash'], + ['OXUSERNAME' => $userData['userLoginName']] + ); + + $I->amGoingTo('send any page request after password change'); + $home->openAccountPage(); + $I->expect('that user was logged out'); + $home->seeUserLoggedOut(); + + $I->expect('that the basket is retained, despite the user being logged out'); + $home->seeItemCountBadge('3'); + } + + public function registerStandardUserInFrontend(AcceptanceTester $I): void { + $I->wantToTest('simple user account opening'); + $username = 'some-user-email@oxid-esales.dev'; + $userRegistration = $I + ->openShop() + ->openUserRegistrationPage(); + $homePage = $I->openShop(); - $accountMenu = $homePage->loginUser($userName, $password); - return $accountMenu->openAccountPage(); + $homePage->openUserRegistrationPage(); + + $userRegistration + ->enterUserLoginData([ + 'userLoginNameField' => $username, + 'userPasswordField' => 'user1user1', + ]) + ->enterUserData([ + 'userUstIDField' => '', + 'userMobFonField' => '111-111111-1', + 'userPrivateFonField' => '111111111', + 'userBirthDateDayField' => random_int(1, 28), + 'userBirthDateMonthField' => random_int(1, 12), + 'userBirthDateYearField' => random_int(1960, 2000), + ]) + ->enterAddressData([ + 'userSalutation' => 'Mrs', + 'userFirstName' => 'John', + 'userLastName' => 'Doe', + 'companyName' => 'Unemployed', + 'street' => 'Main Str.', + 'streetNr' => 123, + 'ZIP' => '12341', + 'city' => 'Big City', + 'additionalInfo' => 'Something additional', + 'fonNr' => '111-111-1', + 'faxNr' => '111-111-111-1', + 'countryId' => 'Germany', + 'stateId' => 'Berlin', + ]) + ->registerUser(); + + $I->openShop() + ->seeUserLoggedIn(); + + $I->amGoingTo('mock password change for this user from admin/another browser session'); + $I->updateInDatabase( + 'oxuser', + ['OXPASSWORD' => 'some-new-password-hash'], + ['OXUSERNAME' => $username] + ); + + $I->openShop() + ->seeUserLoggedOut(); + } + + private function createUserSession(AcceptanceTester $I, string $userName, string $password): UserAccount + { + return $I + ->openShop() + ->loginUser($userName, $password) + ->openAccountPage(); } private function forgetUserSession(AcceptanceTester $I): void diff --git a/tests/Codeception/Acceptance/UserAccountCest.php b/tests/Codeception/Acceptance/UserAccountCest.php index e95226e13a..c40db2fbbf 100644 --- a/tests/Codeception/Acceptance/UserAccountCest.php +++ b/tests/Codeception/Acceptance/UserAccountCest.php @@ -48,10 +48,12 @@ public function changeUserAccountPassword(AcceptanceTester $I): void $userData = $this->getExistingUserData(); $userName = $userData['userLoginName']; - $userPassword = $userData['userPassword']; + $oldPass = $userData['userPassword']; + $newPass = 'someNewPassword123'; + $invalidPass = 'pass'; $startPage = $I->openShop() - ->loginUser($userName, $userPassword); + ->loginUser($userName, $oldPass); $I->dontSee(Translator::translate('LOGIN')); $accountPage = $startPage->openAccountPage()->seePageOpened()->seeUserAccount($userData); @@ -59,29 +61,34 @@ public function changeUserAccountPassword(AcceptanceTester $I): void $changePasswordPage = $accountPage->openChangePasswordPage(); //entered not matching new passwords - $changePasswordPage->fillPasswordFields($userPassword, 'user1user', 'useruser'); + $changePasswordPage->fillPasswordFields($oldPass, $newPass, $oldPass); $I->see(Translator::translate('ERROR_MESSAGE_PASSWORD_DO_NOT_MATCH')); //new pass is too short - $changePasswordPage->changePassword($userPassword, 'user', 'user'); + $changePasswordPage->changePassword($oldPass, $invalidPass, $invalidPass); $I->see(Translator::translate('ERROR_MESSAGE_PASSWORD_TOO_SHORT')); //correct new pass - $changePasswordPage->changePassword($userPassword, 'user1user', 'user1user'); + $changePasswordPage->changePassword($oldPass, $newPass, $newPass); $I->see(Translator::translate('MESSAGE_PASSWORD_CHANGED')); - $loginPage = $changePasswordPage->openAccountPage()->logoutUserInAccountPage(); + $I->reloadPage(); + $startPage->seeUserLoggedOut(); // try to login with old password - $loginPage = $loginPage->loginWithError($userName, $userPassword); + $I->openShop() + ->loginUser($userName, $oldPass); $I->see(Translator::translate('ERROR_MESSAGE_USER_NOVALIDLOGIN')); // try to login with new password - $changePasswordPage = $loginPage->login($userName, 'user1user')->openChangePasswordPage(); + $changePasswordPage = $I->openShop() + ->loginUser($userName, $newPass) + ->openUserAccountPage() + ->openChangePasswordPage(); $I->dontSee(Translator::translate('LOGIN')); //reset new pass to old one - $changePasswordPage->changePassword('user1user', $userPassword, $userPassword); + $changePasswordPage->changePassword($newPass, $oldPass, $oldPass); $I->see(Translator::translate('MESSAGE_PASSWORD_CHANGED')); } @@ -177,8 +184,6 @@ public function subscribeNewsletterInUserAccount(AcceptanceTester $I): void /** * @group myAccount - * - * @after cleanUpUserData */ public function changeUserBillingAddress(AcceptanceTester $I): void { @@ -284,20 +289,6 @@ public function createAndDeleteUserShippingAddress(AcceptanceTester $I): void ->seeNumberOfShippingAddresses(0); } - public function _after(AcceptanceTester $I): void - { - $this->cleanUpUserData($I); - } - - private function cleanUpUserData(AcceptanceTester $I): void - { - /** Change Germany and Belgium data to original. */ - $I->updateInDatabase('oxcountry', ['oxvatstatus' => 1], ['OXID' => 'a7c40f632e04633c9.47194042']); - $I->updateInDatabase('oxcountry', ['oxvatstatus' => 1], ['OXID' => 'a7c40f631fc920687.20179984']); - $userData = $this->getExistingUserData(); - $I->deleteFromDatabase('oxaddress', ['OXUSERID' => $userData['userId']]); - } - private function getExistingUserData() { return Fixtures::get('existingUser'); diff --git a/tests/Integration/Application/Model/UserTest.php b/tests/Integration/Application/Model/UserTest.php new file mode 100644 index 0000000000..145d8d3a7e --- /dev/null +++ b/tests/Integration/Application/Model/UserTest.php @@ -0,0 +1,50 @@ +<?php + +/** + * Copyright © OXID eSales AG. All rights reserved. + * See LICENSE file for license details. + */ + +declare(strict_types=1); + +namespace OxidEsales\EshopCommunity\Tests\Integration\Application\Model; + +use OxidEsales\Eshop\Application\Model\User; +use OxidEsales\EshopCommunity\Internal\Domain\Authentication\Bridge\PasswordServiceBridgeInterface; +use OxidEsales\EshopCommunity\Tests\ContainerTrait; +use PHPUnit\Framework\TestCase; +use Prophecy\PhpUnit\ProphecyTrait; + +final class UserTest extends TestCase +{ + use ProphecyTrait; + use ContainerTrait; + + public function testSetPassword(): void + { + $password = 'some-pass'; + $user = oxNew(User::class); + + $user->setPassword($password); + + $this->assertTrue( + $this->get(PasswordServiceBridgeInterface::class) + ->verifyPassword( + $password, + $user->getFieldData('oxpassword') + ) + ); + $this->assertEmpty($user->getFieldData('oxpasssalt')); + + } + + public function testSetPasswordWithEmptyPass(): void + { + $user = oxNew(User::class); + + $user->setPassword(''); + + $this->assertEmpty($user->getFieldData('oxpassword')); + $this->assertEmpty($user->getFieldData('oxpasssalt')); + } +}