Add captcha tokens management.
This commit is contained in:
15
app/Services/CaptchaToken/BuilderCommand.php
Normal file
15
app/Services/CaptchaToken/BuilderCommand.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\CaptchaToken;
|
||||
|
||||
use App\Dto\Builder\CaptchaToken as CaptchaTokenDto;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
|
||||
final readonly class BuilderCommand
|
||||
{
|
||||
public function execute(Relation | Builder $query, CaptchaTokenDto $captchaTokenDto): Relation | Builder
|
||||
{
|
||||
return $query;
|
||||
}
|
||||
}
|
39
app/Services/CaptchaToken/CaptchaTokenHandler.php
Normal file
39
app/Services/CaptchaToken/CaptchaTokenHandler.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\CaptchaToken;
|
||||
|
||||
use App\Contracts\GenerateTokenCommand;
|
||||
use App\Models\CaptchaToken;
|
||||
use App\Models\User;
|
||||
|
||||
final readonly class CaptchaTokenHandler
|
||||
{
|
||||
public function __construct(
|
||||
private GenerateTokenCommand $generatePublicTokenCommand,
|
||||
private GenerateTokenCommand $generatePrivateTokenCommand
|
||||
) { }
|
||||
|
||||
public function handleStore(array $data, User $user): CaptchaToken
|
||||
{
|
||||
$captchaToken = new CaptchaToken();
|
||||
$captchaToken->public_token = $this->generatePublicTokenCommand->unique(CaptchaToken::query(), 'public_token');
|
||||
$captchaToken->private_token = $this->generatePrivateTokenCommand->unique(CaptchaToken::query(), 'private_token');
|
||||
$captchaToken->user_id = $user->id;
|
||||
$captchaToken->fill($data)->save();
|
||||
|
||||
return $captchaToken;
|
||||
}
|
||||
|
||||
public function handleUpdate(CaptchaToken $captchaToken, array $data): CaptchaToken
|
||||
{
|
||||
$captchaToken->update($data);
|
||||
$captchaToken->touch();
|
||||
|
||||
return $captchaToken;
|
||||
}
|
||||
|
||||
public function handleDestroy(CaptchaToken $captchaToken): void
|
||||
{
|
||||
$captchaToken->delete();
|
||||
}
|
||||
}
|
34
app/Services/GenerateTokenCommand/GenerateTokenCommand.php
Normal file
34
app/Services/GenerateTokenCommand/GenerateTokenCommand.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\GenerateTokenCommand;
|
||||
|
||||
use App\Contracts\GenerateTokenCommand as GenerateTokenCommandContract;
|
||||
use App\Exceptions\Service\GenerateTokenCommandException;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
abstract readonly class GenerateTokenCommand implements GenerateTokenCommandContract
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract public function execute(): string;
|
||||
|
||||
/**
|
||||
* @param Builder $builder
|
||||
* @param string $field
|
||||
* @param int $numberAttempts
|
||||
* @return string
|
||||
* @throws GenerateTokenCommandException
|
||||
*/
|
||||
public function unique(Builder $builder, string $field, int $numberAttempts = 10): string
|
||||
{
|
||||
for ($attempt = 0; $attempt < $numberAttempts; ++$attempt) {
|
||||
$token = $this->execute();
|
||||
if ($builder->where($field, '=', $token)->doesntExist()) {
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
||||
throw new GenerateTokenCommandException(__('Failed to generate token.'));
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\GenerateTokenCommand;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
final readonly class GenerateTokenUlidCommand extends GenerateTokenCommand
|
||||
{
|
||||
public function execute(): string
|
||||
{
|
||||
return (string) Str::ulid();
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\GenerateTokenCommand;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
final readonly class GenerateTokenUuidCommand extends GenerateTokenCommand
|
||||
{
|
||||
public function execute(): string
|
||||
{
|
||||
return (string) Str::orderedUuid();
|
||||
}
|
||||
}
|
154
app/Services/Private/CaptchaTokenService.php
Normal file
154
app/Services/Private/CaptchaTokenService.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Private;
|
||||
|
||||
use App\Dto\Builder\CaptchaToken as CaptchaTokenDto;
|
||||
use App\Dto\QuerySettingsDto;
|
||||
use App\Dto\Request\Private\CaptchaToken\StoreUpdate;
|
||||
use App\Models\User;
|
||||
use App\Models\CaptchaToken;
|
||||
use App\Repositories\CaptchaTokenRepository;
|
||||
use App\ServiceResults\ServiceResultArray;
|
||||
use App\ServiceResults\ServiceResultError;
|
||||
use App\ServiceResults\ServiceResultSuccess;
|
||||
use App\ServiceResults\StoreUpdateResult;
|
||||
use App\Services\CaptchaToken\CaptchaTokenHandler;
|
||||
use App\Services\Service;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class CaptchaTokenService extends Service
|
||||
{
|
||||
public function __construct(
|
||||
private readonly CaptchaTokenRepository $captchaTokenRepository,
|
||||
private readonly CaptchaTokenHandler $captchaTokenHandler,
|
||||
) { }
|
||||
|
||||
public function index(CaptchaTokenDto $captchaTokenDto, QuerySettingsDto $querySettingsDto, User $user): ServiceResultError | ServiceResultArray
|
||||
{
|
||||
if ($user->cannot('viewAny', CaptchaToken::class)) {
|
||||
return $this->errFobidden(__('Access is denied'));
|
||||
}
|
||||
|
||||
$userId = null;
|
||||
if ($user->cannot('viewAnyAll', CaptchaToken::class)) {
|
||||
$userId = $user->id;
|
||||
}
|
||||
|
||||
$captchaTokens = $this->captchaTokenRepository->getCaptchaTokens(
|
||||
$captchaTokenDto,
|
||||
$querySettingsDto->getQueryWith(),
|
||||
$userId
|
||||
)->pagination(
|
||||
$querySettingsDto->getLimit(),
|
||||
$querySettingsDto->getPage()
|
||||
);
|
||||
|
||||
return $this->result([
|
||||
'captchaTokens' => $captchaTokens,
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(User $user): ServiceResultError | ServiceResultArray
|
||||
{
|
||||
if ($user->cannot('create', CaptchaToken::class)) {
|
||||
return $this->errFobidden(__('Access is denied'));
|
||||
}
|
||||
|
||||
return $this->result([
|
||||
'captchaToken' => new CaptchaToken(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function edit(int $id, User $user): ServiceResultError | ServiceResultArray
|
||||
{
|
||||
$modelCaptchaToken = $this->captchaTokenRepository->getCaptchaTokenById($id);
|
||||
|
||||
if (is_null($modelCaptchaToken)) {
|
||||
return $this->errNotFound(__('Not Found'));
|
||||
}
|
||||
|
||||
if ($user->cannot('view', $modelCaptchaToken)) {
|
||||
return $this->errFobidden(__('Access is denied'));
|
||||
}
|
||||
|
||||
return $this->result([
|
||||
'captchaToken' => $modelCaptchaToken,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
|
||||
{
|
||||
if ($user->cannot('create', CaptchaToken::class)) {
|
||||
return $this->errFobidden(__('Access is denied'));
|
||||
}
|
||||
|
||||
try {
|
||||
$modelCaptchaToken = DB::transaction(function () use ($data, $user) {
|
||||
$dataCaptchaToken = $this->getDataCaptchaToken($data);
|
||||
return $this->captchaTokenHandler->handleStore($dataCaptchaToken, $user);
|
||||
});
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
}
|
||||
|
||||
return $this->resultStoreUpdateModel($modelCaptchaToken, __('Captcha token created successfully'));
|
||||
}
|
||||
|
||||
public function update(int $id, StoreUpdate $data, User $user): ServiceResultError | StoreUpdateResult
|
||||
{
|
||||
$modelCaptchaToken = $this->captchaTokenRepository->getCaptchaTokenById($id);
|
||||
|
||||
if (is_null($modelCaptchaToken)) {
|
||||
return $this->errNotFound(__('Not Found'));
|
||||
}
|
||||
|
||||
if ($user->cannot('update', $modelCaptchaToken)) {
|
||||
return $this->errFobidden(__('Access is denied'));
|
||||
}
|
||||
|
||||
try {
|
||||
$modelCaptchaToken = DB::transaction(function () use ($data, $modelCaptchaToken) {
|
||||
$dataCaptchaToken = $this->getDataCaptchaToken($data);
|
||||
|
||||
return $this->captchaTokenHandler->handleUpdate($modelCaptchaToken, $dataCaptchaToken);
|
||||
});
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
}
|
||||
|
||||
return $this->resultStoreUpdateModel($modelCaptchaToken, __('Captcha token updated successfully'));
|
||||
}
|
||||
|
||||
public function destroy(int $id, User $user): ServiceResultError | ServiceResultSuccess
|
||||
{
|
||||
$modelCaptchaToken = $this->captchaTokenRepository->getCaptchaTokenById($id);
|
||||
|
||||
if (is_null($modelCaptchaToken)) {
|
||||
return $this->errNotFound(__('Not Found'));
|
||||
}
|
||||
|
||||
if ($user->cannot('delete', $modelCaptchaToken)) {
|
||||
return $this->errFobidden(__('Access is denied'));
|
||||
}
|
||||
|
||||
try {
|
||||
DB::transaction(function () use ($modelCaptchaToken) {
|
||||
$this->captchaTokenHandler->handleDestroy($modelCaptchaToken);
|
||||
});
|
||||
} catch (\Throwable $e) {
|
||||
report($e);
|
||||
return $this->errService(__('Server Error'));
|
||||
}
|
||||
|
||||
return $this->ok(__('The captcha token has been removed'));
|
||||
}
|
||||
|
||||
private function getDataCaptchaToken(StoreUpdate $data): array
|
||||
{
|
||||
return [
|
||||
'title' => $data->getTitle(),
|
||||
];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user