Implement an interactive command to create a new API client, including input validation and confirmation steps. Add presenter and view classes to handle the output of the client creation process.
125 lines
3.4 KiB
PHP
125 lines
3.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Presentation\Console\Commands;
|
|
|
|
use Application\Security\Models\ValueObjects\ClientName;
|
|
use Application\Security\Usecases\CreateClient\CreateClient;
|
|
use Application\Security\Usecases\CreateClient\Input;
|
|
use Illuminate\Console\Command;
|
|
use Presentation\Console\Presenters\Clients\CreateClientPresenter;
|
|
use Presentation\Console\Presenters\Clients\CreateClientView;
|
|
use Shared\DDD\Usecase\Builder\UsecaseBuilder;
|
|
use Shared\DDD\Usecase\Builder\UsecaseExecutor;
|
|
|
|
final class CreateClientCommand extends Command
|
|
{
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $signature = 'client:create';
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
protected $description = 'Create a new API client (interactive wizard)';
|
|
|
|
public function handle(
|
|
CreateClient $usecase,
|
|
UsecaseExecutor $executor,
|
|
): int {
|
|
$clientName = $this->askForClientName();
|
|
|
|
if ($clientName === null) {
|
|
return self::FAILURE;
|
|
}
|
|
|
|
if (! $this->confirmCreation($clientName)) {
|
|
$this->warn('Client creation cancelled.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
$input = new Input($clientName);
|
|
|
|
/** @var CreateClientView $view */
|
|
$view = UsecaseBuilder::using($executor)
|
|
->do($usecase)
|
|
->from($input)
|
|
->with(new CreateClientPresenter())
|
|
->run();
|
|
|
|
$this->displayCredentials($view);
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function askForClientName(): ?ClientName
|
|
{
|
|
$maxAttempts = 3;
|
|
|
|
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
|
|
/** @var string|null $nameInput */
|
|
$nameInput = $this->ask('Client name (e.g. "Ones Branding website")');
|
|
$nameInput = $nameInput !== null ? trim($nameInput) : '';
|
|
|
|
if ($nameInput === '') {
|
|
$this->error('Client name cannot be empty.');
|
|
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
return new ClientName($nameInput);
|
|
} catch (\InvalidArgumentException $e) {
|
|
$this->error($e->getMessage());
|
|
|
|
if ($attempt < $maxAttempts) {
|
|
$this->warn(sprintf('You have %d attempt(s) remaining.', $maxAttempts - $attempt));
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->error('Maximum number of attempts reached. Aborting.');
|
|
|
|
return null;
|
|
}
|
|
|
|
private function confirmCreation(ClientName $name): bool
|
|
{
|
|
$this->newLine();
|
|
$this->info('Summary:');
|
|
$this->table(
|
|
['Field', 'Value'],
|
|
[
|
|
['Name', $name->value],
|
|
['Identifier', '<auto-generated>'],
|
|
['Secret', '<auto-generated>'],
|
|
['Status', 'Active'],
|
|
],
|
|
);
|
|
|
|
return $this->confirm('Create this API client?', false);
|
|
}
|
|
|
|
private function displayCredentials(CreateClientView $view): void
|
|
{
|
|
$this->newLine();
|
|
$this->info($view->message);
|
|
$this->newLine();
|
|
|
|
$this->table(
|
|
['Field', 'Value'],
|
|
[
|
|
['ID', $view->id],
|
|
['Name', $view->name],
|
|
['Identifier', $view->identifier],
|
|
['Secret', $view->secret],
|
|
],
|
|
);
|
|
|
|
$this->newLine();
|
|
$this->warn('WARNING: Store the secret securely, it cannot be retrieved later.');
|
|
}
|
|
}
|