From 277a5f2d330fc6c5aa13db584cd57e7f16c29358 Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Thu, 14 Dec 2017 16:38:29 -0600 Subject: [PATCH] Rewrite installer without 3rd party installer lib. --- .env.dev.example | 6 + .env.prod.example | 4 +- .gitignore | 1 + app/Console/Commands/CreateDatabase.php | 14 +- config/database.php | 19 +-- config/installer.php | 142 ------------------ modules/Installer/Config/config.php | 20 ++- .../Http/Controllers/InstallerController.php | 117 ++++++++++++++- modules/Installer/Http/Routes/install.php | 8 +- .../Installer/Resources/views/app.blade.php | 15 +- .../Resources/views/flash/message.blade.php | 8 + .../Resources/views/index-start.blade.php | 11 ++ .../Installer/Resources/views/index.blade.php | 6 - .../views/steps/step1-requirements.blade.php | 43 ++++++ .../Resources/views/steps/step2-db.blade.php | 116 ++++++++++++++ .../Resources/views/stubs/env.blade.php | 34 +++++ .../Installer/Services/DatabaseService.php | 50 ++++++ .../Installer/Services/EnvironmentService.php | 52 +++++++ .../Services/RequirementsService.php | 43 ++++++ resources/views/layouts/default/app.blade.php | 3 +- .../layouts/default/flash/message.blade.php | 24 +++ .../layouts/default/flash/modal.blade.php | 19 +++ 22 files changed, 581 insertions(+), 174 deletions(-) delete mode 100644 config/installer.php create mode 100644 modules/Installer/Resources/views/flash/message.blade.php create mode 100644 modules/Installer/Resources/views/index-start.blade.php delete mode 100644 modules/Installer/Resources/views/index.blade.php create mode 100644 modules/Installer/Resources/views/steps/step1-requirements.blade.php create mode 100644 modules/Installer/Resources/views/steps/step2-db.blade.php create mode 100644 modules/Installer/Resources/views/stubs/env.blade.php create mode 100644 modules/Installer/Services/DatabaseService.php create mode 100644 modules/Installer/Services/EnvironmentService.php create mode 100644 modules/Installer/Services/RequirementsService.php create mode 100644 resources/views/layouts/default/flash/message.blade.php create mode 100644 resources/views/layouts/default/flash/modal.blade.php diff --git a/.env.dev.example b/.env.dev.example index 403ac056..68cef183 100644 --- a/.env.dev.example +++ b/.env.dev.example @@ -9,6 +9,12 @@ APP_LOG_LEVEL=debug APP_LOG_MAX_FILES=7 DB_CONNECTION=sqlite +DB_HOST= +DB_PORT= +DB_DATABASE= +DB_USERNAME= +DB_PASSWORD= +DB_PREFIX= CACHE_DRIVER=array CACHE_PREFIX= diff --git a/.env.prod.example b/.env.prod.example index dceb6909..e08d7907 100644 --- a/.env.prod.example +++ b/.env.prod.example @@ -4,11 +4,11 @@ APP_DEBUG=false APP_LOG_LEVEL=info APP_URL=http://localhost -DB_CONNECTION=travis +DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=phpvms -DB_USERNAME=root +DB_USERNAME= DB_PASSWORD= CACHE_DRIVER=array diff --git a/.gitignore b/.gitignore index 1dcde42b..92a99c9b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ storage/*.sqlite .env.php .env .env.php +.env.generated .vagrant #Homestead.yaml Homestead.json diff --git a/app/Console/Commands/CreateDatabase.php b/app/Console/Commands/CreateDatabase.php index 9030ab82..75422247 100644 --- a/app/Console/Commands/CreateDatabase.php +++ b/app/Console/Commands/CreateDatabase.php @@ -103,6 +103,11 @@ class CreateDatabase extends Command } } + protected function create_postgres($dbkey) + { + $this->error('Not supported yet!'); + } + /** * Execute the console command. * @@ -123,8 +128,15 @@ class CreateDatabase extends Command if (config($dbkey . 'driver') === 'mysql') { $this->create_mysql($dbkey); - } elseif (config($dbkey . 'driver') === 'sqlite') { + } + + elseif (config($dbkey . 'driver') === 'sqlite') { $this->create_sqlite($dbkey); } + + // TODO: Eventually + elseif (config($dbkey . 'driver') === 'postgres') { + $this->create_postgres($dbkey); + } } } diff --git a/config/database.php b/config/database.php index 85e4731e..a8e2b538 100755 --- a/config/database.php +++ b/config/database.php @@ -1,9 +1,8 @@ PDO::FETCH_ASSOC, - 'default' => env('DB_CONNECTION', 'local'), + 'default' => env('DB_CONNECTION', 'sqlite'), 'connections' => [ 'mysql' => [ 'driver' => 'mysql', @@ -12,23 +11,17 @@ return [ 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), - 'unix_socket' => env('DB_SOCKET', ''), + //'unix_socket' => env('DB_SOCKET', ''), + 'prefix' => env('DB_PREFIX', ''), 'timezone' => '+00:00', 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', - 'prefix' => '', - 'strict' => true, + 'strict' => false, 'engine' => null, ], 'sqlite' => [ 'driver' => 'sqlite', - 'database' => env('DB_DATABASE', storage_path('db.sqlite')), - 'timezone' => '+00:00', - 'prefix' => '', - ], - 'local' => [ - 'driver' => 'sqlite', - 'database' => storage_path('local.sqlite'), + 'database' => storage_path('db.sqlite'), 'timezone' => '+00:00', 'prefix' => '', ], @@ -54,7 +47,7 @@ return [ 'host' => env('REDIS_HOST', 'localhost'), 'password' => env('REDIS_PASSWORD', null), 'port' => env('REDIS_PORT', 6379), - 'database' => 0, + 'database' => env('REDIS_DATABASE', 1), ], ] ]; diff --git a/config/installer.php b/config/installer.php deleted file mode 100644 index 4cde564f..00000000 --- a/config/installer.php +++ /dev/null @@ -1,142 +0,0 @@ - [ - 'minPhpVersion' => '7.0.0' - ], - 'requirements' => [ - 'php' => [ - 'openssl', - 'pdo', - 'mbstring', - 'tokenizer', - 'JSON', - 'cURL', - ], - 'apache' => [ - 'mod_rewrite', - ], - ], - - /* - |-------------------------------------------------------------------------- - | Folders Permissions - |-------------------------------------------------------------------------- - | - | This is the default Laravel folders permissions, if your application - | requires more permissions just add them to the array list bellow. - | - */ - 'permissions' => [ - 'storage/framework/' => '755', - 'storage/logs/' => '755', - 'bootstrap/cache/' => '755' - ], - - /* - |-------------------------------------------------------------------------- - | Environment Form Wizard Validation Rules & Messages - |-------------------------------------------------------------------------- - | - | This are the default form vield validation rules. Available Rules: - | https://laravel.com/docs/5.4/validation#available-validation-rules - | - */ - 'environment' => [ - 'form' => [ - 'rules' => [ - 'app_name' => 'required|string|max:50', - 'environment' => 'required|string|max:50', - 'environment_custom' => 'required_if:environment,other|max:50', - 'app_debug' => [ - 'required|in:true,false', - //Rule::in(['true', 'false']), - ], - 'app_log_level' => 'required|string|max:50', - 'app_url' => 'required|url', - 'database_connection' => 'required|string|max:50', - 'database_hostname' => 'string|max:50', - 'database_port' => 'numeric', - 'database_name' => 'string|max:50', - 'database_username' => 'string|max:50', - 'database_password' => 'string|max:50', - 'broadcast_driver' => 'string|max:50', - 'cache_driver' => 'string|max:50', - 'session_driver' => 'string|max:50', - 'queue_driver' => 'string|max:50', - 'redis_hostname' => 'string|max:50', - 'redis_password' => 'string|max:50', - 'redis_port' => 'numeric', - 'mail_driver' => 'string|max:50', - 'mail_host' => 'string|max:50', - 'mail_port' => 'string|max:50', - 'mail_username' => 'string|max:50', - 'mail_password' => 'string|max:50', - 'mail_encryption' => 'string|max:50', - /*'pusher_app_id' => 'max:50', - 'pusher_app_key' => 'max:50', - 'pusher_app_secret' => 'max:50',*/ - ], - ], - ], - - /* - |-------------------------------------------------------------------------- - | Installed Middlware Options - |-------------------------------------------------------------------------- - | Different available status switch configuration for the - | canInstall middleware located in `canInstall.php`. - | - */ - 'installed' => [ - 'redirectOptions' => [ - 'route' => [ - 'name' => 'welcome', - 'data' => [], - ], - 'abort' => [ - 'type' => '404', - ], - 'dump' => [ - 'data' => 'Dumping a not found message.', - ] - ], - ], - - /* - |-------------------------------------------------------------------------- - | Selected Installed Middlware Option - |-------------------------------------------------------------------------- - | The selected option fo what happens when an installer intance has been - | Default output is to `/resources/views/error/404.blade.php` if none. - | The available middleware options include: - | route, abort, dump, 404, default, '' - | - */ - 'installedAlreadyAction' => '', - - /* - |-------------------------------------------------------------------------- - | Updater Enabled - |-------------------------------------------------------------------------- - | Can the application run the '/update' route with the migrations. - | The default option is set to False if none is present. - | Boolean value - | - */ - 'updaterEnabled' => 'true', - -]; diff --git a/modules/Installer/Config/config.php b/modules/Installer/Config/config.php index 0a0b66dc..6eac51bf 100644 --- a/modules/Installer/Config/config.php +++ b/modules/Installer/Config/config.php @@ -1,5 +1,23 @@ 'Installer' + 'php' => [ + 'version' => '7.0.0' + ], + 'extensions' => [ + 'openssl', + 'pdo', + 'mbstring', + 'tokenizer', + 'JSON', + 'cURL', + ], + + 'permissions' => [ + 'storage/framework/' => 'writeable', + 'storage/logs/' => 'writeable', + 'bootstrap/cache/' => 'writable' + ], ]; diff --git a/modules/Installer/Http/Controllers/InstallerController.php b/modules/Installer/Http/Controllers/InstallerController.php index e6620f44..c8a9abd0 100644 --- a/modules/Installer/Http/Controllers/InstallerController.php +++ b/modules/Installer/Http/Controllers/InstallerController.php @@ -2,18 +2,131 @@ namespace Modules\Installer\Http\Controllers; -use App\Http\Controllers\AppBaseController; +use Log; use Illuminate\Http\Request; +use App\Http\Controllers\AppBaseController; + +use Modules\Installer\Services\DatabaseService; +use Modules\Installer\Services\EnvironmentService; +use Modules\Installer\Services\RequirementsService; + class InstallerController extends AppBaseController { + protected $dbService, $envService, $reqService; + + public function __construct( + DatabaseService $dbService, + EnvironmentService $envService, + RequirementsService $reqService + ) { + $this->dbService = $dbService; + $this->envService = $envService; + $this->reqService = $reqService; + } /** * Display a listing of the resource. */ public function index() { - return view('installer::index'); + return view('installer::index-start'); } + /** + * Check the database connection + */ + public function dbtest(Request $request) + { + $status = 'success'; # success|warn|danger + $message = 'Database connection looks good!'; + + try { + $this->dbService->checkDbConnection( + $request->input('db_conn'), + $request->input('db_host'), + $request->input('db_port'), + $request->input('db_name'), + $request->input('db_user'), + $request->input('db_pass') + ); + } catch (\Exception $e) { + $status = 'danger'; + $message = 'Failed! ' . $e->getMessage(); + } + + return view('installer::flash/message', [ + 'status' => $status, + 'message' => $message, + ]); + } + + /** + * Step 1. Check the modules and permissions + */ + public function step1(Request $request) + { + $passed = true; + $php_version = $this->reqService->checkPHPVersion(); + if($php_version['passed'] === false) { + $passed = false; + } + + $extensions = $this->reqService->checkExtensions(); + foreach ($extensions as $ext) { + if($ext['passed'] === false) { + $passed = false; + } + } + + return view('installer::steps/step1-requirements', [ + 'php' => $php_version, + 'extensions' => $extensions, + 'passed' => $passed, + ]); + } + + /** + * Step 2. Database Setup + */ + public function step2(Request $request) + { + $db_types = ['mysql' => 'mysql', 'sqlite' => 'sqlite']; + return view('installer::steps/step2-db', [ + 'db_types' => $db_types, + ]); + } + + /** + * Step 2a. Do the config and setup + */ + public function dbsetup(Request $request) + { + $log = []; + + Log::info('DB Setup', $request->toArray()); + + $log[] = 'Creating environment file'; + $this->envService->createEnvFile( + $request->input('db_conn'), + $request->input('db_host'), + $request->input('db_port'), + $request->input('db_name'), + $request->input('db_user'), + $request->input('db_pass') + ); + + $log[] = 'Creating database'; + $this->dbService->setupDB(); + + return redirect('/'); + } + + /** + * Step 3. Setup the admin user and initial settings + */ + public function step3(Request $request) + { + + } } diff --git a/modules/Installer/Http/Routes/install.php b/modules/Installer/Http/Routes/install.php index 5cc3acb5..fce93602 100644 --- a/modules/Installer/Http/Routes/install.php +++ b/modules/Installer/Http/Routes/install.php @@ -1,3 +1,9 @@ name('index'); +Route::get('/step1', 'InstallerController@step1')->name('step1'); +Route::get('/step2', 'InstallerController@step2')->name('step2'); +Route::get('/step3', 'InstallerController@step3')->name('step3'); + +Route::post('/dbtest', 'InstallerController@dbtest')->name('dbtest'); +Route::post('/dbsetup', 'InstallerController@dbsetup')->name('dbsetup'); diff --git a/modules/Installer/Resources/views/app.blade.php b/modules/Installer/Resources/views/app.blade.php index 83a865fd..9efbb93d 100644 --- a/modules/Installer/Resources/views/app.blade.php +++ b/modules/Installer/Resources/views/app.blade.php @@ -6,7 +6,7 @@ - phpvms installer + @yield('title') - installer @@ -39,15 +39,22 @@

