Skip to content

Commit

Permalink
[!!!]FEATURE] Release new major version to switch to v2 of Friendlyca…
Browse files Browse the repository at this point in the history
…ptcha
  • Loading branch information
georgringer authored Dec 16, 2024
2 parents 6f4be6f + 32969de commit b616b19
Show file tree
Hide file tree
Showing 23 changed files with 74 additions and 65 deletions.
12 changes: 6 additions & 6 deletions Classes/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@

class Configuration
{
public const DEFAULT_JS_PATH = 'EXT:friendlycaptcha_official/Resources/Public/JavaScript/lib/widget-0.9.12.min.js';
public const DEFAULT_JS_PATH = 'EXT:friendlycaptcha_official/Resources/Public/JavaScript/lib/[email protected].min.js';

protected string $siteKey = '';
protected string $siteSecretKey = '';
protected string $puzzleUrl = '';
protected bool $useEuPuzzleEndpoint = false;
protected string $verifyUrl = '';
protected string $jsPath = '';
protected bool $skipDevValidation = false;
Expand All @@ -31,15 +31,15 @@ public function __construct(Site $site = null)
$siteConfiguration = $site->getConfiguration();
$this->siteKey = trim($siteConfiguration['friendlycaptcha_site_key'] ?? '');
$this->siteSecretKey = trim($siteConfiguration['friendlycaptcha_secret_key'] ?? '');
$this->puzzleUrl = trim($siteConfiguration['friendlycaptcha_puzzle_url'] ?? '');
$this->useEuPuzzleEndpoint = (bool)($siteConfiguration['friendlycaptcha_use_eu_puzzle_endpoint'] ?? false);
$this->verifyUrl = trim($siteConfiguration['friendlycaptcha_verify_url'] ?? '');
$this->jsPath = trim($siteConfiguration['friendlycaptcha_js_path'] ?? '');
$this->skipDevValidation = (bool)($siteConfiguration['friendlycaptcha_skip_dev_validation'] ?? false);
}

public function isEnabled(): bool
{
return $this->siteKey !== '' && $this->siteSecretKey !== '' && $this->puzzleUrl !== '' && $this->verifyUrl !== '' && !$this->hasSkipHeaderValidation();
return $this->siteKey !== '' && $this->siteSecretKey !== '' && $this->verifyUrl !== '' && !$this->hasSkipHeaderValidation();
}

public function getSiteKey(): string
Expand All @@ -52,9 +52,9 @@ public function getSiteSecretKey(): string
return $this->siteSecretKey;
}

public function getPuzzleUrl(): string
public function useEuPuzzleEndpoint(): bool
{
return $this->puzzleUrl;
return $this->useEuPuzzleEndpoint;
}

public function getVerifyUrl(): string
Expand Down
18 changes: 10 additions & 8 deletions Classes/Service/Api.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function __construct(
$this->configuration = new Configuration();
}

public function verify(string $solution = ''): bool
public function verify(string $response = ''): bool
{
if ($this->configuration->hasSkipDevValidation()) {
return true;
Expand All @@ -39,17 +39,19 @@ public function verify(string $solution = ''): bool
return true;
}

$solution = $solution ?: $this->getSolutionFromRequest();
if (!$solution || !$this->configuration->isEnabled()) {
$response = $response ?: $this->getResponseFromRequest();
if (!$response || !$this->configuration->isEnabled()) {
return false;
}

$options = [
'headers' => ['Cache-Control' => 'no-cache'],
'headers' => [
'Cache-Control' => 'no-cache',
'X-API-Key' => $this->configuration->getSiteSecretKey(),
],
'allow_redirects' => true,
'form_params' => [
'secret' => $this->configuration->getSiteSecretKey(),
'solution' => $solution,
'response' => $response,
],
];

Expand Down Expand Up @@ -86,13 +88,13 @@ protected function request(string $method, string $url, array $options = [])
return $result->getBody()->getContents();
}

protected function getSolutionFromRequest(): string
protected function getResponseFromRequest(): string
{
/** @var ServerRequest $request */
$request = $GLOBALS['TYPO3_REQUEST'] ?? null;
if (!$request) {
return '';
}
return $request->getParsedBody()['frc-captcha-solution'] ?? $request->getQueryParams()['frc-captcha-solution'] ?? '';
return $request->getParsedBody()['frc-captcha-response'] ?? $request->getQueryParams()['frc-captcha-response'] ?? '';
}
}
19 changes: 2 additions & 17 deletions Classes/ViewHelpers/ConfigurationViewHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,22 @@
namespace StudioMitte\FriendlyCaptcha\ViewHelpers;

