From 8323b870763d9518bfc362c06e01997666bdd5f6 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sun, 30 Sep 2018 09:40:43 +0200 Subject: [PATCH] Ensured required config options cannot be left empty --- .../Plugin/ApplicationConfigCustomizer.php | 12 +++------- .../Plugin/DatabaseConfigCustomizer.php | 7 ++++-- .../Plugin/LanguageConfigCustomizer.php | 6 ++--- .../Plugin/UrlShortenerConfigCustomizer.php | 14 +++++------- .../src/Exception/ExceptionInterface.php | 10 +++++++++ .../MissingRequiredOptionException.php | 15 +++++++++++++ module/Installer/src/Util/AskUtilsTrait.php | 22 +++++++++++++++++++ .../MissingRequiredOptionExceptionTest.php | 19 ++++++++++++++++ 8 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 module/Installer/src/Exception/ExceptionInterface.php create mode 100644 module/Installer/src/Exception/MissingRequiredOptionException.php create mode 100644 module/Installer/src/Util/AskUtilsTrait.php create mode 100644 module/Installer/test/Exception/MissingRequiredOptionExceptionTest.php diff --git a/module/Installer/src/Config/Plugin/ApplicationConfigCustomizer.php b/module/Installer/src/Config/Plugin/ApplicationConfigCustomizer.php index a57a3f78..74c8ac16 100644 --- a/module/Installer/src/Config/Plugin/ApplicationConfigCustomizer.php +++ b/module/Installer/src/Config/Plugin/ApplicationConfigCustomizer.php @@ -19,20 +19,14 @@ class ApplicationConfigCustomizer implements ConfigCustomizerInterface return; } - $validator = function ($value) { - return $value; - }; $appConfig->setApp([ 'SECRET' => $io->ask( - 'Define a secret string that will be used to sign API tokens (leave empty to autogenerate one)', - null, - $validator + 'Define a secret string that will be used to sign API tokens (leave empty to autogenerate one) ' + . '[DEPRECATED. TO BE REMOVED]' ) ?: $this->generateRandomString(32), 'DISABLE_TRACK_PARAM' => $io->ask( 'Provide a parameter name that you will be able to use to disable tracking on specific request to ' - . 'short URLs (leave empty and this feature won\'t be enabled)', - null, - $validator + . 'short URLs (leave empty and this feature won\'t be enabled)' ), ]); } diff --git a/module/Installer/src/Config/Plugin/DatabaseConfigCustomizer.php b/module/Installer/src/Config/Plugin/DatabaseConfigCustomizer.php index c117c32d..c6ada322 100644 --- a/module/Installer/src/Config/Plugin/DatabaseConfigCustomizer.php +++ b/module/Installer/src/Config/Plugin/DatabaseConfigCustomizer.php @@ -4,12 +4,15 @@ declare(strict_types=1); namespace Shlinkio\Shlink\Installer\Config\Plugin; use Shlinkio\Shlink\Installer\Model\CustomizableAppConfig; +use Shlinkio\Shlink\Installer\Util\AskUtilsTrait; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; class DatabaseConfigCustomizer implements ConfigCustomizerInterface { + use AskUtilsTrait; + private const DATABASE_DRIVERS = [ 'MySQL' => 'pdo_mysql', 'PostgreSQL' => 'pdo_pgsql', @@ -59,8 +62,8 @@ class DatabaseConfigCustomizer implements ConfigCustomizerInterface // Ask for connection params if database is not SQLite if ($params['DRIVER'] !== self::DATABASE_DRIVERS['SQLite']) { $params['NAME'] = $io->ask('Database name', 'shlink'); - $params['USER'] = $io->ask('Database username'); - $params['PASSWORD'] = $io->ask('Database password'); + $params['USER'] = $this->askRequired($io, 'username', 'Database username'); + $params['PASSWORD'] = $this->askRequired($io, 'password', 'Database password'); $params['HOST'] = $io->ask('Database host', 'localhost'); $params['PORT'] = $io->ask('Database port', $this->getDefaultDbPort($params['DRIVER'])); } diff --git a/module/Installer/src/Config/Plugin/LanguageConfigCustomizer.php b/module/Installer/src/Config/Plugin/LanguageConfigCustomizer.php index 1a7a2de4..24d57b3c 100644 --- a/module/Installer/src/Config/Plugin/LanguageConfigCustomizer.php +++ b/module/Installer/src/Config/Plugin/LanguageConfigCustomizer.php @@ -19,12 +19,12 @@ class LanguageConfigCustomizer implements ConfigCustomizerInterface } $appConfig->setLanguage([ - 'DEFAULT' => $this->chooseLanguage('Select default language for the application in general', $io), - 'CLI' => $this->chooseLanguage('Select default language for CLI executions', $io), + 'DEFAULT' => $this->chooseLanguage($io, 'Select default language for the application in general'), + 'CLI' => $this->chooseLanguage($io, 'Select default language for CLI executions'), ]); } - private function chooseLanguage(string $message, SymfonyStyle $io): string + private function chooseLanguage(SymfonyStyle $io, string $message): string { return $io->choice($message, self::SUPPORTED_LANGUAGES, self::SUPPORTED_LANGUAGES[0]); } diff --git a/module/Installer/src/Config/Plugin/UrlShortenerConfigCustomizer.php b/module/Installer/src/Config/Plugin/UrlShortenerConfigCustomizer.php index 729ec2f8..a59210d7 100644 --- a/module/Installer/src/Config/Plugin/UrlShortenerConfigCustomizer.php +++ b/module/Installer/src/Config/Plugin/UrlShortenerConfigCustomizer.php @@ -5,11 +5,14 @@ namespace Shlinkio\Shlink\Installer\Config\Plugin; use Shlinkio\Shlink\Core\Service\UrlShortener; use Shlinkio\Shlink\Installer\Model\CustomizableAppConfig; +use Shlinkio\Shlink\Installer\Util\AskUtilsTrait; use Symfony\Component\Console\Style\SymfonyStyle; use function str_shuffle; class UrlShortenerConfigCustomizer implements ConfigCustomizerInterface { + use AskUtilsTrait; + public function process(SymfonyStyle $io, CustomizableAppConfig $appConfig): void { $io->title('URL SHORTENER'); @@ -25,14 +28,9 @@ class UrlShortenerConfigCustomizer implements ConfigCustomizerInterface ['http', 'https'], 'http' ), - 'HOSTNAME' => $io->ask('Hostname for generated URLs'), - 'CHARS' => $io->ask( - 'Character set for generated short codes (leave empty to autogenerate one)', - null, - function ($value) { - return $value; - } - ) ?: str_shuffle(UrlShortener::DEFAULT_CHARS), + 'HOSTNAME' => $this->askRequired($io, 'hostname', 'Hostname for generated URLs'), + 'CHARS' => $io->ask('Character set for generated short codes (leave empty to autogenerate one)') + ?: str_shuffle(UrlShortener::DEFAULT_CHARS), 'VALIDATE_URL' => $io->confirm('Do you want to validate long urls by 200 HTTP status code on response'), ]); } diff --git a/module/Installer/src/Exception/ExceptionInterface.php b/module/Installer/src/Exception/ExceptionInterface.php new file mode 100644 index 00000000..fcca1cc9 --- /dev/null +++ b/module/Installer/src/Exception/ExceptionInterface.php @@ -0,0 +1,10 @@ +ask($question, null, function ($value) use ($optionName) { + if (empty($value)) { + throw MissingRequiredOptionException::fromOption($optionName); + }; + }); + } +} diff --git a/module/Installer/test/Exception/MissingRequiredOptionExceptionTest.php b/module/Installer/test/Exception/MissingRequiredOptionExceptionTest.php new file mode 100644 index 00000000..4fde71ec --- /dev/null +++ b/module/Installer/test/Exception/MissingRequiredOptionExceptionTest.php @@ -0,0 +1,19 @@ +assertEquals('The "foo" is required and can\'t be empty', $e->getMessage()); + } +}