- +
-
- @yield('content') +
+
+
+ @include('flash::message') + @yield('content') +
+
diff --git a/modules/Installer/Resources/views/flash/message.blade.php b/modules/Installer/Resources/views/flash/message.blade.php new file mode 100644 index 00000000..6834618f --- /dev/null +++ b/modules/Installer/Resources/views/flash/message.blade.php @@ -0,0 +1,8 @@ + diff --git a/modules/Installer/Resources/views/index-start.blade.php b/modules/Installer/Resources/views/index-start.blade.php new file mode 100644 index 00000000..0afcd42e --- /dev/null +++ b/modules/Installer/Resources/views/index-start.blade.php @@ -0,0 +1,11 @@ +@extends('installer::app') + +@section('content') +

phpvms installer

+

Press continue to start

+ {!! Form::open(['route' => 'installer.step1', 'method' => 'post']) !!} +

+ {!! Form::submit('Start >>', ['class' => 'btn btn-success']) !!} +

+ {!! Form::close() !!} +@endsection diff --git a/modules/Installer/Resources/views/index.blade.php b/modules/Installer/Resources/views/index.blade.php deleted file mode 100644 index 366679b6..00000000 --- a/modules/Installer/Resources/views/index.blade.php +++ /dev/null @@ -1,6 +0,0 @@ -@extends('installer::app') - -@section('content') -

