config: removed support for --config option. deprecated the use backend_name as argument.

This commit is contained in:
Abdulmhsen B. A. A
2024-03-07 19:18:13 +03:00
parent 0c5f9924ed
commit fab02e7ad3
7 changed files with 138 additions and 454 deletions

View File

@@ -33,8 +33,8 @@ final class AddCommand extends Command
{
$this->setName(self::ROUTE)
->setDescription('Add new backend.')
->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Use Alternative config file.')
->addArgument('backend', InputArgument::OPTIONAL, 'Backend name', null)
->addOption('select-backend', 's', InputOption::VALUE_REQUIRED, 'Select backend.')
->setHelp(
r(
<<<HELP
@@ -44,7 +44,7 @@ final class AddCommand extends Command
This command is shortcut for running the following command:
{cmd} <cmd>{manage_route}</cmd> --add -- <value>backend_name</value>
{cmd} <cmd>{manage_route}</cmd> <flag>--add -s</flag> <value>backend_name</value>
HELP,
[
@@ -103,10 +103,19 @@ final class AddCommand extends Command
$opts['--' . $option] = $val;
}
$backend = $input->getArgument('backend');
if (null !== ($name = $input->getOption('select-backend'))) {
$name = explode(',', $name, 2)[0];
}
if (null !== $backend) {
$opts['backend'] = strtolower($backend);
if (empty($name) && null !== ($name = $input->getArgument('backend'))) {
$name = $input->getArgument('backend');
$output->writeln(
'<notice>WARNING: The use of backend name as argument is deprecated and will be removed from future versions. Please use [-s, --select-backend] option instead.</notice>'
);
}
if (null !== $name) {
$opts['backend'] = strtolower($name);
} else {
// -- $backend.token
$opts['backend'] = (function () use (&$opts, $input, $output) {
@@ -144,7 +153,7 @@ final class AddCommand extends Command
return (new QuestionHelper())->ask($input, $output, $question);
})();
$output->writeln('');
$opts['backend'] = strtolower($opts['backend']);
$opts['--select-backend'] = strtolower($opts['backend']);
}
return $this->getApplication()?->find(ManageCommand::ROUTE)->run(new ArrayInput($opts), $output) ?? 1;

View File

@@ -7,15 +7,15 @@ namespace App\Commands\Config;
use App\Command;
use App\Libs\Attributes\Route\Cli;
use App\Libs\Config;
use App\Libs\ConfigFile;
use App\Libs\Database\DatabaseInterface as iDB;
use App\Libs\Stream;
use PDO;
use Psr\Log\LoggerInterface;
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\Question\ConfirmationQuestion;
use Symfony\Component\Yaml\Yaml;
/**
* Class DeleteCommand
@@ -30,16 +30,9 @@ final class DeleteCommand extends Command
public const ROUTE = 'config:delete';
private PDO $pdo;
/**
* Class constructor.
*
* @param iDB $db The iDB instance used for database interaction.
*
* @return void
*/
public function __construct(private iDB $db)
public function __construct(private LoggerInterface $logger, iDB $db)
{
$this->pdo = $this->db->getPDO();
$this->pdo = $db->getPDO();
parent::__construct();
}
@@ -51,8 +44,8 @@ final class DeleteCommand extends Command
{
$this->setName(self::ROUTE)
->setDescription('Delete Local backend data.')
->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Use Alternative config file.')
->addArgument('backend', InputArgument::REQUIRED, 'Backend name.')
->addOption('select-backend', 's', InputOption::VALUE_REQUIRED, 'Select backend.')
->addArgument('backend', InputArgument::OPTIONAL, 'Backend name.')
->setHelp(
r(
<<<HELP
@@ -117,26 +110,21 @@ final class DeleteCommand extends Command
return self::FAILURE;
}
$custom = false;
// -- Use Custom servers.yaml file.
if (($config = $input->getOption('config'))) {
try {
$custom = true;
$backends = (array)Yaml::parseFile($this->checkCustomBackendsFile($config));
} catch (\App\Libs\Exceptions\RuntimeException $e) {
$output->writeln(r('<error>ERROR:</error> {error}', ['error' => $e->getMessage()]));
return self::FAILURE;
}
} else {
$config = Config::get('path') . '/config/servers.yaml';
if (!file_exists($config)) {
touch($config);
}
$backends = (array)Config::get('servers', []);
if (null !== ($name = $input->getOption('select-backend'))) {
$name = explode(',', $name, 2)[0];
}
$name = $input->getArgument('backend');
if (empty($name) && null !== ($name = $input->getArgument('backend'))) {
$name = $input->getArgument('backend');
$output->writeln(
'<notice>WARNING: The use of backend name as argument is deprecated and will be removed from future versions. Please use [-s, --select-backend] option instead.</notice>'
);
}
if (empty($name)) {
$output->writeln(r('<error>ERROR: Backend not specified. Please use [-s, --select-backend].</error>'));
return self::FAILURE;
}
if (!isValidName($name) || strtolower($name) !== $name) {
$output->writeln(
@@ -150,7 +138,10 @@ final class DeleteCommand extends Command
return self::FAILURE;
}
if (null === ag($backends, "{$name}.type", null)) {
$configFile = ConfigFile::open(Config::get('backends_file'), 'yaml');
$configFile->setLogger($this->logger);
if (null === $configFile->get("{$name}.type", null)) {
$output->writeln(
r('<error>ERROR:</error> No backend named [<value>{backend}</value>] was found.', [
'backend' => $name,
@@ -164,7 +155,7 @@ final class DeleteCommand extends Command
$question = new ConfirmationQuestion(
r(
<<<HELP
<question>Are you sure you want to remove [<value>{name}</value>] data?</question>? {default}
<question>Are you sure you want to remove [<value>{name}</value>] data?</question> {default}
------------------
<notice>WARNING:</notice> This command will remove entries from database related to the backend.
Database records will be removed if [<value>{name}</value>] was the only backend referencing them.
@@ -240,15 +231,7 @@ final class DeleteCommand extends Command
);
}
if (false === $custom) {
copy($config, $config . '.bak');
}
$backends = ag_delete($backends, $name);
$stream = new Stream($config, 'w');
$stream->write(Yaml::dump($backends, 8, 2));
$stream->close();
$configFile->delete($name)->persist();
$output->writeln('<info>Config updated.</info>');

View File

@@ -7,14 +7,14 @@ namespace App\Commands\Config;
use App\Command;
use App\Libs\Attributes\Route\Cli;
use App\Libs\Config;
use App\Libs\Stream;
use App\Libs\ConfigFile;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
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\Yaml\Yaml;
use Throwable;
/**
@@ -27,6 +27,11 @@ final class EditCommand extends Command
{
public const ROUTE = 'config:edit';
public function __construct(private LoggerInterface $logger)
{
parent::__construct();
}
/**
* Configures the command.
*/
@@ -36,10 +41,11 @@ final class EditCommand extends Command
->setDescription('Edit backend settings inline.')
->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Use Alternative config file.')
->addOption('key', 'k', InputOption::VALUE_REQUIRED, 'Key to update.')
->addOption('set', 's', InputOption::VALUE_REQUIRED, 'Value to set.')
->addOption('set', 'e', InputOption::VALUE_REQUIRED, 'Value to set.')
->addOption('delete', 'd', InputOption::VALUE_NONE, 'Delete value.')
->addOption('regenerate-webhook-token', 'g', InputOption::VALUE_NONE, 'Re-generate backend webhook token.')
->addArgument('backend', InputArgument::REQUIRED, 'Backend name')
->addOption('select-backend', 's', InputOption::VALUE_REQUIRED, 'Select backend.')
->addArgument('backend', InputArgument::OPTIONAL, 'Backend name')
->setHelp(
r(
<<<HELP
@@ -56,11 +62,11 @@ final class EditCommand extends Command
<question># How to edit config setting?</question>
{cmd} <cmd>{route}</cmd> <flag>--key</flag> <value>key</value> <flag>--set</flag> <value>value</value> -- <value>backend_name</value>
{cmd} <cmd>{route}</cmd> <flag>--key</flag> <value>key</value> <flag>--set</flag> <value>value</value> <flag>-s</flag> <value>backend_name</value>
<question># How to change the webhook token?</question>
<question># How to change the re-generate webhook token?</question>
{cmd} <cmd>{route}</cmd> <flag>--regenerate-webhook-token</flag> -- <value>backend_name</value>
{cmd} <cmd>{route}</cmd> <flag>-g -s</flag> <value>backend_name</value>
HELP,
[
@@ -96,25 +102,21 @@ final class EditCommand extends Command
*/
protected function runCommand(InputInterface $input, OutputInterface $output, null|array $rerun = null): int
{
// -- Use Custom servers.yaml file.
if (($config = $input->getOption('config'))) {
try {
$custom = true;
$backends = Yaml::parseFile($this->checkCustomBackendsFile($config));
} catch (\App\Libs\Exceptions\RuntimeException $e) {
$output->writeln(r('<error>{error}</error>', ['error' => $e->getMessage()]));
return self::FAILURE;
}
} else {
$custom = false;
$config = Config::get('path') . '/config/servers.yaml';
if (!file_exists($config)) {
touch($config);
}
$backends = (array)Config::get('servers', []);
if (null !== ($name = $input->getOption('select-backend'))) {
$name = explode(',', $name, 2)[0];
}
$name = $input->getArgument('backend');
if (empty($name) && null !== ($name = $input->getArgument('backend'))) {
$name = $input->getArgument('backend');
$output->writeln(
'<notice>WARNING: The use of backend name as argument is deprecated and will be removed from future versions. Please use [-s, --select-backend] option instead.</notice>'
);
}
if (empty($name)) {
$output->writeln(r('<error>ERROR: Backend not specified. Please use [-s, --select-backend].</error>'));
return self::FAILURE;
}
if (!isValidName($name) || strtolower($name) !== $name) {
$output->writeln(
@@ -128,7 +130,10 @@ final class EditCommand extends Command
return self::FAILURE;
}
if (null === ($backend = ag($backends, $name, null))) {
$configFile = ConfigFile::open(Config::get('backends_file'), 'yaml');
$configFile->setLogger($this->logger);
if (null === $configFile->get("{$name}.type", null)) {
$output->writeln(r('<error>ERROR: Backend \'{name}\' not found.</error>', ['name' => $name]));
return self::FAILURE;
}
@@ -137,14 +142,12 @@ final class EditCommand extends Command
try {
$webhookToken = bin2hex(random_bytes(Config::get('webhook.tokenLength')));
$output->writeln(
r('<info>The webhook token for \'{name}\' is: \'{token}\'.</info>', [
'name' => $name,
'token' => $webhookToken
])
);
$output->writeln(r('<info>The webhook token for \'{name}\' is: \'{token}\'.</info>', [
'name' => $name,
'token' => $webhookToken
]));
$backend = ag_set($backend, 'webhook.token', $webhookToken);
$configFile->set("{$name}.webhook.token", $webhookToken);
} catch (Throwable $e) {
$output->writeln(r('<error>ERROR: {error}</error>', ['error' => $e->getMessage()]));
return self::FAILURE;
@@ -166,7 +169,12 @@ final class EditCommand extends Command
}
if (null === $value && !$input->getOption('delete')) {
$val = ag($backend, $key, '[No value]');
if ($configFile->has("{$name}.{$key}")) {
$val = $configFile->get("{$name}.{$key}", '[No value]');
} else {
$val = '[Not set]';
}
$output->writeln(is_scalar($val) ? (string)$val : r('Type({type})', ['type' => get_debug_type($val)]));
return self::SUCCESS;
}
@@ -182,50 +190,38 @@ final class EditCommand extends Command
$value = (string)$value;
}
if ($value === ag($backend, $key, null)) {
if ($value === $configFile->get("{$name}.{$key}", null)) {
$output->writeln('<comment>Not updating. Value already matches.</comment>');
return self::SUCCESS;
}
$backend = ag_set($backend, $key, $value);
$configFile->set("{$name}.{$key}", $value);
$output->writeln(
r("<info>{name}: Updated '{key}' key value to '{value}'.</info>", [
'name' => $name,
'key' => $key,
'value' => is_bool($value) ? (true === $value ? 'true' : 'false') : $value,
])
);
$output->writeln(r("<info>{name}: Updated '{key}' key value to '{value}'.</info>", [
'name' => $name,
'key' => $key,
'value' => is_bool($value) ? (true === $value ? 'true' : 'false') : $value,
]));
}
if ($input->getOption('delete')) {
if (false === ag_exists($backend, $key)) {
$output->writeln(
r("<error>{name}: '{key}' key does not exist.</error>", [
'name' => $name,
'key' => $key
])
);
if (false === $configFile->has("{$name}.{$key}")) {
$output->writeln(r("<error>{name}: '{key}' key does not exist.</error>", [
'name' => $name,
'key' => $key
]));
return self::FAILURE;
}
$backend = ag_delete($backend, $key);
$output->writeln(
r("<info>{name}: Removed '{key}' key.</info>", [
'name' => $name,
'key' => $key
])
);
$configFile->delete("{$name}.{$key}");
$output->writeln(r("<info>{name}: Removed '{key}' key.</info>", [
'name' => $name,
'key' => $key
]));
}
}
if (false === $custom) {
copy($config, $config . '.bak');
}
$stream = Stream::make($config, 'w');
$stream->write(Yaml::dump(ag_set($backends, $name, $backend), 8, 2));
$stream->close();
$configFile->persist();
return self::SUCCESS;
}

View File

@@ -10,9 +10,7 @@ use App\Libs\Config;
use App\Libs\Options;
use DateTimeInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Yaml\Yaml;
#[Cli(command: self::ROUTE)]
final class ListCommand extends Command
@@ -25,15 +23,8 @@ final class ListCommand extends Command
protected function configure(): void
{
$this->setName(self::ROUTE)
->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Use Alternative config file.')
->setDescription('List Added backends.')
->setHelp(
<<<HELP
This command list your configured backends.
HELP
);
->setHelp('This command list your configured backends.');
}
/**
@@ -46,16 +37,6 @@ final class ListCommand extends Command
*/
protected function runCommand(InputInterface $input, OutputInterface $output): int
{
// -- Use Custom servers.yaml file.
if (($config = $input->getOption('config'))) {
try {
Config::save('servers', Yaml::parseFile($this->checkCustomBackendsFile($config)));
} catch (\App\Libs\Exceptions\RuntimeException $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return self::FAILURE;
}
}
$list = [];
foreach (Config::get('servers', []) as $name => $backend) {

View File

@@ -9,8 +9,9 @@ use App\Commands\State\ImportCommand;
use App\Commands\System\IndexCommand;
use App\Libs\Attributes\Route\Cli;
use App\Libs\Config;
use App\Libs\ConfigFile;
use App\Libs\Options;
use App\Libs\Stream;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputArgument;
@@ -32,13 +33,18 @@ final class ManageCommand extends Command
{
public const ROUTE = 'config:manage';
public function __construct(private LoggerInterface $logger)
{
parent::__construct();
}
protected function configure(): void
{
$this->setName(self::ROUTE)
->setDescription('Manage backend settings.')
->addOption('add', 'a', InputOption::VALUE_NONE, 'Add Backend.')
->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Use Alternative config file.')
->addArgument('backend', InputArgument::REQUIRED, 'Backend name.')
->addOption('select-backend', 's', InputOption::VALUE_REQUIRED, 'Select backend.')
->addArgument('backend', InputArgument::OPTIONAL, 'Backend name.')
->setHelp(
r(
<<<HELP
@@ -89,27 +95,26 @@ final class ManageCommand extends Command
return self::FAILURE;
}
$custom = false;
// -- Use Custom servers.yaml file.
if (($config = $input->getOption('config'))) {
try {
$custom = true;
$backends = (array)Yaml::parseFile($this->checkCustomBackendsFile($config));
} catch (\App\Libs\Exceptions\RuntimeException $e) {
$output->writeln(r('<error>ERROR:</error> {error}', ['error' => $e->getMessage()]));
return self::FAILURE;
}
} else {
$config = Config::get('path') . '/config/servers.yaml';
if (!file_exists($config)) {
touch($config);
}
$backends = (array)Config::get('servers', []);
if (null !== ($name = $input->getOption('select-backend'))) {
$name = explode(',', $name, 2)[0];
}
if (empty($name) && null !== ($name = $input->getArgument('backend'))) {
$name = $input->getArgument('backend');
$output->writeln(
'<notice>WARNING: The use of backend name as argument is deprecated and will be removed from future versions. Please use [-s, --select-backend] option instead.</notice>'
);
}
if (empty($name)) {
$output->writeln(r('<error>ERROR: Backend not specified. Please use [-s, --select-backend].</error>'));
return self::FAILURE;
}
$configFile = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
$configFile->setLogger($this->logger);
$add = $input->getOption('add');
$name = $input->getArgument('backend');
if (!isValidName($name) || strtolower($name) !== $name) {
$output->writeln(
@@ -124,7 +129,7 @@ final class ManageCommand extends Command
}
if (true === $add) {
if (null !== ag($backends, "{$name}.type", null)) {
if (null !== $configFile->get("{$name}.type", null)) {
$output->writeln(
r(
'<error>ERROR:</error> Backend with [<value>{backend}</value>] name already exists. Omit the [<flag>--add</flag>] flag if you want to edit the backend settings.',
@@ -135,7 +140,7 @@ final class ManageCommand extends Command
);
return self::FAILURE;
}
} elseif (null === ag($backends, "{$name}.type", null)) {
} elseif (null === $configFile->get("{$name}.type", null)) {
$output->writeln(
r(
'<error>ERROR:</error> No backend named [<value>{backend}</value>] was found. Append [<flag>--add</flag>] to add as new backend.',
@@ -147,7 +152,7 @@ final class ManageCommand extends Command
return self::FAILURE;
}
$u = $rerun ?? ag($backends, $name, []);
$u = $rerun ?? $configFile->get($name, []);
$u['name'] = $name;
$output->writeln('');
@@ -392,19 +397,11 @@ final class ManageCommand extends Command
return $this->runCommand($input, $output, $u);
}
if (false === $custom) {
copy($config, $config . '.bak');
}
$backends = ag_set($backends, $name, $u);
$stream = new Stream($config, 'w');
$stream->write(Yaml::dump($backends, 8, 2));
$stream->close();
$configFile->set($name, $u)->persist();
$output->writeln('<info>Config updated.</info>');
if (false === $custom && $input->getOption('add')) {
if ($input->getOption('add')) {
$helper = $this->getHelper('question');
$text =
<<<TEXT
@@ -452,15 +449,9 @@ final class ManageCommand extends Command
'type' => $importType
])
);
$cmd = $this->getApplication()?->find(ImportCommand::ROUTE);
$cmd->run(
new ArrayInput([
'--quiet',
'--config' => $config,
'--select-backends' => $name
]),
$output
);
$cmd->run(new ArrayInput(['--quiet', '--select-backends' => $name]), $output);
}
$output->writeln('<info>Import complete</info>');

View File

@@ -1,264 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Commands\Config;
use App\Command;
use App\Libs\Attributes\Route\Cli;
use App\Libs\Config;
use App\Libs\Stream;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
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\Yaml\Yaml;
use Throwable;
/**
* Class UnifyCommand
*
* UnifyCommand is a command that unifies the webhook tokens of backend types.
*
* @package Your\Namespace
*/
#[Cli(command: self::ROUTE)]
final class UnifyCommand extends Command
{
public const ROUTE = 'config:unify';
/**
* Configure the command.
*/
protected function configure(): void
{
$this->setName(self::ROUTE)
->setDescription('Unify backend type webhook tokens.')
->addOption('select-backends', 's', InputOption::VALUE_OPTIONAL, 'Select backends. comma , seperated.', '')
->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Use Alternative config file.')
->addArgument(
'type',
InputArgument::REQUIRED,
sprintf(
'Backend type to unify. Expecting one of [%s]',
implode('|', array_keys(Config::get('supported', [])))
),
)
->setHelp(
r(
<<<HELP
This command is mainly intended for <notice>Plex</notice> multi server users.
You shouldn't use this command unless told by the team.
Due to <notice>Plex</notice> webhook limitation you cannot use multiple webhook tokens for one PlexPass account.
And as workaround we have to use one webhook token for all of your <notice>Plex</notice> backends.
This command will do the following.
3. Update backends unique identifier (uuid).
1. Change the selected backend's webhook tokens to be replica of each other.
2. Enable limit backend webhook requests to matching unique identifier.
To execute the command, you can do the following
{cmd} <cmd>{route}</cmd> -- <value>plex</value>
HELP,
[
'cmd' => trim(commandContext()),
'route' => self::ROUTE,
]
)
);
}
/**
* Run the command.
*
* @param InputInterface $input The input interface.
* @param OutputInterface $output The output interface.
*
* @return int Returns the exit code.
*/
protected function runCommand(InputInterface $input, OutputInterface $output): int
{
// -- Use Custom servers.yaml file.
if (($config = $input->getOption('config'))) {
try {
$custom = true;
Config::save('servers', Yaml::parseFile($this->checkCustomBackendsFile($config)));
} catch (\App\Libs\Exceptions\RuntimeException $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return self::FAILURE;
}
} else {
$custom = false;
$config = Config::get('path') . '/config/servers.yaml';
if (!file_exists($config)) {
touch($config);
}
}
$type = strtolower((string)$input->getArgument('type'));
if (!array_key_exists($type, Config::get('supported', []))) {
$message = r("<error>Invalid type was given. Expecting one of [{backends}] but got '{backend}' instead.", [
'backends' => implode('|', array_keys(Config::get('supported', []))),
'backend' => $type,
]);
$output->writeln($message);
return self::FAILURE;
}
$selectBackends = (string)$input->getOption('select-backends');
$selected = explode(',', $selectBackends);
$selected = array_map('trim', $selected);
$isCustom = !empty($selectBackends) && count($selected) >= 1;
$list = $keys = [];
foreach (Config::get('servers', []) as $backendName => $backend) {
if (ag($backend, 'type') !== $type) {
$output->writeln(
sprintf(
'<comment>Ignoring \'%s\' backend, not of %s type. (type: %s).</comment>',
$backendName,
$type,
ag($backend, 'type')
),
OutputInterface::VERBOSITY_DEBUG
);
continue;
}
if ($isCustom && !in_array($backendName, $selected, true)) {
$output->writeln(
sprintf(
'<comment>Ignoring \'%s\' as requested by [-s, --select-backends] filter.</comment>',
$backendName
),
OutputInterface::VERBOSITY_DEBUG
);
continue;
}
$backend['name'] = $backendName;
$backend['ref'] = "servers.{$backendName}";
$list[$backendName] = $backend;
if (null === ($apiToken = ag($backend, 'webhook.token', null))) {
try {
$apiToken = bin2hex(random_bytes(Config::get('webhook.tokenLength')));
} catch (Throwable $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return self::FAILURE;
}
}
$keys[$apiToken] = 1;
}
$count = count($list);
if (0 === $count) {
$message = sprintf(
$isCustom ? '[-s, --select-backends] did not return any %s backends.' : 'No %s backends were found.',
$type
);
$output->writeln(sprintf('<error>%s</error>', $message));
return self::FAILURE;
}
if (1 === $count) {
$output->writeln(sprintf('<info>We found only one %s backend, therefore, no need to unify.</info>', $type));
return self::SUCCESS;
}
if (count($keys) <= 1) {
$output->writeln(sprintf('<info>[%s] Webhook tokens are already unified.</info>', ucfirst($type)));
return self::SUCCESS;
}
// -- check for server unique identifier before unifying.
foreach ($list as $backendName => $backend) {
$ref = ag($backend, 'ref');
if (null !== Config::get("{$ref}.uuid", null)) {
continue;
}
$client = makeBackend(Config::get($ref), $backendName);
$uuid = $client->getContext()->backendId ?? $client->getIdentifier(true);
if (empty($uuid)) {
$output->writeln(
sprintf('<error>ERROR %s: does not have backend unique id set.</error>', $backendName)
);
$output->writeln('<comment>Please run this command to update backend info.</comment>');
$output->writeln(sprintf(commandContext() . 'config:manage \'%s\' ', $backendName));
return self::FAILURE;
}
Config::save("{$ref}.uuid", $uuid);
}
try {
$apiToken = array_keys($keys ?? [])[0] ?? bin2hex(random_bytes(Config::get('webhook.tokenLength')));
} catch (Throwable $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return self::FAILURE;
}
foreach ($list as $backend) {
$ref = ag($backend, 'ref');
Config::save("{$ref}.webhook.token", $apiToken);
Config::save("{$ref}.webhook.match.uuid", true);
}
if (false === $custom) {
copy($config, $config . '.bak');
}
$stream = new Stream($config, 'w');
$stream->write(Yaml::dump(Config::get('servers', []), 8, 2));
$stream->close();
$output->writeln(
sprintf('<comment>Unified the webhook token of %d %s backends.</comment>', count($list), $type)
);
$output->writeln(sprintf('<info>%s global webhook API key is: %s</info>', ucfirst($type), $apiToken));
return self::SUCCESS;
}
/**
* Completes the input with suggestions based on the "type" argument.
*
* @param CompletionInput $input The completion input object.
* @param CompletionSuggestions $suggestions The completion suggestions object.
*/
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
parent::complete($input, $suggestions);
if ($input->mustSuggestArgumentValuesFor('type')) {
$currentValue = $input->getCompletionValue();
$suggest = [];
foreach (array_keys(Config::get('supported', [])) as $name) {
if (empty($currentValue) || str_starts_with($name, $currentValue)) {
$suggest[] = $name;
}
}
$suggestions->suggestValues($suggest);
}
}
}

View File

@@ -45,9 +45,8 @@ final class ViewCommand extends Command
{
$this->setName(self::ROUTE)
->setDescription('View Backends settings.')
->addOption('select-backends', 's', InputOption::VALUE_OPTIONAL, 'Select backends. comma , seperated.', '')
->addOption('select-backends', 's', InputOption::VALUE_REQUIRED, 'Select backends. comma , seperated.')
->addOption('exclude', null, InputOption::VALUE_NONE, 'Inverse --select-backends logic.')
->addOption('config', 'c', InputOption::VALUE_REQUIRED, 'Use Alternative config file.')
->addOption('expose', 'x', InputOption::VALUE_NONE, 'Expose the secret tokens in the view.')
->addArgument(
'filter',
@@ -99,16 +98,6 @@ final class ViewCommand extends Command
*/
protected function runCommand(InputInterface $input, OutputInterface $output): int
{
// -- Use Custom servers.yaml file.
if (($config = $input->getOption('config'))) {
try {
Config::save('servers', Yaml::parseFile($this->checkCustomBackendsFile($config)));
} catch (RuntimeException $e) {
$output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
return self::FAILURE;
}
}
$selectBackends = (string)$input->getOption('select-backends');
$list = [];
@@ -118,10 +107,9 @@ final class ViewCommand extends Command
foreach (Config::get('servers', []) as $backendName => $backend) {
if ($isCustom && $input->getOption('exclude') === in_array($backendName, $selected)) {
$output->writeln(
sprintf('%s: Ignoring backend as requested by [-s, --select-backends].', $backendName),
OutputInterface::VERBOSITY_VERY_VERBOSE
);
$output->writeln(r('Ignoring backend \'{backend}\' as requested by [-s, --select-backends].', [
'backend' => $backendName
]), OutputInterface::VERBOSITY_VERY_VERBOSE);
continue;
}
@@ -154,7 +142,7 @@ final class ViewCommand extends Command
if ('table' === $mode) {
(new Table($output))->setStyle('box')
->setHeaders(['Backend', 'Filter: ' . (empty($filter) ? 'None' : $filter)]
->setHeaders(['Backend', 'Data (Filter: ' . (empty($filter) ? 'None' : $filter) . ')']
)->setRows($rows)
->render();
} else {