Version 0.7.0 #1
21
app/Dto/Repository/DataCaptchaRepository/DataCaptcha.php
Normal file
21
app/Dto/Repository/DataCaptchaRepository/DataCaptcha.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Dto\Repository\DataCaptchaRepository;
|
||||||
|
|
||||||
|
final readonly class DataCaptcha
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private int $captchaId,
|
||||||
|
private array $coordinators,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getCaptchaId(): int
|
||||||
|
{
|
||||||
|
return $this->captchaId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCoordinators(): array
|
||||||
|
{
|
||||||
|
return $this->coordinators;
|
||||||
|
}
|
||||||
|
}
|
29
app/Dto/Request/Api/V1/Captcha/CheckingDto.php
Normal file
29
app/Dto/Request/Api/V1/Captcha/CheckingDto.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Dto\Request\Api\V1\Captcha;
|
||||||
|
|
||||||
|
use App\Dto\Request\Dto;
|
||||||
|
|
||||||
|
final readonly class CheckingDto extends Dto
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private CaptchaPublicToken $captchaPublicToken,
|
||||||
|
private string $captchaKey,
|
||||||
|
private array $coordinators,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getCaptchaPublicToken(): CaptchaPublicToken
|
||||||
|
{
|
||||||
|
return $this->captchaPublicToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCaptchaKey(): string
|
||||||
|
{
|
||||||
|
return $this->captchaKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCoordinators(): array
|
||||||
|
{
|
||||||
|
return $this->coordinators;
|
||||||
|
}
|
||||||
|
}
|
@ -5,4 +5,6 @@ namespace App\Enums;
|
|||||||
enum CaptchaLogType: int
|
enum CaptchaLogType: int
|
||||||
{
|
{
|
||||||
case Created = 1;
|
case Created = 1;
|
||||||
|
case Error = 2;
|
||||||
|
case Verified = 3;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
namespace App\Http\Controllers\Api\V1;
|
namespace App\Http\Controllers\Api\V1;
|
||||||
|
|
||||||
use App\Http\Requests\Api\V1\Captcha\CaptchaRequest;
|
use App\Http\Requests\Api\V1\Captcha\CaptchaRequest;
|
||||||
|
use App\Http\Requests\Api\V1\Captcha\CheckingRequest;
|
||||||
use App\Http\Resources\Api\V1\Captcha;
|
use App\Http\Resources\Api\V1\Captcha;
|
||||||
|
use App\Http\Resources\Api\V1\CaptchaVerified;
|
||||||
use App\Services\Api\V1\CaptchaService;
|
use App\Services\Api\V1\CaptchaService;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
@ -24,4 +26,16 @@ final class CaptchaController extends Controller
|
|||||||
|
|
||||||
return response()->json(new Captcha($result));
|
return response()->json(new Captcha($result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function checking(CheckingRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$maxCountError = config('captcha.validate_max_count_errors');
|
||||||
|
$params = $request->getDto();
|
||||||
|
$result = $this->captchaService->checking($params, $maxCountError);
|
||||||
|
if (!$result->isSuccess()) {
|
||||||
|
return response()->json($result->getData())->setStatusCode($result->getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(new CaptchaVerified($result));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
68
app/Http/Requests/Api/V1/Captcha/CheckingRequest.php
Normal file
68
app/Http/Requests/Api/V1/Captcha/CheckingRequest.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Api\V1\Captcha;
|
||||||
|
|
||||||
|
use App\Contracts\FormRequestDto;
|
||||||
|
use App\Dto\HttpUserData;
|
||||||
|
use App\Dto\Request\Api\V1\Captcha\CaptchaPublicToken;
|
||||||
|
use App\Dto\Request\Api\V1\Captcha\CheckingDto;
|
||||||
|
use App\Models\CaptchaToken;
|
||||||
|
use App\Repositories\CaptchaTokenRepository;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
final class CheckingRequest extends FormRequest implements FormRequestDto
|
||||||
|
{
|
||||||
|
private readonly CaptchaToken $captchaToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(CaptchaTokenRepository $captchaTokenRepository): bool
|
||||||
|
{
|
||||||
|
if (!$this->hasHeader('public-token')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$captchaToken = $captchaTokenRepository->getCaptchaTokenByPublicToken($this->header('public-token'));
|
||||||
|
if (is_null($captchaToken)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->captchaToken = $captchaToken;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'captcha_key' => ['required', 'string', 'max:75'],
|
||||||
|
'verification' => ['required', 'array'],
|
||||||
|
'verification.*' => ['required', 'array', 'size:2'],
|
||||||
|
'verification.*.x' => ['required', 'numeric', 'min:0'],
|
||||||
|
'verification.*.y' => ['required', 'numeric', 'min:0'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDto(): CheckingDto
|
||||||
|
{
|
||||||
|
$httpUserData = new HttpUserData(
|
||||||
|
$this->getClientIp(),
|
||||||
|
$this->userAgent(),
|
||||||
|
$this->header('referer')
|
||||||
|
);
|
||||||
|
|
||||||
|
$captchaPublicToken = new CaptchaPublicToken(
|
||||||
|
$this->captchaToken,
|
||||||
|
$httpUserData
|
||||||
|
);
|
||||||
|
|
||||||
|
return new CheckingDto(
|
||||||
|
captchaPublicToken: $captchaPublicToken,
|
||||||
|
captchaKey: $this->input('captcha_key'),
|
||||||
|
coordinators: $this->input('verification'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
28
app/Http/Resources/Api/V1/CaptchaVerified.php
Normal file
28
app/Http/Resources/Api/V1/CaptchaVerified.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Api\V1;
|
||||||
|
|
||||||
|
use App\ServiceResults\Api\V1\CaptchaService\CaptchaVerifiedResult;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
final class CaptchaVerified extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var CaptchaVerifiedResult
|
||||||
|
*/
|
||||||
|
public $resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'captcha_key' => $this->resource->getKey()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ final class CaptchaLog extends Model
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
'captcha_id',
|
||||||
'type',
|
'type',
|
||||||
'ip',
|
'ip',
|
||||||
'user_agent',
|
'user_agent',
|
||||||
|
@ -50,5 +50,10 @@ class RouteServiceProvider extends ServiceProvider
|
|||||||
Limit::perHour(config('rate_limiting.login_max_email_request', 10))->by($request->getClientIp() . '-' . $request->input('email')),
|
Limit::perHour(config('rate_limiting.login_max_email_request', 10))->by($request->getClientIp() . '-' . $request->input('email')),
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
RateLimiter::for('captcha-checking', function (Request $request) {
|
||||||
|
return [
|
||||||
|
Limit::perMinute(config('captcha.validate_max_count_errors', 5))->by($request->input('captcha_key', null)),
|
||||||
|
];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
app/Repositories/CaptchaLogRepository.php
Normal file
20
app/Repositories/CaptchaLogRepository.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Enums\CaptchaLogType;
|
||||||
|
use App\Models\CaptchaLog;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
|
final class CaptchaLogRepository
|
||||||
|
{
|
||||||
|
public function countByType(CaptchaLogType $type, ?int $captchaId = null): int
|
||||||
|
{
|
||||||
|
return CaptchaLog::query()
|
||||||
|
->when($captchaId, function (Builder $query, int $captchaId) {
|
||||||
|
$query->where('id', $captchaId);
|
||||||
|
})
|
||||||
|
->where('type', '=', $type)
|
||||||
|
->count();
|
||||||
|
}
|
||||||
|
}
|
13
app/Repositories/CaptchaRepository.php
Normal file
13
app/Repositories/CaptchaRepository.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Models\Captcha;
|
||||||
|
|
||||||
|
final class CaptchaRepository
|
||||||
|
{
|
||||||
|
public function getCaptchaById(int $id): ?Captcha
|
||||||
|
{
|
||||||
|
return Captcha::query()->where('id', $id)->first();
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Repositories;
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Dto\Repository\DataCaptchaRepository\DataCaptcha;
|
||||||
use App\Exceptions\Repositories\DataCaptchaRepositoryException;
|
use App\Exceptions\Repositories\DataCaptchaRepositoryException;
|
||||||
use App\Models\Captcha;
|
use App\Models\Captcha;
|
||||||
use App\Services\GenerateTokenCommand\GenerateTokenUlidCommand;
|
use App\Services\GenerateTokenCommand\GenerateTokenUlidCommand;
|
||||||
@ -28,4 +29,22 @@ final readonly class DataCaptchaRepository
|
|||||||
|
|
||||||
return $key;
|
return $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getByKey(string $key): ?DataCaptcha
|
||||||
|
{
|
||||||
|
$dataCaptcha = Cache::driver('redis')->get($key);
|
||||||
|
if (is_null($dataCaptcha)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DataCaptcha(
|
||||||
|
captchaId: $dataCaptcha['id'],
|
||||||
|
coordinators: $dataCaptcha['coordinators'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(string $key): void
|
||||||
|
{
|
||||||
|
Cache::driver('redis')->delete($key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\ServiceResults\Api\V1\CaptchaService;
|
||||||
|
|
||||||
|
use App\ServiceResults\ServiceResult;
|
||||||
|
|
||||||
|
final class CaptchaVerifiedResult extends ServiceResult
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly string $key
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getKey(): string
|
||||||
|
{
|
||||||
|
return $this->key;
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,17 @@
|
|||||||
namespace App\Services\Api\V1;
|
namespace App\Services\Api\V1;
|
||||||
|
|
||||||
use App\Dto\Request\Api\V1\Captcha\CaptchaPublicToken;
|
use App\Dto\Request\Api\V1\Captcha\CaptchaPublicToken;
|
||||||
|
use App\Dto\Request\Api\V1\Captcha\CheckingDto;
|
||||||
|
use App\Enums\CaptchaLogType;
|
||||||
|
use App\Repositories\CaptchaLogRepository;
|
||||||
|
use App\Repositories\CaptchaRepository;
|
||||||
use App\Repositories\DataCaptchaRepository;
|
use App\Repositories\DataCaptchaRepository;
|
||||||
use App\ServiceResults\Api\V1\CaptchaService\Captcha;
|
use App\ServiceResults\Api\V1\CaptchaService\Captcha;
|
||||||
|
use App\ServiceResults\Api\V1\CaptchaService\CaptchaVerifiedResult;
|
||||||
use App\ServiceResults\ServiceResultError;
|
use App\ServiceResults\ServiceResultError;
|
||||||
use App\Services\Captcha\CaptchaHandler;
|
use App\Services\Captcha\CaptchaHandler;
|
||||||
|
use App\Services\Captcha\CheckingCommand;
|
||||||
|
use App\Services\CaptchaLog\CaptchaLogHandler;
|
||||||
use App\Services\Service;
|
use App\Services\Service;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@ -16,7 +23,11 @@ final class CaptchaService extends Service
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly CaptchaGenerateService $captchaGenerateService,
|
private readonly CaptchaGenerateService $captchaGenerateService,
|
||||||
private readonly CaptchaHandler $captchaHandler,
|
private readonly CaptchaHandler $captchaHandler,
|
||||||
|
private readonly CaptchaLogHandler $captchaLogHandler,
|
||||||
private readonly DataCaptchaRepository $dataCaptchaRepository,
|
private readonly DataCaptchaRepository $dataCaptchaRepository,
|
||||||
|
private readonly CaptchaLogRepository $captchaLogRepository,
|
||||||
|
private readonly CaptchaRepository $captchaRepository,
|
||||||
|
private readonly CheckingCommand $checkingCommand,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
public function createKeyWithCaptcha(CaptchaPublicToken $captchaPublicToken, Carbon $expires): ServiceResultError | Captcha
|
public function createKeyWithCaptcha(CaptchaPublicToken $captchaPublicToken, Carbon $expires): ServiceResultError | Captcha
|
||||||
@ -43,4 +54,40 @@ final class CaptchaService extends Service
|
|||||||
key: $captchaKey
|
key: $captchaKey
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function checking(CheckingDto $checkingDto, int $maxCountError): ServiceResultError | CaptchaVerifiedResult
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$captchaData = $this->dataCaptchaRepository->getByKey($checkingDto->getCaptchaKey());
|
||||||
|
if (is_null($captchaData)) {
|
||||||
|
return $this->errValidate(__('Captcha not found or verification period has expired. Please try to refresh the captcha.'));
|
||||||
|
}
|
||||||
|
if (!$this->checkingCommand->execute($captchaData->getCoordinators(), $checkingDto->getCoordinators())) {
|
||||||
|
$this->captchaLogHandler->handleStore($captchaData->getCaptchaId(), CaptchaLogType::Error, $checkingDto->getCaptchaPublicToken()->getHttpUserData());
|
||||||
|
return $this->errValidate(__('CAPTCHA validation failed. Please try again.'));
|
||||||
|
}
|
||||||
|
$result = DB::transaction(function () use ($checkingDto, $captchaData, $maxCountError) {
|
||||||
|
$errorCount = $this->captchaLogRepository->countByType(CaptchaLogType::Error, $captchaData->getCaptchaId());
|
||||||
|
if ($errorCount > $maxCountError) {
|
||||||
|
$this->dataCaptchaRepository->destroy($checkingDto->getCaptchaKey());
|
||||||
|
return $this->errValidate(__('You have exceeded the number of attempts. Please refresh the captcha.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->captchaLogHandler->handleStore($captchaData->getCaptchaId(), CaptchaLogType::Verified, $checkingDto->getCaptchaPublicToken()->getHttpUserData());
|
||||||
|
$this->dataCaptchaRepository->destroy($checkingDto->getCaptchaKey());
|
||||||
|
|
||||||
|
$modelCaptcha = $this->captchaRepository->getCaptchaById($captchaData->getCaptchaId());
|
||||||
|
if (is_null($modelCaptcha)) {
|
||||||
|
return $this->errValidate(__('Captcha not found or verification period has expired. Please try to refresh the captcha.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CaptchaVerifiedResult(key: $modelCaptcha->uuid);
|
||||||
|
});
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
report($e);
|
||||||
|
return $this->errService('Captcha service error!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ final readonly class CaptchaHandler
|
|||||||
$captcha = $captchaToken->captchas()->create([
|
$captcha = $captchaToken->captchas()->create([
|
||||||
'uuid' => $this->uuidCommand->unique($captchaToken->captchas()->getQuery(), 'uuid')
|
'uuid' => $this->uuidCommand->unique($captchaToken->captchas()->getQuery(), 'uuid')
|
||||||
]);
|
]);
|
||||||
$this->captchaLogHandler->handleStore($captcha, CaptchaLogType::Created, $httpUserData);
|
$this->captchaLogHandler->handleStore($captcha->id, CaptchaLogType::Created, $httpUserData);
|
||||||
|
|
||||||
return $captcha;
|
return $captcha;
|
||||||
}
|
}
|
||||||
|
53
app/Services/Captcha/CheckingCommand.php
Normal file
53
app/Services/Captcha/CheckingCommand.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Services\Captcha;
|
||||||
|
|
||||||
|
use App\Captcha\Dto\Coordinators;
|
||||||
|
|
||||||
|
final readonly class CheckingCommand
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $captchaCoordinators
|
||||||
|
* @param array $userCoordinators
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function execute(array $captchaCoordinators, array $userCoordinators): bool
|
||||||
|
{
|
||||||
|
foreach ($captchaCoordinators as $index => $coordinators) {
|
||||||
|
/**
|
||||||
|
* @var Coordinators $coordinators
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (empty($userCoordinators[$index]) || !isset($userCoordinators[$index]['x']) || !isset($userCoordinators[$index]['y'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->isInside($coordinators, $userCoordinators[$index])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isInside(Coordinators $captchaCoordinators, array $userCoordinators): bool
|
||||||
|
{
|
||||||
|
$xMin = min($captchaCoordinators->getX1(), $captchaCoordinators->getX2(), $captchaCoordinators->getX3(), $captchaCoordinators->getX4());
|
||||||
|
$xMax = max($captchaCoordinators->getX1(), $captchaCoordinators->getX2(), $captchaCoordinators->getX3(), $captchaCoordinators->getX4());
|
||||||
|
|
||||||
|
$yMin = min($captchaCoordinators->getY1(), $captchaCoordinators->getY2(), $captchaCoordinators->getY3(), $captchaCoordinators->getY4());
|
||||||
|
$yMax = max($captchaCoordinators->getY1(), $captchaCoordinators->getY2(), $captchaCoordinators->getY3(), $captchaCoordinators->getY4());
|
||||||
|
|
||||||
|
if (
|
||||||
|
$xMin > $userCoordinators['x']
|
||||||
|
|| $xMax < $userCoordinators['x']
|
||||||
|
|| $yMin > $userCoordinators['y']
|
||||||
|
|| $yMax < $userCoordinators['y']
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -10,13 +10,24 @@ use Illuminate\Support\Str;
|
|||||||
|
|
||||||
final readonly class CaptchaLogHandler
|
final readonly class CaptchaLogHandler
|
||||||
{
|
{
|
||||||
public function handleStore(Captcha $captcha, CaptchaLogType $captchaLogType, HttpUserData $httpUserData): CaptchaLog
|
public function handleStore(int $captchaId, CaptchaLogType $captchaLogType, HttpUserData $httpUserData): CaptchaLog
|
||||||
{
|
{
|
||||||
return $captcha->captchaLogs()->create([
|
$userAgent = $httpUserData->getUserAgent();
|
||||||
|
if (!is_null($userAgent)) {
|
||||||
|
$userAgent = Str::limit($userAgent, 255, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
$referer = $httpUserData->getReferer();
|
||||||
|
if (!is_null($referer)) {
|
||||||
|
$referer = Str::limit($referer, 10000, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return CaptchaLog::create([
|
||||||
|
'captcha_id' => $captchaId,
|
||||||
'type' => $captchaLogType,
|
'type' => $captchaLogType,
|
||||||
'ip' => $httpUserData->getClientIp(),
|
'ip' => $httpUserData->getClientIp(),
|
||||||
'user_agent' => Str::limit($httpUserData->getUserAgent(), 255, ''),
|
'user_agent' => $userAgent,
|
||||||
'referer' => Str::limit($httpUserData->getReferer(), 10000, ''),
|
'referer' => $referer,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'waiting_for_captcha_verification_in_seconds' => env('WAITING_FOR_CAPTCHA_VERIFICATION_IN_SECONDS', 900),
|
'waiting_for_captcha_verification_in_seconds' => env('WAITING_FOR_CAPTCHA_VERIFICATION_IN_SECONDS', 900),
|
||||||
|
'validate_max_count_errors' => env('CAPTCHA_VALIDATE_MAX_COUNT_ERRORS', 3),
|
||||||
'imageClass' => \App\Captcha\Images\Image::class,
|
'imageClass' => \App\Captcha\Images\Image::class,
|
||||||
'types' => [
|
'types' => [
|
||||||
'string' => [
|
'string' => [
|
||||||
|
@ -62,5 +62,8 @@
|
|||||||
"Captcha token created successfully": "Captcha token created successfully",
|
"Captcha token created successfully": "Captcha token created successfully",
|
||||||
"Captcha token updated successfully": "Captcha token updated successfully",
|
"Captcha token updated successfully": "Captcha token updated successfully",
|
||||||
"The captcha token has been removed": "The captcha token has been removed",
|
"The captcha token has been removed": "The captcha token has been removed",
|
||||||
"Failed to generate token.": "Failed to generate token."
|
"Failed to generate token.": "Failed to generate token.",
|
||||||
|
"Captcha not found or verification period has expired. Please try to refresh the captcha.": "Captcha not found or verification period has expired. Please try to refresh the captcha.",
|
||||||
|
"CAPTCHA validation failed. Please try again.": "CAPTCHA validation failed. Please try again.",
|
||||||
|
"You have exceeded the number of attempts. Please refresh the captcha.": "You have exceeded the number of attempts. Please refresh the captcha."
|
||||||
}
|
}
|
||||||
|
@ -62,5 +62,8 @@
|
|||||||
"Captcha token created successfully": "Токен капчи успешно создан",
|
"Captcha token created successfully": "Токен капчи успешно создан",
|
||||||
"Captcha token updated successfully": "Токен капчи успешно обновлен",
|
"Captcha token updated successfully": "Токен капчи успешно обновлен",
|
||||||
"The captcha token has been removed": "Токен капчи был удален",
|
"The captcha token has been removed": "Токен капчи был удален",
|
||||||
"Failed to generate token.": "Не удалось сгенерировать токен."
|
"Failed to generate token.": "Не удалось сгенерировать токен.",
|
||||||
|
"Captcha not found or verification period has expired. Please try to refresh the captcha.": "Капча не найдена или истёк срок проверки. По пробуйтн обновить капчу.",
|
||||||
|
"CAPTCHA validation failed. Please try again.": "Не удалось пройти проверку CAPTCHA. Пожалуйста, попробуйте еще раз.",
|
||||||
|
"You have exceeded the number of attempts. Please refresh the captcha.": "Вы превысили количество попыток. Обновите каптчу."
|
||||||
}
|
}
|
||||||
|
@ -198,15 +198,12 @@
|
|||||||
"CaptchaVerification": {
|
"CaptchaVerification": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"status": {
|
"captcha_key": {
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"message": {
|
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"status", "message"
|
"captcha_key"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"CaptchaChecking": {
|
"CaptchaChecking": {
|
||||||
|
@ -15,3 +15,4 @@ use Illuminate\Support\Facades\Route;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Route::get('/captcha', [\App\Http\Controllers\Api\V1\CaptchaController::class, 'getCaptcha']);
|
Route::get('/captcha', [\App\Http\Controllers\Api\V1\CaptchaController::class, 'getCaptcha']);
|
||||||
|
Route::middleware(['throttle:captcha-checking'])->post('/captcha', [\App\Http\Controllers\Api\V1\CaptchaController::class, 'checking']);
|
||||||
|
Loading…
Reference in New Issue
Block a user