From ac64a5db75fb0fad08d4440c8dcce0347f138609 Mon Sep 17 00:00:00 2001 From: Nabeel S Date: Sat, 10 Apr 2021 17:19:45 -0400 Subject: [PATCH] Migrate all configs into the env.php file #1075 (#1128) * Migrate all configs into the env.php file #1075 * Style fixes * Fix config names in CreateConfig * Fix installer/installer error messages --- .github/scripts/env.php | 2 +- .gitignore | 1 + .htaccess | 2 + Dockerfile | 3 +- app/Console/Commands/CreateConfigs.php | 16 +-- app/Console/Commands/DevInstall.php | 6 +- app/Console/Commands/RewriteConfigs.php | 25 ++++ .../2021_04_10_055245_migrate_configs.php | 21 +++ .../System/InstallerController.php | 24 ++-- app/Services/Installer/ConfigService.php | 123 ++++++++++++++---- config/app.php | 2 +- config/logging.php | 14 +- config/services.php | 4 +- resources/docker/php/Dockerfile | 5 +- resources/stubs/installer/config.stub | 6 +- resources/stubs/installer/env.stub | 45 ++++++- .../system/installer/flash/message.blade.php | 29 +++-- 17 files changed, 247 insertions(+), 81 deletions(-) create mode 100644 app/Console/Commands/RewriteConfigs.php create mode 100644 app/Database/migrations/2021_04_10_055245_migrate_configs.php diff --git a/.github/scripts/env.php b/.github/scripts/env.php index 169c3e15..331fcd92 100644 --- a/.github/scripts/env.php +++ b/.github/scripts/env.php @@ -8,7 +8,7 @@ APP_LOCALE="en" PHPVMS_INSTALLED="true" APP_LOG="daily" -APP_LOG_LEVEL="debug" +LOG_LEVEL="debug" APP_LOG_MAX_FILES="3" DB_CONNECTION="mysql" diff --git a/.gitignore b/.gitignore index 2cd78d74..c9ac68ec 100644 --- a/.gitignore +++ b/.gitignore @@ -74,4 +74,5 @@ error_log .sass-cache .DS_Store /config.php +/config.bak.php /VERSION diff --git a/.htaccess b/.htaccess index cef54daa..5e5e975c 100755 --- a/.htaccess +++ b/.htaccess @@ -28,6 +28,8 @@ RedirectMatch 403 ^/composer.phar RedirectMatch 403 ^/env.php.*?$ RedirectMatch 403 ^/env.php RedirectMatch 403 ^/env.php$ +RedirectMatch 403 ^/config.php$ +RedirectMatch 403 ^/config.bak.php$ RedirectMatch 403 ^/Makefile RedirectMatch 403 ^/package.json RedirectMatch 403 ^/package-lock.json diff --git a/Dockerfile b/Dockerfile index 8460bfb7..824fcd5a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM php:7.4-fpm-alpine WORKDIR /var/www/ -RUN apk add gmp-dev +RUN apk add gmp-dev icu-dev RUN curl --silent --show-error https://getcomposer.org/installer | php # Copy any config files in @@ -12,6 +12,7 @@ RUN ln -sf /dev/stderr /var/log/fpm-error.log RUN docker-php-ext-install \ calendar \ + intl \ pdo_mysql \ gmp \ opcache && \ diff --git a/app/Console/Commands/CreateConfigs.php b/app/Console/Commands/CreateConfigs.php index 3d3a1813..835a9461 100644 --- a/app/Console/Commands/CreateConfigs.php +++ b/app/Console/Commands/CreateConfigs.php @@ -4,9 +4,9 @@ namespace App\Console\Commands; use App; use App\Contracts\Command; +use App\Services\Installer\ConfigService; use App\Services\Installer\SeederService; use DatabaseSeeder; -use Modules\Installer\Services\ConfigService; /** * Create the config files @@ -81,13 +81,13 @@ class CreateConfigs extends Command $this->info('Regenerating the config files'); $cfgSvc->createConfigFiles([ - 'APP_ENV' => 'dev', - 'SITE_NAME' => $this->argument('name'), - 'DB_CONN' => 'mysql', - 'DB_HOST' => $this->argument('db_host'), - 'DB_NAME' => $this->argument('db_name'), - 'DB_USER' => $this->argument('db_user'), - 'DB_PASS' => $this->argument('db_pass'), + 'APP_ENV' => 'dev', + 'SITE_NAME' => $this->argument('name'), + 'DB_CONNECTION' => 'mysql', + 'DB_HOST' => $this->argument('db_host'), + 'DB_DATABASE' => $this->argument('db_name'), + 'DB_USERNAME' => $this->argument('db_user'), + 'DB_PASSWORD' => $this->argument('db_pass'), ]); $this->info('Config files generated!'); diff --git a/app/Console/Commands/DevInstall.php b/app/Console/Commands/DevInstall.php index 39b34e48..6d5d748a 100644 --- a/app/Console/Commands/DevInstall.php +++ b/app/Console/Commands/DevInstall.php @@ -79,9 +79,9 @@ class DevInstall extends Command $this->info('Regenerating the config files'); $cfgSvc->createConfigFiles([ - 'APP_ENV' => 'dev', - 'SITE_NAME' => 'phpvms test', - 'DB_CONN' => 'sqlite', + 'APP_ENV' => 'dev', + 'SITE_NAME' => 'phpvms test', + 'DB_CONNECTION' => 'sqlite', ]); $this->info('Config files generated!'); diff --git a/app/Console/Commands/RewriteConfigs.php b/app/Console/Commands/RewriteConfigs.php new file mode 100644 index 00000000..93729fad --- /dev/null +++ b/app/Console/Commands/RewriteConfigs.php @@ -0,0 +1,25 @@ +rewriteConfigFiles(); + } +} diff --git a/app/Database/migrations/2021_04_10_055245_migrate_configs.php b/app/Database/migrations/2021_04_10_055245_migrate_configs.php new file mode 100644 index 00000000..3d04b9b9 --- /dev/null +++ b/app/Database/migrations/2021_04_10_055245_migrate_configs.php @@ -0,0 +1,21 @@ +rewriteConfigFiles(); + } + + public function down() + { + } +} diff --git a/app/Http/Controllers/System/InstallerController.php b/app/Http/Controllers/System/InstallerController.php index 2a816e10..ea73a25b 100644 --- a/app/Http/Controllers/System/InstallerController.php +++ b/app/Http/Controllers/System/InstallerController.php @@ -203,21 +203,21 @@ class InstallerController extends Controller Log::error('Testing db before writing configs failed'); Log::error($e->getMessage()); - Flash::error($e->getMessage()); + flash()->error($e->getMessage()); return redirect(route('installer.step2'))->withInput(); } // Now write out the env file $attrs = [ - 'SITE_NAME' => $request->post('site_name'), - 'SITE_URL' => $request->post('site_url'), - 'DB_CONN' => $request->post('db_conn'), - 'DB_HOST' => $request->post('db_host'), - 'DB_PORT' => $request->post('db_port'), - 'DB_NAME' => $request->post('db_name'), - 'DB_USER' => $request->post('db_user'), - 'DB_PASS' => $request->post('db_pass'), - 'DB_PREFIX' => $request->post('db_prefix'), + 'SITE_NAME' => $request->post('site_name'), + 'SITE_URL' => $request->post('site_url'), + 'DB_CONNECTION' => $request->post('db_conn'), + 'DB_HOST' => $request->post('db_host'), + 'DB_PORT' => $request->post('db_port'), + 'DB_DATABASE' => $request->post('db_name'), + 'DB_USERNAME' => $request->post('db_user'), + 'DB_PASSWORD' => $request->post('db_pass'), + 'DB_PREFIX' => $request->post('db_prefix'), ]; /* @@ -231,7 +231,7 @@ class InstallerController extends Controller Log::error('Config files failed to write'); Log::error($e->getMessage()); - Flash::error($e->getMessage()); + flash()->error($e->getMessage()); return redirect(route('installer.step2'))->withInput(); } @@ -257,7 +257,7 @@ class InstallerController extends Controller Log::error('Error on db setup: '.$e->getMessage()); //dd($e); $this->envSvc->removeConfigFiles(); - Flash::error($e->getMessage()); + flash()->error($e->getMessage()); return redirect(route('installer.step2'))->withInput(); } diff --git a/app/Services/Installer/ConfigService.php b/app/Services/Installer/ConfigService.php index 541516b5..bbaf8a29 100644 --- a/app/Services/Installer/ConfigService.php +++ b/app/Services/Installer/ConfigService.php @@ -15,34 +15,49 @@ use Symfony\Component\HttpFoundation\File\Exception\FileException; class ConfigService extends Service { + protected static $defaultValues = [ + 'APP_ENV' => 'dev', + 'APP_KEY' => '', + 'APP_DEBUG' => true, + 'APP_LOCALE' => 'en', + 'DEBUG_TOOLBAR' => false, + 'SITE_NAME' => '', + 'SITE_URL' => 'http://phpvms.test', + 'DB_CONNECTION' => '', + 'DB_HOST' => '', + 'DB_PORT' => 3306, + 'DB_DATABASE' => '', + 'DB_USERNAME' => '', + 'DB_PASSWORD' => '', + 'DB_PREFIX' => '', + 'DB_EMULATE_PREPARES' => false, + 'CACHE_DRIVER' => 'array', + 'CACHE_PREFIX' => '', + 'MAIL_DRIVER' => 'smtp', + 'MAIL_HOST' => '', + 'MAIL_PORT' => 587, + 'MAIL_ENCRYPTION' => '', + 'MAIL_USERNAME' => '', + 'MAIL_PASSWORD' => '', + 'MAIL_FROM_NAME' => 'phpVMS Admin', + 'MAIL_FROM_ADDRESS' => 'no-reply@phpvms.net', + ]; + /** - * Create the .env file + * Create the .env file. This is called by an initial install * * @param $attrs * - * @throws \Symfony\Component\HttpFoundation\File\Exception\FileException + * @throws FileException * * @return bool */ public function createConfigFiles($attrs): bool { - $opts = [ - 'APP_ENV' => 'dev', - 'APP_KEY' => $this->createAppKey(), - 'SITE_NAME' => '', - 'SITE_URL' => 'http://phpvms.test', - 'CACHE_PREFIX' => '', - 'DB_CONN' => '', - 'DB_HOST' => '', - 'DB_PORT' => 3306, - 'DB_NAME' => '', - 'DB_USER' => '', - 'DB_PASS' => '', - 'DB_PREFIX' => '', - 'DB_EMULATE_PREPARES' => false, - ]; - - $opts = array_merge($opts, $attrs); + $opts = array_merge(static::$defaultValues, $attrs); + if (empty($opts['APP_KEY'])) { + $opts['APP_KEY'] = $this->createAppKey(); + } $opts = $this->determinePdoOptions($opts); $opts = $this->configCacheDriver($opts); @@ -53,6 +68,61 @@ class ConfigService extends Service return true; } + /** + * Rewrite the config files - this means mapping the values that are currently + * loaded in the config and rewriting them into the env.php file, and then renaming + * the config.php files to config.bak.php + * + * This is called from the migrations which removes the old config.php file + */ + public function rewriteConfigFiles() + { + /*$cfg_file = App::environmentPath().'/config.php'; + if (!file_exists($cfg_file)) { + Log::info('Main config.php file is missing, migration already completed'); + return; + }*/ + + $db_opts = config('database.connections.mysql.options'); + $emulate_prepares = $db_opts[PDO::ATTR_EMULATE_PREPARES] ? 'true' : 'false'; + + $opts = array_merge(static::$defaultValues, [ + 'APP_ENV' => config('app.env'), + 'APP_KEY' => config('app.key'), + 'APP_DEBUG' => config('app.debug') ? 'true' : 'false', + 'APP_LOCALE' => config('app.locale'), + 'DEBUG_TOOLBAR' => config('app.debug_toolbar') ? 'true' : 'false', + 'SITE_NAME' => config('app.name'), + 'SITE_URL' => config('app.url'), + 'DB_CONNECTION' => config('database.default'), + 'DB_HOST' => config('database.connections.mysql.host'), + 'DB_PORT' => config('database.connections.mysql.port'), + 'DB_DATABASE' => config('database.connections.mysql.database'), + 'DB_USERNAME' => config('database.connections.mysql.username'), + 'DB_PASSWORD' => config('database.connections.mysql.password'), + 'DB_PREFIX' => config('database.connections.mysql.prefix'), + 'DB_EMULATE_PREPARES' => $emulate_prepares, + 'CACHE_DRIVER' => config('cache.default'), + 'CACHE_PREFIX' => config('cache.prefix'), + 'MAIL_DRIVER' => config('mail.default'), + 'MAIL_HOST' => config('mail.mailers.smtp.host'), + 'MAIL_PORT' => config('mail.mailers.smtp.port'), + 'MAIL_ENCRYPTION' => config('mail.mailers.smtp.encryption'), + 'MAIL_USERNAME' => config('mail.mailers.smtp.username'), + 'MAIL_PASSWORD' => config('mail.mailers.smtp.password'), + 'MAIL_FROM_NAME' => config('mail.from.name'), + 'MAIL_FROM_ADDRESS' => config('mail.from.address'), + ]); + + $this->writeConfigFiles($opts); + + // Rename the old config file + $cfg_file = App::environmentPath().'/config.php'; + if (file_exists($cfg_file)) { + rename($cfg_file, App::environmentPath().'/config.bak.php'); + } + } + /** * Update the environment file and update certain keys/values * @@ -97,7 +167,7 @@ class ConfigService extends Service */ protected function createAppKey(): string { - return base64_encode(Encrypter::generateKey(config('app.cipher'))); + return 'base64:'.base64_encode(Encrypter::generateKey(config('app.cipher'))); } /** @@ -110,14 +180,14 @@ class ConfigService extends Service */ protected function determinePdoOptions($opts) { - if ($opts['DB_CONN'] !== 'mysql') { + if ($opts['DB_CONNECTION'] !== 'mysql') { return $opts; } $dsn = "mysql:host=$opts[DB_HOST];port=$opts[DB_PORT];"; Log::info('Connection string: '.$dsn); - $conn = new PDO($dsn, $opts['DB_USER'], $opts['DB_PASS']); + $conn = new PDO($dsn, $opts['DB_USERNAME'], $opts['DB_PASSWORD']); $version = strtolower($conn->getAttribute(PDO::ATTR_SERVER_VERSION)); Log::info('Detected DB Version: '.$version); @@ -171,7 +241,7 @@ class ConfigService extends Service { // If we're setting up a database, then also setup // the default queue driver to use the database - if ($opts['DB_CONN'] === 'mysql' || $opts['DB_CONN'] === 'postgres') { + if ($opts['DB_CONNECTION'] === 'mysql' || $opts['DB_CONNECTION'] === 'postgres') { $opts['QUEUE_DRIVER'] = 'database'; } else { $opts['QUEUE_DRIVER'] = 'sync'; @@ -210,14 +280,13 @@ class ConfigService extends Service * * @param $opts * - * @throws \Symfony\Component\HttpFoundation\File\Exception\FileException + * @throws FileException */ protected function writeConfigFiles($opts) { Stub::setBasePath(resource_path('/stubs/installer')); $env_file = App::environmentFilePath(); - if (file_exists($env_file) && !is_writable($env_file)) { Log::error('Permissions on existing env.php is not writable'); @@ -239,7 +308,7 @@ class ConfigService extends Service * Next write out the config file. If there's an error here, * then throw an exception but delete the env file first */ - try { + /*try { $stub = new Stub('/config.stub', $opts); $stub->render(); $stub->saveTo(App::environmentPath(), 'config.php'); @@ -247,6 +316,6 @@ class ConfigService extends Service unlink(App::environmentPath().'/'.App::environmentFile()); throw new FileException('Couldn\'t write config.php. ('.$e.')'); - } + }*/ } } diff --git a/config/app.php b/config/app.php index 7fe7c3f3..8e264b64 100755 --- a/config/app.php +++ b/config/app.php @@ -15,7 +15,7 @@ return [ 'debug' => env('APP_DEBUG', true), 'url' => env('APP_URL', ''), 'version' => '7.0.0', - 'debug_toolbar' => false, + 'debug_toolbar' => env('DEBUG_TOOLBAR', false), 'locale' => env('APP_LOCALE', 'en'), 'fallback_locale' => 'en', diff --git a/config/logging.php b/config/logging.php index a423e38c..ab9c63b3 100644 --- a/config/logging.php +++ b/config/logging.php @@ -1,5 +1,7 @@ [ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), - 'level' => 'debug', + 'level' => env('LOG_LEVEL', 'debug'), ], 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), - 'level' => 'debug', + 'level' => env('LOG_LEVEL', 'debug'), 'days' => 3, ], 'cron_rotating' => [ 'driver' => 'daily', 'path' => storage_path('logs/cron.log'), - 'level' => 'debug', + 'level' => env('LOG_LEVEL', 'debug'), 'days' => 3, ], 'slack' => [ @@ -67,15 +69,15 @@ return [ ], 'stdout' => [ 'driver' => 'custom', - 'via' => \App\Console\Logger::class, + 'via' => Logger::class, ], 'syslog' => [ 'driver' => 'syslog', - 'level' => 'debug', + 'level' => env('LOG_LEVEL', 'debug'), ], 'errorlog' => [ 'driver' => 'errorlog', - 'level' => 'debug', + 'level' => env('LOG_LEVEL', 'debug'), ], ], ]; diff --git a/config/services.php b/config/services.php index fe795b74..30e7ebef 100755 --- a/config/services.php +++ b/config/services.php @@ -1,5 +1,7 @@ [ - 'model' => App\User::class, + 'model' => User::class, 'key' => env('STRIPE_KEY'), 'secret' => env('STRIPE_SECRET'), ], diff --git a/resources/docker/php/Dockerfile b/resources/docker/php/Dockerfile index 7fa5d10e..05651f1e 100644 --- a/resources/docker/php/Dockerfile +++ b/resources/docker/php/Dockerfile @@ -10,6 +10,7 @@ RUN ln -sf /dev/stderr /var/log/fpm-error.log RUN docker-php-ext-install \ bcmath \ calendar \ - pdo_mysql \ gmp \ - opcache + intl \ + opcache \ + pdo_mysql diff --git a/resources/stubs/installer/config.stub b/resources/stubs/installer/config.stub index e60e0107..1d96bc71 100644 --- a/resources/stubs/installer/config.stub +++ b/resources/stubs/installer/config.stub @@ -60,9 +60,9 @@ return [ 'mysql' => [ 'host' => env('DB_HOST', '$DB_HOST$'), 'port' => $DB_PORT$, - 'database' => '$DB_NAME$', - 'username' => '$DB_USER$', - 'password' => '$DB_PASS$', + 'database' => '$DB_DATABASE$', + 'username' => '$DB_USERNAME$', + 'password' => '$DB_PASSWORD$', 'prefix' => '$DB_PREFIX$', 'prefix_indexes' => true, ], diff --git a/resources/stubs/installer/env.stub b/resources/stubs/installer/env.stub index 2a481fae..de0b89db 100644 --- a/resources/stubs/installer/env.stub +++ b/resources/stubs/installer/env.stub @@ -1,8 +1,49 @@ -# # THIS FILE MUST BE KEPT SECRET! IT IS BLOCKED IN THE HTACCESS FILE # HOWEVER, THIS DIRECTORY SHOULDN'T BE EXPOSED TO THE PUBLIC AT ALL # SEE THE DOCS FOR PROPER (SECURE) INSTALLATION: # https://docs.phpvms.net/installation/uploading # +# This is the place to edit your configuration. To change a config that's +# not present here, you need to either edit the file/config in the config +# folder, or change it to read the value from the environment. Something like: +# +# 'some_key' = env('ENVIRONMENT_VARIABLE_KEY_ADDED_BELOW', 'default value') +# +# Various other settings in the configs also read from some environment variables +# by default. You can override those here + +APP_KEY='$APP_KEY$' +SITE_NAME='$SITE_NAME$' +SITE_URL='$SITE_URL$' +APP_ENV=$APP_ENV$ +APP_LOCALE=$APP_LOCALE$ +LOG_LEVEL=debug +APP_DEBUG=$APP_DEBUG$ +DEBUG_TOOLBAR=$DEBUG_TOOLBAR$ + +# DATABASE SETTINGS +DB_CONNECTION=$DB_CONNECTION$ +DB_HOST='$DB_HOST$' +DB_PORT=$DB_PORT$ +DB_DATABASE='$DB_DATABASE$' +DB_USERNAME='$DB_USERNAME$' +DB_PASSWORD='$DB_PASSWORD$' +DB_PREFIX='$DB_PREFIX$' +DB_EMULATE_PREPARES=$DB_EMULATE_PREPARES$ +DB_SOCKET= + +# CACHE SETTINGS +CACHE_DRIVER=$CACHE_DRIVER$ +CACHE_PREFIX=$CACHE_PREFIX$ -APP_KEY=base64:$APP_KEY$ +# EMAIL SETTINGS +# Look at the available mail configs in config/mail.php +# Also refer to the Laravel docs here: https://laravel.com/docs/8.x/mail +MAIL_DRIVER=$MAIL_DRIVER$ +MAIL_FROM_NAME='$MAIL_FROM_NAME$' +MAIL_FROM_ADDRESS='$MAIL_FROM_ADDRESS$' +MAIL_HOST=$MAIL_HOST$ +MAIL_PORT=$MAIL_PORT$ +MAIL_ENCRYPTION=$MAIL_ENCRYPTION$ +MAIL_USERNAME=$MAIL_USERNAME$ +MAIL_PASSWORD=$MAIL_PASSWORD$ diff --git a/resources/views/system/installer/flash/message.blade.php b/resources/views/system/installer/flash/message.blade.php index 9e47c4fd..c4b65e99 100644 --- a/resources/views/system/installer/flash/message.blade.php +++ b/resources/views/system/installer/flash/message.blade.php @@ -1,19 +1,20 @@ -@if (session()->has('flash_notification.message')) - @if (session()->has('flash_notification.overlay')) - @include('flash::modal', [ - 'modalClass' => 'flash-modal', - 'title' => session('flash_notification.title'), - 'body' => session('flash_notification.message') - ]) +@foreach (collect(session('flash_notification', collect()))->toArray() as $message) + @if (is_string($message)) +
{!! $message !!}
@else -
- @if(session()->has('flash_notification.important')) - + @endif -@endif +@endforeach + +{{ session()->forget('flash_notification') }}