use StudioMitte\FriendlyCaptcha\Configuration;
use TYPO3\CMS\Core\Information\Typo3Version;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;

class ConfigurationViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;

public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
public static function render()
{
$configuration = new Configuration();
return [
'languageIsoCode' => self::getLanguageIsoCode(),
'siteKey' => $configuration->getSiteKey(),
'verifyUrl' => $configuration->getVerifyUrl(),
'puzzleUrl' => $configuration->getPuzzleUrl(),
'useEuPuzzleEndpoint' => $configuration->useEuPuzzleEndpoint(),
'jsPath' => $configuration->getJsPath(),
'enabled' => $configuration->isEnabled(),
];
}

protected static function getLanguageIsoCode(): string
{
$language = $GLOBALS['TYPO3_REQUEST']->getAttribute('language');
if (!$language) {
return '';
}
if ((new Typo3Version())->getMajorVersion() >= 12) {
return $language->getLocale()->getLanguageCode();
}
return $language->getTwoLetterIsoCode();
}
}
2 changes: 1 addition & 1 deletion Configuration/PageTsConfig/powermail.typoscript
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Add FriendlyCaptcha field to Powermail
tx_powermail.flexForm.type.addFieldOptions {
friendlycaptcha = FriendlyCaptcha
friendlycaptcha = FriendlyCaptcha V2
}
14 changes: 6 additions & 8 deletions Configuration/SiteConfiguration/Overrides/sites.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,18 @@ static function () {
'placeholder' => 'A16UE6NICBMVQKG1I1BFMLBD56K53D3CS0L5N00AJNBT1R41P8O7N1KFMH',
],
];
$GLOBALS['SiteConfiguration']['site']['columns']['friendlycaptcha_puzzle_url'] = [
'label' => $lll . 'site.configuration.puzzle_url',
$GLOBALS['SiteConfiguration']['site']['columns']['friendlycaptcha_use_eu_puzzle_endpoint'] = [
'label' => $lll . 'site.configuration.puzzle_endpoint',
'config' => [
'type' => 'input',
'placeholder' => 'https://eu-api.friendlycaptcha.eu/api/v1/puzzle',
'default' => 'https://eu-api.friendlycaptcha.eu/api/v1/puzzle',
'type' => 'check',
],
];
$GLOBALS['SiteConfiguration']['site']['columns']['friendlycaptcha_verify_url'] = [
'label' => $lll . 'site.configuration.verify_url',
'config' => [
'type' => 'input',
'placeholder' => 'https://api.friendlycaptcha.com/api/v1/siteverify',
'default' => 'https://eu-api.friendlycaptcha.eu/api/v1/siteverify',
'placeholder' => 'https://global.frcapi.com/api/v2/captcha/siteverify',
'default' => 'https://global.frcapi.com/api/v2/captcha/siteverify',
],
];
$GLOBALS['SiteConfiguration']['site']['columns']['friendlycaptcha_js_path'] = [
Expand All @@ -48,6 +46,6 @@ static function () {
'type' => 'check',
],
];
$GLOBALS['SiteConfiguration']['site']['types']['0']['showitem'] .= ',--div--;' . $lll . 'site.configuration.tab, friendlycaptcha_site_key,friendlycaptcha_secret_key,friendlycaptcha_puzzle_url,friendlycaptcha_verify_url,friendlycaptcha_js_path,friendlycaptcha_skip_dev_validation,';
$GLOBALS['SiteConfiguration']['site']['types']['0']['showitem'] .= ',--div--;' . $lll . 'site.configuration.tab, friendlycaptcha_site_key,friendlycaptcha_secret_key,friendlycaptcha_use_eu_puzzle_endpoint,friendlycaptcha_verify_url,friendlycaptcha_js_path,friendlycaptcha_skip_dev_validation,';
}
);
2 changes: 1 addition & 1 deletion Configuration/Yaml/FormSetup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ TYPO3:

# Headline (appears as a title in the overview and above the form)
formEditor:
label: 'Friendly Captcha'
label: 'Friendly Captcha V2'
group: custom
groupSorting: 1010

Expand Down
3 changes: 3 additions & 0 deletions Documentation/Configuration/General.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ After creating the account, you need to setup a so called *Application*

Creation of an application

.. note::
This version on the Plugin supports only FriendlyCaptcha V2. The V2 version has to be enabled in your Application

and afterwards you need to create new a new *API Key*. Please copy the generated key as you need it later!

.. figure:: /Images/setup/apikey.png
Expand Down
3 changes: 3 additions & 0 deletions Documentation/Configuration/Integration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ A new tab **Friendly Captcha** is available which includes all configuration opt
This is described in the :ref:`using` section!


