diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php index d43b313c43b3e..5dabd48782b73 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Gallery/Upload.php @@ -108,8 +108,10 @@ public function execute() $result['url'] = $this->productMediaConfig->getTmpMediaUrl($result['file']); $result['file'] = $result['file'] . '.tmp'; - } catch (\Exception $e) { + } catch (LocalizedException $e) { $result = ['error' => $e->getMessage(), 'errorcode' => $e->getCode()]; + } catch (\Throwable $e) { + $result = ['error' => 'Something went wrong while saving the file(s).', 'errorcode' => 0]; } /** @var \Magento\Framework\Controller\Result\Raw $response */ diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontRemoveFirstProductFromCompareActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontRemoveFirstProductFromCompareActionGroup.xml new file mode 100644 index 0000000000000..fefcdb6930c61 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/StorefrontRemoveFirstProductFromCompareActionGroup.xml @@ -0,0 +1,24 @@ + + + + + + + Open Compare Products list and remove a product + + + + + + + + + + + diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductCompareMainSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductCompareMainSection.xml index ad31be6b277ee..d120042fbe9a2 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductCompareMainSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/StorefrontProductCompareMainSection.xml @@ -14,5 +14,6 @@ + diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml index d2de38c31dbb5..fad0b26262d0a 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AddOutOfStockProductToCompareListTest.xml @@ -78,8 +78,7 @@ - - + @@ -92,11 +91,13 @@ - + - + + + @@ -108,11 +109,11 @@ - - + + - + diff --git a/app/code/Magento/Customer/Model/Validator/Name.php b/app/code/Magento/Customer/Model/Validator/Name.php new file mode 100644 index 0000000000000..9bab241465d6c --- /dev/null +++ b/app/code/Magento/Customer/Model/Validator/Name.php @@ -0,0 +1,59 @@ +isValidName($customer->getFirstname())) { + parent::_addMessages([['firstname' => 'First Name is not valid!']]); + } + + if (!$this->isValidName($customer->getLastname())) { + parent::_addMessages([['lastname' => 'Last Name is not valid!']]); + } + + if (!$this->isValidName($customer->getMiddlename())) { + parent::_addMessages([['middlename' => 'Middle Name is not valid!']]); + } + + return count($this->_messages) == 0; + } + + /** + * Check if name field is valid. + * + * @param string|null $nameValue + * @return bool + */ + private function isValidName($nameValue) + { + if ($nameValue != null) { + if (preg_match(self::PATTERN_NAME, $nameValue, $matches)) { + return $matches[0] == $nameValue; + } + } + + return true; + } +} diff --git a/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml index 14d569ed9101d..ef9c90847adec 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/AdminExactMatchSearchInCustomerGridTest.xml @@ -21,7 +21,7 @@ - "Jane Doe" + Jane Doe diff --git a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml index 11aed4a3461e1..712ad61a9663e 100644 --- a/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml +++ b/app/code/Magento/Customer/Test/Mftf/Test/StorefrontVerifyNoXssInjectionOnUpdateCustomerInformationAddAddressTest.xml @@ -11,12 +11,15 @@ - + <title value="DEPRECATED [Security] Verify No XSS Injection on Update Customer Information Add Address"/> <description value="Test log in to Storefront and Verify No XSS Injection on Update Customer Information Add Address"/> <testCaseId value="MC-10910"/> <severity value="CRITICAL"/> <group value="customer"/> <group value="mtf_migrated"/> + <skip> + <issueId value="DEPRECATED">Test outdated</issueId> + </skip> </annotations> <before> diff --git a/app/code/Magento/Customer/etc/validation.xml b/app/code/Magento/Customer/etc/validation.xml index 85d657dff266a..bac6e54afa7b5 100644 --- a/app/code/Magento/Customer/etc/validation.xml +++ b/app/code/Magento/Customer/etc/validation.xml @@ -18,11 +18,17 @@ <constraint alias="metadata_data_validator" class="Magento\Customer\Model\Metadata\Validator" /> </entity_constraints> </rule> + <rule name="check_name"> + <entity_constraints> + <constraint alias="name_validator" class="Magento\Customer\Model\Validator\Name" /> + </entity_constraints> + </rule> </rules> <groups> <group name="save"> <uses> <use rule="check_eav"/> + <use rule="check_name"/> </uses> </group> <group name="form"> diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php index f7732b5fd68dd..95f7da88b0619 100644 --- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/CustomerRepositoryTest.php @@ -1058,4 +1058,204 @@ protected function _createCustomer(?array $additionalData = []) $this->currentCustomerId[] = $customerData['id']; return $customerData; } + + /** + * Test customer create with invalid name's. + * + * @param string $fieldName + * @param string $fieldValue + * @param string $expectedMessage + * @return void + * + * @dataProvider customerDataProvider + */ + public function testCreateCustomerWithInvalidCustomerFirstName(string $fieldName, string $fieldValue, string $expectedMessage): void + { + $customerData = $this->dataObjectProcessor->buildOutputDataArray( + $this->customerHelper->createSampleCustomerDataObject(), + Customer::class + ); + $customerData[$fieldName] = $fieldValue; + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + + $requestData = ['customer' => $customerData]; + + try { + $this->_webApiCall($serviceInfo, $requestData); + $this->fail('Expected exception was not raised'); + } catch (\SoapFault $e) { + $this->assertStringContainsString($expectedMessage, $e->getMessage()); + } catch (\Exception $e) { + $errorObj = $this->processRestExceptionResult($e); + $this->assertEquals(HTTPExceptionCodes::HTTP_BAD_REQUEST, $e->getCode()); + $this->assertEquals($expectedMessage, $errorObj['message']); + } + } + + /** + * Invalid customer data provider + * + * @return array + */ + public function customerDataProvider(): array + { + return [ + ['firstname', 'Jane ☺ ', 'First Name is not valid!'], + ['lastname', '☏ - Doe', 'Last Name is not valid!'], + ['middlename', '⚐ $(date)', 'Middle Name is not valid!'], + [ + 'firstname', + str_repeat('खाना अच्छा है', 20), + 'First Name is not valid!', + ], + [ + 'lastname', + str_repeat('المغلوطة حول استنكار النشوة وتمجيد الألمالمغلوطة حول', 5), + 'Last Name is not valid!', + ], + ]; + } + + /** + * Test customer create with ultibyte chanracters in name's. + * + * @param string $fieldName + * @param string $fieldValue + * @return void + * + * @dataProvider customerWithMultiByteDataProvider + */ + public function testCreateCustomerWithMultibyteCharacters(string $fieldName, string $fieldValue): void + { + $customerData = $this->dataObjectProcessor->buildOutputDataArray( + $this->customerHelper->createSampleCustomerDataObject(), + Customer::class + ); + $customerData[$fieldName] = $fieldValue; + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + + $requestData = ['customer' => $customerData]; + + $response = $this->_webApiCall($serviceInfo, $requestData); + + $this->assertNotNull($response); + $this->assertEquals($fieldValue, $response[$fieldName]); + } + + /** + * Customer with multibyte characters data provider. + * + * @return array + */ + public function customerWithMultiByteDataProvider(): array + { + return [ + [ + 'firstname', + str_repeat('हैखान', 51), + ], + [ + 'lastname', + str_repeat('مغلوطة حول استنكار النشوة وتمجيد الألمالمغلوطة حول', 5), + ], + ]; + } + + /** + * Test customer create with valid name's. + * + * @param string $fieldName + * @param string $fieldValue + * @return void + * + * @dataProvider customerValidNameDataProvider + */ + public function testCreateCustomerWithValidName(string $fieldName, string $fieldValue): void + { + $customerData = $this->dataObjectProcessor->buildOutputDataArray( + $this->customerHelper->createSampleCustomerDataObject(), + Customer::class + ); + $customerData[$fieldName] = $fieldValue; + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + + $requestData = ['customer' => $customerData]; + + $response = $this->_webApiCall($serviceInfo, $requestData); + + $this->assertNotNull($response); + $this->assertEquals($fieldValue, $response[$fieldName]); + } + + /** + * Customer valid name data provider. + * + * @return array + */ + public function customerValidNameDataProvider(): array + { + return [ + [ + 'firstname', + 'Anne-Marie', + ], + [ + 'lastname', + 'D\'Artagnan', + ], + [ + 'lastname', + 'Guðmundsdóttir', + ], + [ + 'lastname', + 'María José Carreño Quiñones', + ], + [ + 'lastname', + 'Q. Public', + ], + [ + 'firstname', + 'Elizabeth II', + ], + [ + 'firstname', + 'X Æ A-12 Musk', + ], + ]; + } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Gallery/UploadTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Gallery/UploadTest.php index 283a3834eab59..b2494ba2ecb8a 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Gallery/UploadTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/Gallery/UploadTest.php @@ -198,7 +198,7 @@ public function uploadActionWithErrorsDataProvider(): array 'current_path' => '/../../../../_files', ], 'expectation' => [ - 'message' => 'Wrong file size.', + 'message' => 'Something went wrong while saving the file(s).', 'errorcode' => 0, 'tmp_media_path' => '/m/a/magento_empty.jpg', ], @@ -206,10 +206,23 @@ public function uploadActionWithErrorsDataProvider(): array 'upload_without_image' => [ 'file' => [], 'expectation' => [ - 'message' => '$_FILES array is empty', + 'message' => 'Something went wrong while saving the file(s).', 'errorcode' => 0, ], ], + 'upload_wrong_png' => [ + 'file' => [ + 'copy_file' => true, + 'name' => 'magento_wrong.png', + 'type' => 'image/png', + 'current_path' => '/../../../../_files', + ], + 'expectation' => [ + 'message' => 'Something went wrong while saving the file(s).', + 'errorcode' => 0, + 'tmp_media_path' => '/m/w/magento_wrong.png', + ], + ] ]; } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/magento_wrong.png b/dev/tests/integration/testsuite/Magento/Catalog/_files/magento_wrong.png new file mode 100644 index 0000000000000..7bca3ec1f1dea Binary files /dev/null and b/dev/tests/integration/testsuite/Magento/Catalog/_files/magento_wrong.png differ