diff --git a/mailpoet/lib/API/JSON/v1/CustomFields.php b/mailpoet/lib/API/JSON/v1/CustomFields.php
index fb036fe561..b06c3ee63c 100644
--- a/mailpoet/lib/API/JSON/v1/CustomFields.php
+++ b/mailpoet/lib/API/JSON/v1/CustomFields.php
@@ -9,6 +9,7 @@ use MailPoet\API\JSON\ResponseBuilders\CustomFieldsResponseBuilder;
use MailPoet\Config\AccessControl;
use MailPoet\CustomFields\CustomFieldsRepository;
use MailPoet\Entities\CustomFieldEntity;
+use MailPoet\Form\ApiDataSanitizer;
class CustomFields extends APIEndpoint {
public $permissions = [
@@ -21,12 +22,17 @@ class CustomFields extends APIEndpoint {
/** @var CustomFieldsResponseBuilder */
private $customFieldsResponseBuilder;
+ /** @var ApiDataSanitizer */
+ private $dataSanitizer;
+
public function __construct(
CustomFieldsRepository $customFieldsRepository,
- CustomFieldsResponseBuilder $customFieldsResponseBuilder
+ CustomFieldsResponseBuilder $customFieldsResponseBuilder,
+ ApiDataSanitizer $dataSanitizer
) {
$this->customFieldsRepository = $customFieldsRepository;
$this->customFieldsResponseBuilder = $customFieldsResponseBuilder;
+ $this->dataSanitizer = $dataSanitizer;
}
public function getAll() {
@@ -51,6 +57,7 @@ class CustomFields extends APIEndpoint {
public function save($data = []) {
try {
+ $data = $this->dataSanitizer->sanitizeBlock($data);
$customField = $this->customFieldsRepository->createOrUpdate($data);
$customField = $this->customFieldsRepository->findOneById($customField->getId());
if(!$customField instanceof CustomFieldEntity) return $this->errorResponse();
diff --git a/mailpoet/lib/Form/ApiDataSanitizer.php b/mailpoet/lib/Form/ApiDataSanitizer.php
index 3b76a4a4ec..d3c1f83943 100644
--- a/mailpoet/lib/Form/ApiDataSanitizer.php
+++ b/mailpoet/lib/Form/ApiDataSanitizer.php
@@ -42,7 +42,7 @@ class ApiDataSanitizer {
return $body;
}
- private function sanitizeBlock(array $block): array {
+ public function sanitizeBlock(array $block): array {
if (!isset($this->htmlSanitizeConfig[$block['type']])) {
return $block;
}
diff --git a/mailpoet/tests/integration/API/JSON/v1/CustomFieldsTest.php b/mailpoet/tests/integration/API/JSON/v1/CustomFieldsTest.php
index ce7ccf5ab7..0a94c59af9 100644
--- a/mailpoet/tests/integration/API/JSON/v1/CustomFieldsTest.php
+++ b/mailpoet/tests/integration/API/JSON/v1/CustomFieldsTest.php
@@ -3,10 +3,8 @@
namespace MailPoet\Test\API\JSON\v1;
use MailPoet\API\JSON\Response as APIResponse;
-use MailPoet\API\JSON\ResponseBuilders\CustomFieldsResponseBuilder;
use MailPoet\API\JSON\v1\CustomFields;
use MailPoet\CustomFields\CustomFieldsRepository;
-use MailPoet\DI\ContainerWrapper;
use MailPoet\Entities\CustomFieldEntity;
class CustomFieldsTest extends \MailPoetTest {
@@ -14,6 +12,9 @@ class CustomFieldsTest extends \MailPoetTest {
/** @var CustomFieldsRepository */
private $repository;
+ /** @var CustomFields */
+ private $endpoint;
+
private $customFields = [
[
'name' => 'CF: text',
@@ -61,15 +62,15 @@ class CustomFieldsTest extends \MailPoetTest {
public function _before() {
parent::_before();
- $this->repository = ContainerWrapper::getInstance(WP_DEBUG)->get(CustomFieldsRepository::class);
+ $this->repository = $this->diContainer->get(CustomFieldsRepository::class);
foreach ($this->customFields as $customField) {
$this->repository->createOrUpdate($customField);
}
+ $this->endpoint = $this->diContainer->get(CustomFields::class);
}
public function testItCanGetAllCustomFields() {
- $router = new CustomFields($this->repository, new CustomFieldsResponseBuilder());
- $response = $router->getAll();
+ $response = $this->endpoint->getAll();
expect($response->status)->equals(APIResponse::STATUS_OK);
expect($response->data)->count(count($this->customFields));
@@ -85,14 +86,13 @@ class CustomFieldsTest extends \MailPoetTest {
$this->assertInstanceOf(CustomFieldEntity::class, $customField);
$customFieldId = $customField->getId();
- $router = new CustomFields($this->repository, new CustomFieldsResponseBuilder());
- $response = $router->delete(['id' => $customFieldId]);
+ $response = $this->endpoint->delete(['id' => $customFieldId]);
expect($response->status)->equals(APIResponse::STATUS_OK);
$customField = $this->repository->findOneBy(['type' => 'date']);
expect($customField)->null();
- $response = $router->delete(['id' => $customFieldId]);
+ $response = $this->endpoint->delete(['id' => $customFieldId]);
expect($response->status)->equals(APIResponse::STATUS_NOT_FOUND);
}
@@ -103,35 +103,54 @@ class CustomFieldsTest extends \MailPoetTest {
'params' => [],
];
- $router = new CustomFields($this->repository, new CustomFieldsResponseBuilder());
- $response = $router->save($newCustomField);
+ $response = $this->endpoint->save($newCustomField);
expect($response->status)->equals(APIResponse::STATUS_OK);
// missing type
- $response = $router->save(['name' => 'New custom field1']);
+ $response = $this->endpoint->save(['name' => 'New custom field1']);
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
// missing name
- $response = $router->save(['type' => 'text']);
+ $response = $this->endpoint->save(['type' => 'text']);
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
// missing data
- $response = $router->save();
+ $response = $this->endpoint->save();
expect($response->status)->equals(APIResponse::STATUS_BAD_REQUEST);
}
+ public function testItSanitizesCheckboxValueButKeepsAllowedHTML() {
+ $newCustomField = [
+ 'name' => 'New custom field',
+ 'type' => 'checkbox',
+ 'params' => [
+ 'values' => [
+ [
+ 'label' => 'label',
+ 'value' => '">
hellolink',
+ ],
+ ],
+ ],
+ ];
+
+ $response = $this->endpoint->save($newCustomField);
+ expect($response->status)->equals(APIResponse::STATUS_OK);
+ expect($response->data['params']['values'][0]['value'])
+ ->equals('"><img src=e onerror=alert(1) hellolink');
+ }
+
public function testItCanGetACustomField() {
$customField = $this->repository->findOneBy(['name' => 'CF: text']);
$this->assertInstanceOf(CustomFieldEntity::class, $customField);
- $router = new CustomFields($this->repository, new CustomFieldsResponseBuilder());
- $response = $router->get(['id' => $customField->getId()]);
+
+ $response = $this->endpoint->get(['id' => $customField->getId()]);
expect($response->data['name'])->equals('CF: text');
expect($response->data['type'])->equals('text');
expect($response->data['params'])->notEmpty();
- $response = $router->get(['id' => 'not_an_id']);
+ $response = $this->endpoint->get(['id' => 'not_an_id']);
expect($response->status)->equals(APIResponse::STATUS_NOT_FOUND);
}
}