diff --git a/mailpoet/lib/API/JSON/API.php b/mailpoet/lib/API/JSON/API.php index ae1e21c223..8ec811035f 100644 --- a/mailpoet/lib/API/JSON/API.php +++ b/mailpoet/lib/API/JSON/API.php @@ -28,6 +28,7 @@ class API { private $availableApiVersions = [ 'v1', ]; + /** @var ContainerInterface */ private $container; @@ -71,7 +72,7 @@ class API { } public function init() { - // admin security token and API version + // admin security token and API version WPFunctions::get()->addAction( 'admin_head', [$this, 'setTokenAndAPIVersion'] @@ -106,10 +107,12 @@ class API { } $ignoreToken = ( - $this->settings->get('captcha.type') != CaptchaConstants::TYPE_DISABLED && - $this->requestEndpoint === 'subscribers' && - $this->requestMethod === 'subscribe' - ); + $this->settings->get('captcha.type') != CaptchaConstants::TYPE_DISABLED && + $this->requestEndpoint === 'subscribers' && + $this->requestMethod === 'subscribe' + ) || ( + $this->requestEndpoint === 'captcha' + ); if (!$ignoreToken && $this->wp->wpVerifyNonce($this->requestToken, 'mailpoet_token') === false) { $errorMessage = __("Sorry, but we couldn't connect to the MailPoet server. Please refresh the web page and try again.", 'mailpoet'); diff --git a/mailpoet/lib/API/JSON/Endpoint.php b/mailpoet/lib/API/JSON/Endpoint.php index a19151cb18..4c6460982c 100644 --- a/mailpoet/lib/API/JSON/Endpoint.php +++ b/mailpoet/lib/API/JSON/Endpoint.php @@ -2,6 +2,7 @@ namespace MailPoet\API\JSON; +use MailPoet\API\JSON\v1\RedirectResponse; use MailPoet\Config\AccessControl; abstract class Endpoint { @@ -41,6 +42,10 @@ abstract class Endpoint { return new ErrorResponse($errors, $meta, Response::STATUS_BAD_REQUEST); } + public function redirectResponse($url) { + return new RedirectResponse($url); + } + public function isMethodAllowed($name, $type) { // Block GET requests on POST endpoints, but allow POST requests on GET endpoints (some plugins // change REQUEST_METHOD to POST on GET requests, which caused them to be blocked) diff --git a/mailpoet/lib/API/JSON/Response.php b/mailpoet/lib/API/JSON/Response.php index 2cc913cad6..e37f90ba64 100644 --- a/mailpoet/lib/API/JSON/Response.php +++ b/mailpoet/lib/API/JSON/Response.php @@ -6,6 +6,7 @@ use MailPoet\WP\Functions as WPFunctions; abstract class Response { const STATUS_OK = 200; + const REDIRECT = 302; const STATUS_BAD_REQUEST = 400; const STATUS_UNAUTHORIZED = 401; const STATUS_FORBIDDEN = 403; @@ -15,16 +16,20 @@ abstract class Response { public $status; public $meta; + public $location; - public function __construct( - $status, - $meta = [] - ) { + public function __construct($status, $meta = [], $location = null) { // phpcs:ignore $this->status = $status; $this->meta = $meta; + $this->location = $location; } public function send() { + if ($this->status === self::REDIRECT && $this->location) { + header("Location: " . $this->location, true, $this->status); + exit; + } + WPFunctions::get()->statusHeader($this->status); $data = $this->getData(); diff --git a/mailpoet/lib/API/JSON/v1/Captcha.php b/mailpoet/lib/API/JSON/v1/Captcha.php new file mode 100644 index 0000000000..81450d690c --- /dev/null +++ b/mailpoet/lib/API/JSON/v1/Captcha.php @@ -0,0 +1,33 @@ + AccessControl::NO_ACCESS_RESTRICTION, + ]; + + public function __construct( + CaptchaSession $captchaSession, + CaptchaUrlFactory $urlFactory + ) { + $this->captchaSession = $captchaSession; + $this->urlFactory = $urlFactory; + } + + public function render(array $data = []) { + $sessionId = $this->captchaSession->generateSessionId(); + $data = array_merge($data, ['captcha_session_id' => $sessionId]); + $captchaUrl = $this->urlFactory->getCaptchaUrl($data); + + return $this->redirectResponse($captchaUrl); + } +} diff --git a/mailpoet/lib/API/JSON/v1/RedirectResponse.php b/mailpoet/lib/API/JSON/v1/RedirectResponse.php new file mode 100644 index 0000000000..2a7888754f --- /dev/null +++ b/mailpoet/lib/API/JSON/v1/RedirectResponse.php @@ -0,0 +1,16 @@ +autowire(\MailPoet\API\JSON\v1\SubscriberStats::class)->setPublic(true); $container->autowire(\MailPoet\API\JSON\v1\Subscribers::class)->setPublic(true); $container->autowire(\MailPoet\API\JSON\v1\WoocommerceSettings::class)->setPublic(true); + $container->autowire(\MailPoet\API\JSON\v1\Captcha::class)->setPublic(true); $container->autowire(\MailPoet\Util\APIPermissionHelper::class)->setPublic(true); // API response builders $container->autowire(\MailPoet\API\JSON\ResponseBuilders\NewslettersResponseBuilder::class)->setPublic(true); diff --git a/mailpoet/tests/integration/API/JSON/v1/CaptchaTest.php b/mailpoet/tests/integration/API/JSON/v1/CaptchaTest.php new file mode 100644 index 0000000000..ae7056a261 --- /dev/null +++ b/mailpoet/tests/integration/API/JSON/v1/CaptchaTest.php @@ -0,0 +1,29 @@ +diContainer->get(Populator::class); + $populator->up(); + + parent::_before(); + } + + public function testItCanRenderCaptcha(): void { + $captchaSession = $this->diContainer->get(CaptchaSession::class); + $urlFactory = $this->diContainer->get(CaptchaUrlFactory::class); + + $captcha = new Captcha($captchaSession, $urlFactory); + $response = $captcha->render(); + + verify($response->status)->equals(Response::REDIRECT); + verify($response->location)->stringContainsString('mailpoet_router&endpoint=captcha&action=render&data='); + } +}