Add FriendlyCaptcha vendor dir
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Ossycodes\FriendlyCaptcha\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
class FriendlyCaptcha extends Facade
|
||||
{
|
||||
/**
|
||||
* Get the registered name of the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return 'FriendlyCaptcha';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
namespace Ossycodes\FriendlyCaptcha;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class FriendlyCaptcha
|
||||
{
|
||||
/**
|
||||
* FriendlyCaptcha secret
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $secret;
|
||||
|
||||
/**
|
||||
* FriendlyCaptcha sitekey
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sitekey;
|
||||
|
||||
/**
|
||||
* FriendlyCaptcha Puzzle endpoint
|
||||
*/
|
||||
protected $puzzle;
|
||||
|
||||
/**
|
||||
* FriendlyCaptcha verify endpoint
|
||||
*/
|
||||
protected $verify;
|
||||
|
||||
/**
|
||||
* error messages
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $error = [];
|
||||
|
||||
public $isSuccess = false;
|
||||
|
||||
/**
|
||||
* @var \GuzzleHttp\Client
|
||||
*/
|
||||
protected $http;
|
||||
|
||||
public function __construct($secret, $sitekey, $puzzle, $verify, $options = [])
|
||||
{
|
||||
$this->secret = $secret;
|
||||
$this->sitekey = $sitekey;
|
||||
$this->puzzle = $puzzle;
|
||||
$this->verify = $verify;
|
||||
$this->http = new Client($options);
|
||||
}
|
||||
|
||||
public function renderWidgetScripts($option = 'unpkg')
|
||||
{
|
||||
if ($option == 'unpkg') {
|
||||
return <<<EOF
|
||||
<script type="module" src="https://unpkg.com/friendly-challenge@0.9.9/widget.module.min.js" async defer></script>
|
||||
<script nomodule src="https://unpkg.com/friendly-challenge@0.9.9/widget.min.js" async defer></script>
|
||||
EOF;
|
||||
}
|
||||
|
||||
return <<<EOF
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.9/widget.module.min.js" async defer></script>
|
||||
<script nomodule src="https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.9/widget.min.js" async defer></script>
|
||||
EOF;
|
||||
}
|
||||
|
||||
public function renderWidget($attributes = [])
|
||||
{
|
||||
$attributes = $this->prepareAttributes($attributes);
|
||||
return '<div' . $this->buildAttributes($attributes) . '></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare HTML attributes and ensure that the correct classes and attributes for captcha are inserted.
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareAttributes(array $attributes)
|
||||
{
|
||||
$attributes['data-puzzle-endpoint'] = $this->puzzle;
|
||||
|
||||
$attributes['data-sitekey'] = $this->sitekey;
|
||||
|
||||
if (isset($attributes['dark-theme'])) {
|
||||
$attributes['class'] = 'frc-captcha dark';
|
||||
unset($attributes['dark-theme']);
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
$attributes['class'] = trim('frc-captcha');
|
||||
|
||||
$locale = app()->getLocale();
|
||||
|
||||
if (in_array($locale, ["en", "fr", "de", "it", "nl", "pt", "es", "ca", "da", "ja", "ru", "sv", "el", "uk", "bg", "cs", "sk", "no", "fi", "lt", "lt", "pl", "et", "hr", "sr", "sl", "hu", "ro", "zh", "zh_TW", "vi"])) {
|
||||
//use supported locale - https://docs.friendlycaptcha.com/#/widget_api?id=data-lang-attribute
|
||||
$attributes['data-lang'] = $locale;
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build HTML attributes.
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildAttributes(array $attributes)
|
||||
{
|
||||
$html = [];
|
||||
|
||||
foreach ($attributes as $key => $value) {
|
||||
$html[] = $key . '="' . $value . '"';
|
||||
}
|
||||
|
||||
return count($html) ? ' ' . implode(' ', $html) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify FriendlyCaptcha response.
|
||||
*
|
||||
* @param string $solution
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function verifyRequest($solution)
|
||||
{
|
||||
return $this->verifyResponse(
|
||||
$solution,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify FriendlyCaptcha response.
|
||||
*
|
||||
* @param string $solution
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function verifyResponse($solution)
|
||||
{
|
||||
if (empty($solution)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$verifyResponse = $this->sendRequestVerify([
|
||||
'solution' => $solution,
|
||||
'secret' => $this->secret,
|
||||
'sitekey' => $this->sitekey,
|
||||
]);
|
||||
|
||||
if (isset($verifyResponse['success']) && $verifyResponse['success'] === true) {
|
||||
$this->isSuccess = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (isset($verifyResponse['errors'])) {
|
||||
$this->errors = $verifyResponse['errors'];
|
||||
}
|
||||
|
||||
if (isset($verifyResponse['error'])) {
|
||||
$this->errors = [$verifyResponse['error']];
|
||||
}
|
||||
|
||||
$this->isSuccess = false;
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Send verify request.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function sendRequestVerify(array $data = [])
|
||||
{
|
||||
$response = $this->http->request('POST', $this->verify, [
|
||||
'form_params' => $data,
|
||||
]);
|
||||
|
||||
return json_decode($response->getBody(), true);
|
||||
}
|
||||
|
||||
public function isSuccess()
|
||||
{
|
||||
return $this->isSuccess;
|
||||
}
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace Ossycodes\FriendlyCaptcha;
|
||||
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Ossycodes\FriendlyCaptcha\FriendlyCaptcha;
|
||||
|
||||
class FriendlyCaptchaServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = false;
|
||||
|
||||
/**
|
||||
* Bootstrap the application services.
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->bootConfig();
|
||||
}
|
||||
|
||||
$this->bootBladeDirectives();
|
||||
|
||||
$this->bootMacro();
|
||||
|
||||
$this->bootLang();
|
||||
}
|
||||
|
||||
/**
|
||||
* Boot config.
|
||||
*/
|
||||
protected function bootConfig()
|
||||
{
|
||||
$path = __DIR__ . '/config/friendlycaptcha.php';
|
||||
|
||||
if (function_exists('config_path')) {
|
||||
$this->publishes([$path => config_path('friendlycaptcha.php')]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Boot blade directives
|
||||
*/
|
||||
public function bootBladeDirectives()
|
||||
{
|
||||
Blade::directive('friendlyCaptchaRenderWidgetScripts', function ($option) {
|
||||
$option = trim($option, "'");
|
||||
|
||||
if (empty($option) || $option == 'unpkg') {
|
||||
return <<<EOF
|
||||
<script type="module" src="https://unpkg.com/friendly-challenge@0.9.8/widget.module.min.js" async defer></script>
|
||||
<script nomodule src="https://unpkg.com/friendly-challenge@0.9.8/widget.min.js" async defer></script>
|
||||
EOF;
|
||||
}
|
||||
|
||||
return <<<EOF
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.8/widget.module.min.js" async defer></script>
|
||||
<script nomodule src="https://cdn.jsdelivr.net/npm/friendly-challenge@0.9.8/widget.min.js" async defer></script>
|
||||
EOF;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* boot macro
|
||||
*/
|
||||
public function bootMacro()
|
||||
{
|
||||
Rule::macro('friendlycaptcha', function () {
|
||||
return app(\Ossycodes\FriendlyCaptcha\Rules\FriendlyCaptcha::class);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* boot lang
|
||||
*/
|
||||
public function bootLang()
|
||||
{
|
||||
Rule::macro('friendlycaptcha', function () {
|
||||
$this->loadTranslationsFrom(__DIR__.'/../lang', 'friendlycaptcha');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the application services.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$path = __DIR__ . '/config/friendlycaptcha.php';
|
||||
|
||||
$this->mergeConfigFrom($path, 'friendlycaptcha');
|
||||
|
||||
$this->app->singleton('FriendlyCaptcha', function ($app) {
|
||||
return new FriendlyCaptcha(
|
||||
$app['config']['friendlycaptcha.secret'],
|
||||
$app['config']['friendlycaptcha.sitekey'],
|
||||
$app['config']['friendlycaptcha.puzzle_endpoint'],
|
||||
$app['config']['friendlycaptcha.verify_endpoint'],
|
||||
$app['config']['friendlycaptcha.options']
|
||||
);
|
||||
});
|
||||
|
||||
$this->app->alias('FriendlyCaptcha', FriendlyCaptcha::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return ['FriendlyCaptcha'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Ossycodes\FriendlyCaptcha\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
use Ossycodes\FriendlyCaptcha\FriendlyCaptcha as FriendlyCaptchaClient;
|
||||
|
||||
class FriendlyCaptcha implements Rule
|
||||
{
|
||||
protected $friendlyCaptchaClient;
|
||||
|
||||
protected array $messages = [];
|
||||
|
||||
public function __construct(
|
||||
FriendlyCaptchaClient $friendlyCaptcha
|
||||
) {
|
||||
$this->friendlyCaptchaClient = $friendlyCaptcha;
|
||||
}
|
||||
|
||||
public function passes($attribute, $value)
|
||||
{
|
||||
$response = $this->friendlyCaptchaClient->verifyResponse($value);
|
||||
|
||||
if ($response->isSuccess()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($response->getErrors() as $errorCode) {
|
||||
$this->messages[] = $this->mapErrorCodeToMessage($errorCode);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function message()
|
||||
{
|
||||
return $this->messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* map FriendlyCaptcha error code to human readable validation message
|
||||
*
|
||||
* @var string $code
|
||||
*/
|
||||
protected function mapErrorCodeToMessage(string $code): string
|
||||
{
|
||||
switch ($code) {
|
||||
case "secret_missing":
|
||||
return __('validation.secret_missing');
|
||||
break;
|
||||
case "secret_invalid":
|
||||
return __('validation.secret_invalid');
|
||||
break;
|
||||
case "solution_missing":
|
||||
return __('validation.solution_missing');
|
||||
break;
|
||||
case "bad_request":
|
||||
return __('validation.bad_request');
|
||||
break;
|
||||
case "solution_invalid":
|
||||
return __('validation.solution_invalid');
|
||||
break;
|
||||
case "solution_timeout_or_duplicate":
|
||||
return __('validation.solution_timeout_or_duplicate');
|
||||
break;
|
||||
default:
|
||||
return __('validation.unexpected');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'secret' => env('FRIENDLY_CAPTCHA_SECRET'),
|
||||
'sitekey' => env('FRIENDLY_CAPTCHA_SITEKEY'),
|
||||
'puzzle_endpoint' => env('FRIENDLY_CAPTCHA_PUZZLE_ENDPOINT', 'https://api.friendlycaptcha.com/api/v1/puzzle'),
|
||||
'verify_endpoint' => env('FRIENDLY_CAPTCHA_VERIFY_ENDPOINT', 'https://api.friendlycaptcha.com/api/v1/siteverify'),
|
||||
'options' => [
|
||||
'timeout' => 30,
|
||||
'http_errors' => false,
|
||||
],
|
||||
];
|
||||
Reference in New Issue
Block a user