By default, the global endpoint `https://global.frcapi.com/api/v2/captcha/siteverify` is used.
If you prefer to use the EU endpoint, enter `https://eu.frcapi.com/api/v2/captcha/siteverify` in `Verify URL` field and ensure that the `Use EU Puzzle Endpoint` option is checked.

Working with automated tests
============================
If you are using automated tests you might want to skip the captcha.
Expand Down
Binary file modified Documentation/Images/configuration_site.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions Documentation/Index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ TYPO3 Extension friendlycaptcha_official
Installation/Index
Configuration/Index
Using/Index
V2_Migration/Index

.. Meta Menu
Expand Down
2 changes: 1 addition & 1 deletion Documentation/Introduction/Index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ What does it do?
================

This extension integrates the service of **Friendly Captcha** into your site by using the
official API.
official API. This version only supports **Friendly Captcha V2**. For **V1** support, please install an earlier version of the plugin.

Currently it supports the following form solutions:

Expand Down
2 changes: 1 addition & 1 deletion Documentation/Using/Custom.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The puzzle needs to be integrated into the form. This can be done like this in y
<f:if condition="{captchaConfiguration.enabled}">
<f:then>
<f:asset.script defer="1" async="1" identifier="friendlycaptcha" src="{captchaConfiguration.jsPath}" />
<div class="frc-captcha" data-sitekey="{captchaConfiguration.siteKey}" data-lang="{captchaConfiguration.languageIsoCode}" data-puzzle-endpoint="{captchaConfiguration.puzzleUrl}"></div>
<div class="frc-captcha" data-sitekey="{captchaConfiguration.siteKey}" {f:if(condition: '{captchaConfiguration.useEuPuzzleEndpoint}', then: 'data-api-endpoint="eu"')}></div>
</f:then>
<f:else>
<p>{f:translate(key:'LLL:EXT:friendlycaptcha_official/Resources/Private/Language/locallang.xlf:configuration_missing')}</p>
Expand Down
16 changes: 16 additions & 0 deletions Documentation/V2_Migration/Index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.. include:: /Includes.rst.txt

.. _v2_migration:

============
Migration to FriendlyCaptcha V2
============

If you’re currently using an earlier version of the plugin with **Friendly Captcha V1** and want to switch to **Friendly Captcha V2**:

* Enable **V2** in yout Application in the Panel at https://friendlycaptcha.com/
* Install the newest version of the plugin (min v1.0)
* In TYPO3 backend, go to the *Site Management*/*Sites* module and switch to the **FriendlyCaptcha** tab. You need to change the URLs
**Puzzle Endpoint** - check it if you want to use the EU Endpoint
**Verify URL** - `https://global.frcapi.com/api/v2/captcha/siteverify` or `https://eu.frcapi.com/api/v2/captcha/siteverify` if you prefer to use EU endpoint
**JavaScript Path** - `EXT:friendlycaptcha_official/Resources/Public/JavaScript/lib/[email protected]`
2 changes: 1 addition & 1 deletion Resources/Private/Form/Partials/Friendlycaptcha.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
value="1"
additionalAttributes="{formvh:translateElementProperty(element: element, property: 'fluidAdditionalAttributes')}"
/>
<div class="frc-captcha" data-sitekey="{captchaConfiguration.siteKey}" data-lang="{captchaConfiguration.languageIsoCode}" data-puzzle-endpoint="{captchaConfiguration.puzzleUrl}"></div>
<div class="frc-captcha" data-sitekey="{captchaConfiguration.siteKey}" {f:if(condition: '{captchaConfiguration.useEuPuzzleEndpoint}', then: 'data-api-endpoint="eu"')}></div>
</f:render>
</f:then>
<f:else>
Expand Down
4 changes: 2 additions & 2 deletions Resources/Private/Language/Configuration.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
<trans-unit id="site.configuration.verify_url">
<source>Verify URL</source>
</trans-unit>
<trans-unit id="site.configuration.puzzle_url">
<source>Puzzle URL</source>
<trans-unit id="site.configuration.puzzle_endpoint">
<source>Use EU Puzzle Endpoint</source>
</trans-unit>
<trans-unit id="site.configuration.js_path">
<source>JavaScript Path</source>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<f:if condition="{captchaConfiguration.enabled}">
<f:then>
<f:asset.script defer="1" async="1" identifier="friendlycaptcha" src="{captchaConfiguration.jsPath}" />
<div class="frc-captcha" data-sitekey="{captchaConfiguration.siteKey}" data-lang="{captchaConfiguration.languageIsoCode}" data-puzzle-endpoint="{captchaConfiguration.puzzleUrl}"></div>
<div class="frc-captcha" data-sitekey="{captchaConfiguration.siteKey}" {f:if(condition: '{captchaConfiguration.useEuPuzzleEndpoint}', then: 'data-api-endpoint="eu"')}></div>
</f:then>
<f:else>
<p>{f:translate(key:'LLL:EXT:friendlycaptcha_official/Resources/Private/Language/locallang.xlf:configuration_missing')}</p>
Expand Down
7 changes: 7 additions & 0 deletions Resources/Public/JavaScript/lib/[email protected]

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion Resources/Public/JavaScript/lib/widget-0.9.12.min.js

This file was deleted.

This file was deleted.

2 changes: 1 addition & 1 deletion Tests/Unit/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function configurationIsBuiltCorrectly(): void
$configuration = new Configuration();
self::assertEquals('12345', $configuration->getSiteKey());
self::assertEquals('ABCDEF', $configuration->getSiteSecretKey());
self::assertEquals('https://puzzle', $configuration->getPuzzleUrl());
self::assertFalse($configuration->useEuPuzzleEndpoint());
self::assertEquals('https://verify,https://verify2', $configuration->getVerifyUrl());
self::assertEquals('https://verify', $configuration->getFirstVerifyUrl());
self::assertTrue($configuration->isEnabled());
Expand Down
12 changes: 6 additions & 6 deletions Tests/Unit/Service/ApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function verifyUrlIsCalledWithProperData(): void
{
self::setupRequest();
$GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']
->withParsedBody(['frc-captcha-solution' => '1234']);
->withParsedBody(['frc-captcha-response' => '1234']);
$historyContainer = [];
$client = $this->createClientWithHistory(
[new Response(200, [], '{"success": true}')],
Expand All @@ -52,15 +52,15 @@ public function solutionIsRetrieved(): void
self::setupRequest();
$mockedApi = $this->getAccessibleMock(Api::class, null, [], '', false);

self::assertSame('', $mockedApi->_call('getSolutionFromRequest'));
self::assertSame('', $mockedApi->_call('getResponseFromRequest'));

$GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']
->withQueryParams(['frc-captcha-solution' => '12345']);
self::assertSame('12345', $mockedApi->_call('getSolutionFromRequest'));
->withQueryParams(['frc-captcha-response' => '12345']);
self::assertSame('12345', $mockedApi->_call('getResponseFromRequest'));

$GLOBALS['TYPO3_REQUEST'] = $GLOBALS['TYPO3_REQUEST']
->withParsedBody(['frc-captcha-solution' => '1234']);
self::assertSame('1234', $mockedApi->_call('getSolutionFromRequest'));
->withParsedBody(['frc-captcha-response' => '1234']);
self::assertSame('1234', $mockedApi->_call('getResponseFromRequest'));
}

private function createClientWithHistory(array $responses, array &$historyContainer): Client
Expand Down
12 changes: 4 additions & 8 deletions Tests/Unit/ViewHelpers/ConfigurationViewHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use StudioMitte\FriendlyCaptcha\Tests\RequestTrait;
use StudioMitte\FriendlyCaptcha\ViewHelpers\ConfigurationViewHelper;
use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
use TYPO3\TestingFramework\Core\BaseTestCase;

class ConfigurationViewHelperTest extends BaseTestCase
Expand All @@ -19,17 +18,14 @@ class ConfigurationViewHelperTest extends BaseTestCase
public function viewHelperReturnsProperConfiguration()
{
self::setupRequest();
$configurationViewHelper = new ConfigurationViewHelper();

$renderingContext = new class () extends RenderingContext {
public function __construct() {}
};
self::assertSame([
'languageIsoCode' => 'en',
'siteKey' => '1234',
'verifyUrl' => 'https://verify,https://verify2',
'puzzleUrl' => 'https://puzzle',
'jsPath' => 'EXT:friendlycaptcha_official/Resources/Public/JavaScript/lib/widget-0.9.12.min.js',
'useEuPuzzleEndpoint' => false,
'jsPath' => 'EXT:friendlycaptcha_official/Resources/Public/JavaScript/lib/[email protected].min.js',
'enabled' => true,
], ConfigurationViewHelper::renderStatic([], static fn() => '', $renderingContext));
], $configurationViewHelper->render());
}
}
2 changes: 1 addition & 1 deletion ext_emconf.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@
],
],
'state' => 'beta',
'version' => '0.1.8',
'version' => '2.0.0',
];

0 comments on commit b616b19

Please sign in to comment.