phpvms installer

-

This view is loaded from module: {!! config('installer.name') !!}

-@endsection diff --git a/modules/Installer/Resources/views/steps/step1-requirements.blade.php b/modules/Installer/Resources/views/steps/step1-requirements.blade.php new file mode 100644 index 00000000..093f9592 --- /dev/null +++ b/modules/Installer/Resources/views/steps/step1-requirements.blade.php @@ -0,0 +1,43 @@ +@extends('installer::app') +@section('title', 'Requirements Check') +@section('content') +
+ {!! Form::open(['route' => 'installer.step2', 'method' => 'GET']) !!} + + + + + + + + + @foreach($extensions as $ext) + + + + + @endforeach +

php version

PHP Version: {!! $php['version'] !!} + @if($php['passed'] === true) + OK! + @else + Failed! + @endif +

php extensions

{!! $ext['ext'] !!} + @if($ext['passed'] === true) + OK! + @else + Failed! + @endif +
+ @if($passed === true) +

+ {!! Form::submit('Database Setup >>', ['class' => 'btn btn-success']) !!} +

+ @endif + {{--{!! $php_version !!} + {!! $extensions !!} + {!! $passed !!}--}} + {!! Form::close() !!} +
+@endsection diff --git a/modules/Installer/Resources/views/steps/step2-db.blade.php b/modules/Installer/Resources/views/steps/step2-db.blade.php new file mode 100644 index 00000000..c2c9fab2 --- /dev/null +++ b/modules/Installer/Resources/views/steps/step2-db.blade.php @@ -0,0 +1,116 @@ +@extends('installer::app') +@section('title', 'Database Setup') +@section('content') +
+ {!! Form::open(['route' => 'installer.dbsetup', 'method' => 'POST']) !!} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Select Database Type +
+ {!! Form::select('db_conn', $db_types, null, ['class' => 'form-control', 'id' => 'db_conn']) !!} +
+
Database Host +
+ {!! Form::input('text', 'db_host', null, ['class' => 'form-control']) !!} +
+
Database Port +
+ {!! Form::input('text', 'db_port', '3307', ['class' => 'form-control']) !!} +
+
Database Name +
+ {!! Form::input('text', 'db_name', 'phpvms', ['class' => 'form-control']) !!} +
+
Database User +
+ {!! Form::input('text', 'db_user', null, ['class' => 'form-control']) !!} +
+
Database Password +
+ {!! Form::input('text', 'db_pass', null, ['class' => 'form-control']) !!} +
+
+ {!! Form::submit('Test Database Credentials', ['class' => 'btn btn-info', 'id' => 'dbtest_button']) !!} +
+
+

