diff --git a/LICENSE b/LICENSE.md similarity index 95% rename from LICENSE rename to LICENSE.md index eca5772..3f3a98e 100644 --- a/LICENSE +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 kor-elf +Copyright (c) 2023 Leonid Nikitin (kor-elf) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index 40fd0f1..240e780 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,33 @@ # captcha-rule-for-laravel +Laravel 10. Rule Validation для сервиса https://git.kor-elf.net/kor-elf/service-captcha. + +Параметры в .env. + +# CAPTCHA_API_DOMAIN +Указываем адрес к сервису для проверки от робота. + +Примеры: http://captcha.localhost:9008, https://captcha.localhost, http://captcha.localhost + +# CAPTCHA_PRIVATE_TOKEN +Указываем приватный токен, для проверки со стороны сервера. + +# CAPTCHA_CURL_TIMEOUT +Curl timeout в секундах. +По умолчанию: 10 + + +# CAPTCHA_ENABLE_BLADE_CAPTCHA +Включает Blade::directive "captcha" (@captcha). + +По умолчанию: true + +# CAPTCHA_PUBLIC_TOKEN +Указываем публичный токен, который мы получаем от сервиса для проверки от робота. + +# CAPTCHA_STATIC_PATH +Указываем путь к статике. + +Примеры: /captcha, https://captcha.localhost/captcha + +По умолчанию: env('CAPTCHA_API_DOMAIN') . '/captcha' \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..d18902d --- /dev/null +++ b/composer.json @@ -0,0 +1,40 @@ +{ + "name": "kor-elf/captcha-rule-for-laravel", + "description": "Validation Rule Captcha for Laravel", + "license": "MIT", + "type": "library", + "keywords": [ + "captcha", + "laravel", + "validation" + ], + "homepage": "https://git.kor-elf.net/kor-elf/captcha-rule-for-laravel", + "authors": [ + { + "name": "Leonid Nikitin", + "email": "i@kor-elf.net", + "homepage": "https://git.kor-elf.net/kor-elf", + "role": "Developer" + } + ], + "require": { + "php": "^8.2", + "illuminate/support": "^10.0", + "guzzlehttp/guzzle": "^7.0.1" + }, + "extra": { + "laravel": { + "providers": [ + "korElf\\CaptchaRuleForLaravel\\CaptchaProvider" + ] + } + }, + "autoload": { + "psr-4": { + "korElf\\CaptchaRuleForLaravel\\": "src/" + }, + "files": [ + "src/helpers.php" + ] + } +} diff --git a/config/captcha.php b/config/captcha.php new file mode 100644 index 0000000..4ecd1ba --- /dev/null +++ b/config/captcha.php @@ -0,0 +1,58 @@ + env('CAPTCHA_API_DOMAIN'), + + /* + * Приватный токен для проверки получаемого ключа после успешной проверки от бота. + */ + 'api_private_token' => env('CAPTCHA_PRIVATE_TOKEN'), + + /* + * Curl timeout в секундах. + */ + 'curl_timeout' => (int) env('CAPTCHA_CURL_TIMEOUT', 10), + + /* + * Включает Blade::directive "captcha". + */ + 'enable_blade_captcha' => (bool) env('CAPTCHA_ENABLE_BLADE_CAPTCHA', true), + + /* + * Публичный токен для начало проверки я не робот. + */ + 'api_public_token' => env('CAPTCHA_PUBLIC_TOKEN'), + + /** + * Указываем путь к статике, на данный момент это к стилям. + * Примеры: /captcha, https://captcha.localhost/captcha + */ + 'static_path' => env('CAPTCHA_STATIC_PATH', env('CAPTCHA_API_DOMAIN') . '/captcha'), + + /* + * Используется в переводах. + */ + 'error_message_key' => 'validation.captcha', + + /* + * Имя Validator::extendImplicit. + */ + 'rule_name' => 'captcha', + + /* + * Name в input после успешной проверки. + */ + 'captcha_verified_name' => 'captcha-verified', +]; diff --git a/src/CaptchaProvider.php b/src/CaptchaProvider.php new file mode 100644 index 0000000..ea326d6 --- /dev/null +++ b/src/CaptchaProvider.php @@ -0,0 +1,60 @@ +addValidationRule(); + $this->publishes([ + __DIR__ . '/../config/captcha.php' => config_path('captcha.php'), + ], 'config'); + + if (config('captcha.enable_blade_captcha')) { + Blade::directive('captcha', function () { + return ""; + }); + } + } + + /** + * Extends Validator to include a captcha type + */ + public function addValidationRule(): Void + { + $message = trans(config('captcha.error_message_key')); + Validator::extendImplicit(config('captcha.rule_name'), function ($attribute, $value) { + if (!is_string($value)) { + return false; + } + return app(CaptchaService::class)->validate($value, request()->userAgent()); + }, $message); + } + + /** + * Register the service provider. + * + * @return void + */ + public function register(): Void + { + $this->mergeConfigFrom( + __DIR__ . '/../config/captcha.php', + 'captcha' + ); + + $this->app->singleton(CaptchaService::class, function (Application $app) { + return new CaptchaService( + privateToken: config('captcha.api_private_token', ''), + domainApi: config('captcha.api_domain', ''), + curlTimeout: config('captcha.curl_timeout', ''), + ); + }); + } +} diff --git a/src/CaptchaService.php b/src/CaptchaService.php new file mode 100644 index 0000000..7680148 --- /dev/null +++ b/src/CaptchaService.php @@ -0,0 +1,35 @@ + $this->privateToken, + ]) + ->timeout($this->curlTimeout) + ->post($this->domainApi . '/api/v1/captcha/' . $token, $post); + + return ($response->json('status') === true); + } catch (\Throwable $e) { + + } + return false; + } +} \ No newline at end of file diff --git a/src/helpers.php b/src/helpers.php new file mode 100644 index 0000000..cd647f6 --- /dev/null +++ b/src/helpers.php @@ -0,0 +1,8 @@ +'; +}