🆙 Add cms i using 🆙

This commit is contained in:
Remco
2025-11-25 22:42:56 +01:00
parent 94704e0925
commit d44196149e
35591 changed files with 3601123 additions and 0 deletions
@@ -0,0 +1,36 @@
<?php
namespace RyanChandler\LaravelCloudflareTurnstile;
use Illuminate\Support\Facades\Http;
use RyanChandler\LaravelCloudflareTurnstile\Contracts\ClientInterface;
use RyanChandler\LaravelCloudflareTurnstile\Responses\SiteverifyResponse;
class Client implements ClientInterface
{
public function __construct(
protected string $secret,
) {}
public function siteverify(string $response): SiteverifyResponse
{
$response = Http::retry(3, 100)
->asForm()
->acceptJson()
->post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
'secret' => config('services.turnstile.secret'),
'response' => $response,
]);
if (! $response->ok()) {
return SiteverifyResponse::success();
}
return SiteverifyResponse::failure($response->json('error-codes'));
}
public function dummy(): string
{
return self::RESPONSE_DUMMY_TOKEN;
}
}
@@ -0,0 +1,12 @@
<?php
namespace RyanChandler\LaravelCloudflareTurnstile\Contracts;
use RyanChandler\LaravelCloudflareTurnstile\Responses\SiteverifyResponse;
interface ClientInterface
{
const RESPONSE_DUMMY_TOKEN = 'XXXX.DUMMY.TOKEN.XXXX';
public function siteverify(string $response): SiteverifyResponse;
}
@@ -0,0 +1,26 @@
<?php
namespace RyanChandler\LaravelCloudflareTurnstile\Facades;
use Illuminate\Support\Facades\Facade;
use RyanChandler\LaravelCloudflareTurnstile\Contracts\ClientInterface;
use RyanChandler\LaravelCloudflareTurnstile\Testing\FakeClient;
/**
* @method static string dummy()
* @method static \RyanChandler\LaravelCloudflareTurnstile\Responses\SiteverifyResponse siteverify(string $response)
*/
class Turnstile extends Facade
{
protected static function getFacadeAccessor(): string
{
return ClientInterface::class;
}
public static function fake(): FakeClient
{
static::swap($fake = new FakeClient);
return $fake;
}
}
@@ -0,0 +1,40 @@
<?php
namespace RyanChandler\LaravelCloudflareTurnstile;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Blade;
use RyanChandler\LaravelCloudflareTurnstile\Contracts\ClientInterface;
use RyanChandler\LaravelCloudflareTurnstile\View\Components\Scripts;
use RyanChandler\LaravelCloudflareTurnstile\View\Components\Turnstile as TurnstileComponent;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
class LaravelCloudflareTurnstileServiceProvider extends PackageServiceProvider
{
public function configurePackage(Package $package): void
{
$package
->name('laravel-cloudflare-turnstile')
->hasTranslations()
->hasViews();
}
public function packageRegistered(): void
{
$this->app->scoped(ClientInterface::class, static function (Application $app): Client {
return new Client($app['config']->get('services.turnstile.secret'));
});
}
public function packageBooted(): void
{
$this->bootBlade();
}
private function bootBlade(): void
{
Blade::component('turnstile.scripts', Scripts::class);
Blade::component('turnstile', TurnstileComponent::class);
}
}
@@ -0,0 +1,31 @@
<?php
namespace RyanChandler\LaravelCloudflareTurnstile\Responses;
use Illuminate\Contracts\Support\Arrayable;
class SiteverifyResponse implements Arrayable
{
public function __construct(
public readonly bool $success,
public readonly array $errorCodes,
) {}
public static function success(): self
{
return new self(true, []);
}
public static function failure(array $errorCodes = []): self
{
return new self(false, $errorCodes);
}
public function toArray(): array
{
return [
'success' => $this->success,
'error-codes' => $this->errorCodes,
];
}
}
@@ -0,0 +1,34 @@
<?php
namespace RyanChandler\LaravelCloudflareTurnstile\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use RyanChandler\LaravelCloudflareTurnstile\Facades\Turnstile as Facade;
class Turnstile implements ValidationRule
{
protected array $messages = [];
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$response = Facade::siteverify($value);
if ($response->success) {
return;
}
foreach ($response->errorCodes as $errorCode) {
$fail(match ($errorCode) {
'missing-input-secret' => __('cloudflare-turnstile::errors.missing-input-secret'),
'invalid-input-secret' => __('cloudflare-turnstile::errors.invalid-input-secret'),
'missing-input-response' => __('cloudflare-turnstile::errors.missing-input-response'),
'invalid-input-response' => __('cloudflare-turnstile::errors.invalid-input-response'),
'bad-request' => __('cloudflare-turnstile::errors.bad-request'),
'timeout-or-duplicate' => __('cloudflare-turnstile::errors.timeout-or-duplicate'),
'internal-error' => __('cloudflare-turnstile::errors.internal-error'),
default => __('cloudflare-turnstile::errors.unexpected'),
});
}
}
}
@@ -0,0 +1,53 @@
<?php
namespace RyanChandler\LaravelCloudflareTurnstile\Testing;
use Illuminate\Support\Testing\Fakes\Fake;
use RyanChandler\LaravelCloudflareTurnstile\Contracts\ClientInterface;
use RyanChandler\LaravelCloudflareTurnstile\Responses\SiteverifyResponse;
class FakeClient implements ClientInterface, Fake
{
protected bool $shouldPass = true;
protected bool $isExpired = false;
public function fail(): self
{
$this->shouldPass = false;
return $this;
}
public function expired(): self
{
$this->isExpired = true;
return $this;
}
public function pass(): self
{
$this->shouldPass = true;
return $this;
}
public function siteverify(string $response): SiteverifyResponse
{
if ($this->isExpired) {
return SiteverifyResponse::failure(['timeout-or-duplicate']);
}
if (! $this->shouldPass) {
return SiteverifyResponse::failure(['invalid-input-response']);
}
return SiteverifyResponse::success();
}
public function dummy(): string
{
return self::RESPONSE_DUMMY_TOKEN;
}
}
@@ -0,0 +1,14 @@
<?php
namespace RyanChandler\LaravelCloudflareTurnstile\View\Components;
use Illuminate\View\Component;
class Scripts extends Component
{
public function render()
{
// @phpstan-ignore-next-line argument.type
return view('cloudflare-turnstile::components.scripts');
}
}
@@ -0,0 +1,14 @@
<?php
namespace RyanChandler\LaravelCloudflareTurnstile\View\Components;
use Illuminate\View\Component;
class Turnstile extends Component
{
public function render()
{
// @phpstan-ignore argument.type
return view('cloudflare-turnstile::components.turnstile');
}
}