+ {!! Form::submit('Complete Setup >>', ['class' => 'btn btn-success']) !!} +

+ {!! Form::close() !!} +
+@endsection + +@section('scripts') + +@endsection diff --git a/modules/Installer/Resources/views/stubs/env.blade.php b/modules/Installer/Resources/views/stubs/env.blade.php new file mode 100644 index 00000000..7abe523a --- /dev/null +++ b/modules/Installer/Resources/views/stubs/env.blade.php @@ -0,0 +1,34 @@ +# +# Before you go live, remember to change the APP_ENV to production +# and APP_DEBUG to false +# + +APP_ENV=dev +APP_KEY=base64:{!! $app_key !!} +APP_DEBUG=true +APP_LOCALE=en + +APP_LOG=daily +APP_LOG_LEVEL=debug +APP_LOG_MAX_FILES=3 + +APP_URL=http://localhost + +DB_CONNECTION={!! $db_conn !!} +DB_HOST={!! $db_host !!} +DB_PORT={!! $db_port !!} +DB_DATABASE={!! $db_name !!} +DB_USERNAME={!! $db_user !!} +DB_PASSWORD={!! $db_pass !!} +DB_PREFIX= + +CACHE_DRIVER=array +CACHE_PREFIX= + +REDIS_HOST=localhost +REDIS_PASSWORD= +REDIS_PORT=6379 +REDIS_DATABASE=1 + +SESSION_DRIVER=array +QUEUE_DRIVER=sync diff --git a/modules/Installer/Services/DatabaseService.php b/modules/Installer/Services/DatabaseService.php new file mode 100644 index 00000000..4c4c0df6 --- /dev/null +++ b/modules/Installer/Services/DatabaseService.php @@ -0,0 +1,50 @@ + $type, + 'db_host' => $host, + 'db_port' => $port, + 'db_name' => $name, + 'db_user' => $user, + 'db_pass' => $pass, + ]; + + $env_opts['app_key'] = base64_encode(Encrypter::generateKey(config('app.cipher'))); + + $this->writeEnvFile($env_opts); + return true; + } + + /** + * Get the template file name and write it out + */ + protected function writeEnvFile($env_opts) + { + $app = app(); + $env_file = $app->environmentFilePath(); + + # TODO: Remove this post-testing + $env_file .= '.generated'; + + $env_contents = view('installer::stubs/env', $env_opts); + Log::info($env_contents); + + $fp = fopen($env_file, 'w'); + fwrite($fp, $env_contents); + fclose($fp); + } + +} diff --git a/modules/Installer/Services/RequirementsService.php b/modules/Installer/Services/RequirementsService.php new file mode 100644 index 00000000..9ba34e2f --- /dev/null +++ b/modules/Installer/Services/RequirementsService.php @@ -0,0 +1,43 @@ += 0) { + $passed = true; + } + + return ['version' => PHP_VERSION, 'passed' => $passed]; + } + + /** + * Make sure the minimal extensions required are loaded + * @return array + */ + public function checkExtensions(): array + { + $extensions = []; + foreach(config('installer.extensions') as $ext) { + $pass = true; + if(!extension_loaded($ext)) { + $pass = false; + } + + $extensions[] = [ + 'ext' => $ext, + 'passed' => $pass, + ]; + } + + return $extensions; + } +} diff --git a/resources/views/layouts/default/app.blade.php b/resources/views/layouts/default/app.blade.php index 2d1804fe..8930ee1e 100644 --- a/resources/views/layouts/default/app.blade.php +++ b/resources/views/layouts/default/app.blade.php @@ -42,8 +42,7 @@

-