generated from Nodarx/template
203 lines
7.7 KiB
PHP
203 lines
7.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
namespace KTXM\ProviderImap\Console;
|
|
|
|
use KTXM\ProviderImap\Providers\Provider;
|
|
use KTXM\ProviderImap\Providers\Service;
|
|
use KTXM\ProviderImap\Providers\ServiceIdentityBasic;
|
|
use KTXM\ProviderImap\Providers\ServiceLocation;
|
|
use KTXC\SessionTenant;
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
|
use Symfony\Component\Console\Command\Command;
|
|
use Symfony\Component\Console\Input\InputArgument;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
|
|
|
/**
|
|
* Manual IMAP service connection wizard.
|
|
*
|
|
* Interactively prompts for all connection details (host, port, encryption,
|
|
* username, password), runs a live connection test, then optionally persists
|
|
* the service to the store.
|
|
*
|
|
* Usage:
|
|
* bin/console provider_imap_mail:service:connect
|
|
* bin/console provider_imap_mail:service:connect --tenant=t1 --user=u1
|
|
*/
|
|
#[AsCommand(
|
|
name: 'provider_imap_mail:service:connect',
|
|
description: 'Manually configure and connect an IMAP service',
|
|
)]
|
|
class ConnectCommand extends Command
|
|
{
|
|
public function __construct(
|
|
private readonly Provider $provider,
|
|
private readonly SessionTenant $sessionTenant,
|
|
) {
|
|
parent::__construct();
|
|
}
|
|
|
|
protected function configure(): void
|
|
{
|
|
$this
|
|
->addOption('tenant', 't', InputOption::VALUE_REQUIRED, 'Tenant ID')
|
|
->addOption('user', 'u', InputOption::VALUE_REQUIRED, 'User ID')
|
|
->addOption('host', null, InputOption::VALUE_REQUIRED, 'IMAP server hostname')
|
|
->addOption('port', null, InputOption::VALUE_REQUIRED, 'IMAP port (default: 993)')
|
|
->addOption('encryption', null, InputOption::VALUE_REQUIRED, 'Encryption: ssl | starttls | none (default: ssl)')
|
|
->addOption('username', null, InputOption::VALUE_REQUIRED, 'IMAP username / e-mail')
|
|
->addOption('no-verify', null, InputOption::VALUE_NONE, 'Disable TLS certificate verification')
|
|
->addOption('no-save', null, InputOption::VALUE_NONE, 'Test connection only; do not persist')
|
|
->setHelp(<<<'HELP'
|
|
The <info>provider_imap_mail:service:connect</info> command walks you through
|
|
manually configuring an IMAP account. All prompts can be pre-filled via
|
|
options to support non-interactive / scripted usage.
|
|
|
|
Examples:
|
|
|
|
Fully interactive:
|
|
<info>bin/console provider_imap_mail:service:connect</info>
|
|
|
|
Pre-fill common options:
|
|
<info>bin/console provider_imap_mail:service:connect \
|
|
--host=mail.example.com --username=user@example.com \
|
|
--tenant=t1 --user=u1</info>
|
|
HELP);
|
|
}
|
|
|
|
protected function interact(InputInterface $input, OutputInterface $output): void
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
$io->title('IMAP Service — Manual Configuration');
|
|
|
|
if (!$input->getOption('tenant')) {
|
|
$tenant = $io->ask('Tenant ID');
|
|
if ($tenant) $input->setOption('tenant', $tenant);
|
|
}
|
|
|
|
if (!$input->getOption('user')) {
|
|
$user = $io->ask('User ID');
|
|
if ($user) $input->setOption('user', $user);
|
|
}
|
|
|
|
if (!$input->getOption('host')) {
|
|
$host = $io->ask('IMAP server hostname');
|
|
if ($host) $input->setOption('host', $host);
|
|
}
|
|
|
|
if (!$input->getOption('port')) {
|
|
$port = $io->ask('Port', '993');
|
|
if ($port) $input->setOption('port', $port);
|
|
}
|
|
|
|
if (!$input->getOption('encryption')) {
|
|
$enc = $io->choice('Encryption', ['ssl', 'starttls', 'none'], 'ssl');
|
|
$input->setOption('encryption', $enc);
|
|
}
|
|
|
|
if (!$input->getOption('username')) {
|
|
$username = $io->ask('Username / e-mail address');
|
|
if ($username) $input->setOption('username', $username);
|
|
}
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
|
{
|
|
$io = new SymfonyStyle($input, $output);
|
|
|
|
$tenantId = (string) ($input->getOption('tenant') ?? '');
|
|
$userId = (string) ($input->getOption('user') ?? '');
|
|
$host = (string) ($input->getOption('host') ?? '');
|
|
$port = (int) ($input->getOption('port') ?? 993);
|
|
$encryption = (string) ($input->getOption('encryption') ?? 'ssl');
|
|
$username = (string) ($input->getOption('username') ?? '');
|
|
$noVerify = (bool) $input->getOption('no-verify');
|
|
$noSave = (bool) $input->getOption('no-save');
|
|
|
|
// ── Validate required fields ─────────────────────────────────────────
|
|
|
|
$errors = [];
|
|
if ($host === '') $errors[] = 'Hostname is required.';
|
|
if ($username === '') $errors[] = 'Username is required.';
|
|
if (!$noSave) {
|
|
if ($tenantId === '') $errors[] = 'Tenant ID is required (or pass --no-save to test only).';
|
|
if ($userId === '') $errors[] = 'User ID is required (or pass --no-save to test only).';
|
|
}
|
|
|
|
if (!empty($errors)) {
|
|
$io->error($errors);
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
// ── Prompt for password (always interactive — never passed via option) ─
|
|
|
|
$password = $io->askHidden('Password');
|
|
|
|
if (!$password) {
|
|
$io->error('Password is required.');
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
// ── Build service object ────────────────────────────────────────────
|
|
|
|
$location = new ServiceLocation(
|
|
host: $host,
|
|
port: $port > 0 ? $port : 993,
|
|
encryption: $encryption,
|
|
verifyPeer: !$noVerify,
|
|
verifyPeerName: !$noVerify,
|
|
allowSelfSigned: $noVerify,
|
|
);
|
|
|
|
$identity = (new ServiceIdentityBasic())->jsonDeserialize([
|
|
'identity' => $username,
|
|
'secret' => $password,
|
|
]);
|
|
|
|
$service = new Service();
|
|
$service->setLocation($location);
|
|
$service->setIdentity($identity);
|
|
|
|
// ── Test connection ──────────────────────────────────────────────────
|
|
|
|
$io->text('Testing connection to <info>' . $host . ':' . $port . '</info>…');
|
|
|
|
$result = $this->provider->serviceTest($service);
|
|
|
|
if (!$result['success']) {
|
|
$io->error('Connection test failed: ' . $result['message']);
|
|
return Command::FAILURE;
|
|
}
|
|
|
|
$io->success($result['message']);
|
|
|
|
if ($noSave) {
|
|
$io->note('Connection test passed. Service not saved (--no-save).');
|
|
return Command::SUCCESS;
|
|
}
|
|
|
|
// ── Persist ──────────────────────────────────────────────────────────
|
|
|
|
$this->sessionTenant->configureById($tenantId);
|
|
|
|
$label = $io->ask('Service label', $username);
|
|
if ($label) {
|
|
$service->setLabel($label);
|
|
}
|
|
|
|
$id = $this->provider->serviceCreate($tenantId, $userId, $service);
|
|
$io->success("Service saved with ID: <info>{$id}</info>");
|
|
|
|
return Command::SUCCESS;
|
|
}
|
|
}
|