Add JSON endpoint for CAPTCHA rendering

To be used inside WP/WC registration form to construct URL for CAPTCHA page.

[MAILPOET-6325]
This commit is contained in:
Mustapha Hadid
2024-11-15 21:50:45 +03:00
committed by David Remer
parent d2ebfba8c3
commit df171fdcc7
7 changed files with 101 additions and 9 deletions

View File

@ -28,6 +28,7 @@ class API {
private $availableApiVersions = [
'v1',
];
/** @var ContainerInterface */
private $container;
@ -109,6 +110,8 @@ class API {
$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) {

View File

@ -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)

View File

@ -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();

View File

@ -0,0 +1,33 @@
<?php declare(strict_types = 1);
namespace MailPoet\API\JSON\v1;
use MailPoet\API\JSON\Endpoint as APIEndpoint;
use MailPoet\Captcha\CaptchaSession;
use MailPoet\Captcha\CaptchaUrlFactory;
use MailPoet\Config\AccessControl;
class Captcha extends APIEndpoint {
private CaptchaSession $captchaSession;
private CaptchaUrlFactory $urlFactory;
public $permissions = [
'global' => 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);
}
}

View File

@ -0,0 +1,16 @@
<?php declare(strict_types = 1);
namespace MailPoet\API\JSON\v1;
use MailPoet\API\JSON\Response;
class RedirectResponse extends Response {
public function __construct($location) { // phpcs:ignore
parent::__construct(self::REDIRECT, [], $location);
}
public function getData() {
return [];
}
}

View File

@ -95,6 +95,7 @@ class ContainerConfigurator implements IContainerConfigurator {
$container->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);

View File

@ -0,0 +1,29 @@
<?php declare(strict_types = 1);
namespace integration\API\JSON\v1;
use MailPoet\API\JSON\Response;
use MailPoet\API\JSON\v1\Captcha;
use MailPoet\Captcha\CaptchaSession;
use MailPoet\Captcha\CaptchaUrlFactory;
use MailPoet\Config\Populator;
class CaptchaTest extends \MailPoetTest {
public function _before() {
$populator = $this->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=');
}
}