installer refactoring

This commit is contained in:
denisdulici 2018-02-20 17:05:58 +03:00
parent 3928adccfe
commit e387548a37
7 changed files with 293 additions and 296 deletions

View File

@ -1,238 +0,0 @@
<?php
namespace App\Console\Commands;
use Artisan;
use Session;
use App\Utilities\AppConfigurer;
use Illuminate\Console\Command;
class ConfigureApp extends Command {
const CMD_SUCCESS = 0;
const CMD_ERROR = 1;
const OPT_DB_HOST = 'db-host';
const OPT_DB_PORT = 'db-port';
const OPT_DB_NAME = 'db-name';
const OPT_DB_USERNAME = 'db-username';
const OPT_DB_PASSWORD = 'db-password';
const OPT_COMPANY_NAME = 'company-name';
const OPT_COMPANY_EMAIL = 'company-email';
const OPT_ADMIN_EMAIL = 'admin-email';
const OPT_ADMIN_PASSWORD = 'admin-password';
const OPT_LOCALE = 'locale';
const OPT_NO_INTERACTION = 'no-interaction';
var $dbHost;
var $dbPort;
var $dbName;
var $dbUsername;
var $dbPassword;
var $companyName;
var $companyEmail;
var $adminEmail;
var $adminPassword;
var $locale;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:configure
{--db-host= : Database host}
{--db-port=3306 : Port of the database host}
{--db-name= : Name of the database}
{--db-username= : Username to use to access the database}
{--db-password= : Password to use to access the database}
{--company-name= : Name of the company managed buy the app}
{--company-email= : email used to contact the company}
{--admin-email= : Admin user email}
{--admin-password= : Admin user password}
{--locale=en-GB : Language used in the app}
';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Allows to configure the app directly through CLI';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct() {
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle() {
$missingOptions = $this->checkOptions();
if ( ! empty( $missingOptions ) && $this->option( self::OPT_NO_INTERACTION ) ) {
$this->line( '❌ Some options are missing and --no-interaction is present. Please run the following command for more informations :' );
$this->line( '❌ php artisan help app:configure' );
$this->line( '❌ Missing options are : ' . join( ', ', $missingOptions ) );
return self::CMD_ERROR;
}
$this->line( 'Setting locale ' . $this->locale );
Session::put( self::OPT_LOCALE, $this->locale );
$this->prompt();
$this->line( 'Configuring database' );
if ( ! $this->configureDatabase() ) {
return self::CMD_ERROR;
}
$this->line( 'Configuring company' );
AppConfigurer::createCompany( $this->companyName, $this->companyEmail, $this->locale );
$this->line( 'Creating Admin user' );
AppConfigurer::createUser( $this->adminEmail, $this->adminPassword, $this->locale );
$this->line( 'Applying the final touches' );
AppConfigurer::finalTouches();
return self::CMD_SUCCESS;
}
/**
* Check that all options are presents. otherwise returns an array of the missing options
*/
private function checkOptions() {
$missingOptions = array();
$this->locale = $this->option( self::OPT_LOCALE );
if ( empty( $this->locale ) ) {
$missingOptions[] = self::OPT_LOCALE;
}
$this->dbHost = $this->option( self::OPT_DB_HOST );
if ( empty( $this->dbHost ) ) {
$missingOptions[] = self::OPT_DB_HOST;
}
$this->dbPort = $this->option( self::OPT_DB_PORT );
if ( empty( $this->dbPort ) ) {
$missingOptions[] = self::OPT_DB_PORT;
}
$this->dbName = $this->option( self::OPT_DB_NAME );
if ( empty( $this->dbPort ) ) {
$missingOptions[] = self::OPT_DB_NAME;
}
$this->dbUsername = $this->option( self::OPT_DB_USERNAME );
if ( empty( $this->dbPort ) ) {
$missingOptions[] = self::OPT_DB_USERNAME;
}
$this->dbPassword = $this->option( self::OPT_DB_PASSWORD );
if ( empty( $this->dbPort ) ) {
$missingOptions[] = self::OPT_DB_PASSWORD;
}
$this->companyName = $this->option( self::OPT_COMPANY_NAME );
if ( empty( $this->dbPort ) ) {
$missingOptions[] = self::OPT_COMPANY_NAME;
}
$this->companyEmail = $this->option( self::OPT_COMPANY_EMAIL );
if ( empty( $this->dbPort ) ) {
$missingOptions[] = self::OPT_COMPANY_EMAIL;
}
$this->adminEmail = $this->option( self::OPT_ADMIN_EMAIL );
if ( empty( $this->dbPort ) ) {
$missingOptions[] = self::OPT_ADMIN_EMAIL;
}
$this->adminPassword = $this->option( self::OPT_ADMIN_PASSWORD );
if ( empty( $this->dbPort ) ) {
$missingOptions[] = self::OPT_ADMIN_PASSWORD;
}
return $missingOptions;
}
/**
* Ask the user for data if some options are missing.
*/
private function prompt() {
if ( empty( $this->dbHost ) ) {
$this->dbHost = $this->ask( 'What is the database host?', 'localhost' );
}
if ( empty( $this->dbPort ) ) {
$this->dbPort = $this->ask( 'What is the database port?', '3606' );
}
if ( empty( $this->dbName ) ) {
$this->dbName = $this->ask( 'What is the database name?' );
}
if ( empty( $this->dbUsername ) ) {
$this->dbUsername = $this->ask( 'What is the database username?' );
}
if ( empty( $this->dbPassword ) ) {
$this->dbPassword = $this->secret( 'What is the database password?' );
}
if ( empty( $this->companyName ) ) {
$this->companyName = $this->ask( 'What is the company name?' );
}
if ( empty( $this->companyEmail ) ) {
$this->companyEmail = $this->ask( 'What is the company contact email?' );
}
if ( empty( $this->adminEmail ) ) {
$this->adminEmail = $this->ask( 'What is the admin email?', $this->companyEmail );
}
if ( empty( $this->adminPassword ) ) {
$this->adminPassword = $this->secret( 'What is the admin password?' );
}
}
private function configureDatabase() {
$this->dbHost = $this->option( self::OPT_DB_HOST );
$this->dbPort = $this->option( self::OPT_DB_PORT );
$this->dbName = $this->option( self::OPT_DB_NAME );
$this->dbUsername = $this->option( self::OPT_DB_USERNAME );
$this->dbPassword = $this->option( self::OPT_DB_PASSWORD );
$this->line( 'Connecting to database ' . $this->dbName . '@' . $this->dbHost . ':' . $this->dbPort );
$isDbValid = AppConfigurer::isDbValid( $this->dbHost, $this->dbPort, $this->dbName, $this->dbUsername, $this->dbPassword );
if ( ! $isDbValid ) {
$this->error( 'Error: Could not connect to the database! Please, make sure the details are correct.' );
return false;
}
AppConfigurer::saveDbVariables( $this->dbHost, $this->dbPort, $this->dbName, $this->dbUsername, $this->dbPassword );
// Try to increase the maximum execution time
set_time_limit( 300 ); // 5 minutes
// Create tables
Artisan::call( 'migrate', [ '--force' => true ] );
// Create Roles
Artisan::call( 'db:seed', [ '--class' => 'Database\Seeds\Roles', '--force' => true ] );
return true;
}
}

View File

@ -0,0 +1,232 @@
<?php
namespace App\Console\Commands;
use Session;
use App\Utilities\Installer;
use Illuminate\Console\Command;
class Install extends Command
{
const CMD_SUCCESS = 0;
const CMD_ERROR = 1;
const OPT_DB_HOST = 'db-host';
const OPT_DB_PORT = 'db-port';
const OPT_DB_NAME = 'db-name';
const OPT_DB_USERNAME = 'db-username';
const OPT_DB_PASSWORD = 'db-password';
const OPT_COMPANY_NAME = 'company-name';
const OPT_COMPANY_EMAIL = 'company-email';
const OPT_ADMIN_EMAIL = 'admin-email';
const OPT_ADMIN_PASSWORD = 'admin-password';
const OPT_LOCALE = 'locale';
const OPT_NO_INTERACTION = 'no-interaction';
public $dbHost;
public $dbPort;
public $dbName;
public $dbUsername;
public $dbPassword;
public $companyName;
public $companyEmail;
public $adminEmail;
public $adminPassword;
public $locale;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'install
{--db-host= : Database host}
{--db-port=3306 : Port of the database host}
{--db-name= : Name of the database}
{--db-username= : Username to use to access the database}
{--db-password= : Password to use to access the database}
{--company-name= : Name of the company managed buy the app}
{--company-email= : email used to contact the company}
{--admin-email= : Admin user email}
{--admin-password= : Admin user password}
{--locale=en-GB : Language used in the app}
';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Allows to install Akaunting directly through CLI';
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$missingOptions = $this->checkOptions();
if (!empty($missingOptions) && $this->option(self::OPT_NO_INTERACTION)) {
$this->line('❌ Some options are missing and --no-interaction is present. Please run the following command for more informations :');
$this->line('❌ php artisan help install');
$this->line('❌ Missing options are : ' . join(', ', $missingOptions));
return self::CMD_ERROR;
}
$this->line('Setting locale ' . $this->locale);
Session::put(self::OPT_LOCALE, $this->locale);
$this->prompt();
// Create the .env file
Installer::createDefaultEnvFile();
$this->line('Creating database tables');
if (!$this->createDatabaseTables()) {
return self::CMD_ERROR;
}
$this->line('Creating company');
Installer::createCompany($this->companyName, $this->companyEmail, $this->locale);
$this->line('Creating admin');
Installer::createUser($this->adminEmail, $this->adminPassword, $this->locale);
$this->line('Applying the final touches');
Installer::finalTouches();
return self::CMD_SUCCESS;
}
/**
* Check that all options are presents. otherwise returns an array of the missing options
*/
private function checkOptions()
{
$missingOptions = array();
$this->locale = $this->option(self::OPT_LOCALE);
if (empty($this->locale)) {
$missingOptions[] = self::OPT_LOCALE;
}
$this->dbHost = $this->option(self::OPT_DB_HOST);
if (empty($this->dbHost)) {
$missingOptions[] = self::OPT_DB_HOST;
}
$this->dbPort = $this->option(self::OPT_DB_PORT);
if (empty($this->dbPort)) {
$missingOptions[] = self::OPT_DB_PORT;
}
$this->dbName = $this->option(self::OPT_DB_NAME);
if (empty($this->dbPort)) {
$missingOptions[] = self::OPT_DB_NAME;
}
$this->dbUsername = $this->option(self::OPT_DB_USERNAME);
if (empty($this->dbPort)) {
$missingOptions[] = self::OPT_DB_USERNAME;
}
$this->dbPassword = $this->option(self::OPT_DB_PASSWORD);
if (empty($this->dbPort)) {
$missingOptions[] = self::OPT_DB_PASSWORD;
}
$this->companyName = $this->option(self::OPT_COMPANY_NAME);
if (empty($this->dbPort)) {
$missingOptions[] = self::OPT_COMPANY_NAME;
}
$this->companyEmail = $this->option(self::OPT_COMPANY_EMAIL);
if (empty($this->dbPort)) {
$missingOptions[] = self::OPT_COMPANY_EMAIL;
}
$this->adminEmail = $this->option(self::OPT_ADMIN_EMAIL);
if (empty($this->dbPort)) {
$missingOptions[] = self::OPT_ADMIN_EMAIL;
}
$this->adminPassword = $this->option(self::OPT_ADMIN_PASSWORD);
if (empty($this->dbPort)) {
$missingOptions[] = self::OPT_ADMIN_PASSWORD;
}
return $missingOptions;
}
/**
* Ask the user for data if some options are missing.
*/
private function prompt()
{
if (empty($this->dbHost)) {
$this->dbHost = $this->ask('What is the database host?', 'localhost');
}
if (empty($this->dbPort)) {
$this->dbPort = $this->ask('What is the database port?', '3606');
}
if (empty($this->dbName)) {
$this->dbName = $this->ask('What is the database name?');
}
if (empty($this->dbUsername)) {
$this->dbUsername = $this->ask('What is the database username?');
}
if (empty($this->dbPassword)) {
$this->dbPassword = $this->secret('What is the database password?');
}
if (empty($this->companyName)) {
$this->companyName = $this->ask('What is the company name?');
}
if (empty($this->companyEmail)) {
$this->companyEmail = $this->ask('What is the company contact email?');
}
if (empty($this->adminEmail)) {
$this->adminEmail = $this->ask('What is the admin email?', $this->companyEmail);
}
if (empty($this->adminPassword)) {
$this->adminPassword = $this->secret('What is the admin password?');
}
}
private function createDatabaseTables() {
$this->dbHost = $this->option(self::OPT_DB_HOST);
$this->dbPort = $this->option(self::OPT_DB_PORT);
$this->dbName = $this->option(self::OPT_DB_NAME);
$this->dbUsername = $this->option(self::OPT_DB_USERNAME);
$this->dbPassword = $this->option(self::OPT_DB_PASSWORD);
$this->line('Connecting to database ' . $this->dbName . '@' . $this->dbHost . ':' . $this->dbPort);
if (!Installer::createDbTables($this->dbHost, $this->dbPort, $this->dbName, $this->dbUsername, $this->dbPassword)) {
$this->error('Error: Could not connect to the database! Please, make sure the details are correct.');
return false;
}
return true;
}
}

View File

@ -15,9 +15,9 @@ class Kernel extends ConsoleKernel
protected $commands = [ protected $commands = [
Commands\CompanySeed::class, Commands\CompanySeed::class,
Commands\BillReminder::class, Commands\BillReminder::class,
Commands\Install::class,
Commands\InvoiceReminder::class, Commands\InvoiceReminder::class,
Commands\ModuleInstall::class, Commands\ModuleInstall::class,
Commands\ConfigureApp::class,
]; ];
/** /**

View File

@ -4,16 +4,18 @@ namespace App\Http\Controllers\Install;
use Artisan; use Artisan;
use App\Http\Requests\Install\Database as Request; use App\Http\Requests\Install\Database as Request;
use App\Utilities\AppConfigurer; use App\Utilities\Installer;
use Illuminate\Routing\Controller; use Illuminate\Routing\Controller;
class Database extends Controller { class Database extends Controller
{
/** /**
* Show the form for creating a new resource. * Show the form for creating a new resource.
* *
* @return Response * @return Response
*/ */
public function create() { public function create()
{
return view( 'install.database.create' ); return view( 'install.database.create' );
} }
@ -24,7 +26,8 @@ class Database extends Controller {
* *
* @return Response * @return Response
*/ */
public function store( Request $request ) { public function store(Request $request)
{
$host = $request['hostname']; $host = $request['hostname'];
$port = env( 'DB_PORT', '3306' ); $port = env( 'DB_PORT', '3306' );
$database = $request['database']; $database = $request['database'];
@ -32,27 +35,14 @@ class Database extends Controller {
$password = $request['password']; $password = $request['password'];
// Check database connection // Check database connection
if ( ! AppConfigurer::isDbValid($host,$port,$database,$username,$password) ) { if (!Installer::createDbTables($host, $port, $database, $username, $password)) {
$message = trans( 'install.error.connection' ); $message = trans('install.error.connection');
flash( $message )->error()->important(); flash( $message )->error()->important();
return redirect( 'install/database' )->withInput(); return redirect( 'install/database' )->withInput();
} }
// Set database details return redirect('install/settings' );
AppConfigurer::saveDbVariables($host, $port, $database, $username, $password);
// Try to increase the maximum execution time
set_time_limit( 300 ); // 5 minutes
// Create tables
Artisan::call( 'migrate', [ '--force' => true ] );
// Create Roles
Artisan::call( 'db:seed', [ '--class' => 'Database\Seeds\Roles', '--force' => true ] );
return redirect( 'install/settings' );
} }
} }

View File

@ -2,8 +2,8 @@
namespace App\Http\Controllers\Install; namespace App\Http\Controllers\Install;
use App\Utilities\Installer;
use File; use File;
use App\Utilities\AppConfigurer;
use Illuminate\Routing\Controller; use Illuminate\Routing\Controller;
class Requirements extends Controller class Requirements extends Controller
@ -16,12 +16,12 @@ class Requirements extends Controller
public function show() public function show()
{ {
// Check requirements // Check requirements
$requirements = AppConfigurer::checkServerRequirements(); $requirements = Installer::checkServerRequirements();
if (empty($requirements)) { if (empty($requirements)) {
// Create the .env file // Create the .env file
if (!File::exists(base_path('.env'))) { if (!File::exists(base_path('.env'))) {
AppConfigurer::createDefaultEnvFile(); Installer::createDefaultEnvFile();
} }
redirect('install/language')->send(); redirect('install/language')->send();

View File

@ -3,7 +3,7 @@
namespace App\Http\Controllers\Install; namespace App\Http\Controllers\Install;
use App\Http\Requests\Install\Setting as Request; use App\Http\Requests\Install\Setting as Request;
use App\Utilities\AppConfigurer; use App\Utilities\Installer;
use Illuminate\Routing\Controller; use Illuminate\Routing\Controller;
class Settings extends Controller class Settings extends Controller
@ -28,19 +28,13 @@ class Settings extends Controller
public function store(Request $request) public function store(Request $request)
{ {
// Create company // Create company
$companyName = $request['company_name']; Installer::createCompany($request->get('company_name'), $request->get('company_email'), session('locale'));
$companyEmail= $request['company_email'];
$locale= session('locale');
AppConfigurer::createCompany($companyName, $companyEmail, $locale);
// Create user // Create user
$adminEmail = $request['user_email']; Installer::createUser($request->get('user_email'), $request->get('user_password'), session('locale'));
$adminPassword = $request['user_password'];
$locale= session('locale');
AppConfigurer::createUser($adminEmail, $adminPassword, $locale);
// Make the final touches // Make the final touches
AppConfigurer::finalTouches(); Installer::finalTouches();
// Redirect to dashboard // Redirect to dashboard
return redirect('auth/login'); return redirect('auth/login');

View File

@ -1,28 +1,23 @@
<?php <?php
/**
* Created by PhpStorm.
* User: vcarmignac
* Date: 30/12/17
* Time: 4:29 AM
*/
namespace App\Utilities; namespace App\Utilities;
use Config;
use DB;
use App\Models\Auth\User; use App\Models\Auth\User;
use App\Models\Company\Company; use App\Models\Company\Company;
use Artisan;
use Config;
use DB;
use File; use File;
use Setting;
/** /**
* Class AppConfigurer * Class Installer
* *
* Contains all of the Business logic to configure the app. Either through the CLI or the `/install` web UI. * Contains all of the Business logic to install the app. Either through the CLI or the `/install` web UI.
* *
* @package App\Utilities * @package App\Utilities
*/ */
class AppConfigurer { class Installer
{
public static function checkServerRequirements() public static function checkServerRequirements()
{ {
@ -99,15 +94,38 @@ class AppConfigurer {
public static function createDefaultEnvFile() public static function createDefaultEnvFile()
{ {
// Rename file // Rename file
File::move(base_path('.env.example'), base_path('.env')); if (is_file(base_path('.env.example'))) {
File::move(base_path('.env.example'), base_path('.env'));
}
// Update .env file // Update .env file
self::updateEnv([ static::updateEnv([
'APP_KEY' => 'base64:'.base64_encode(random_bytes(32)), 'APP_KEY' => 'base64:'.base64_encode(random_bytes(32)),
'APP_URL' => url('/'), 'APP_URL' => url('/'),
]); ]);
} }
public static function createDbTables($host, $port, $database, $username, $password)
{
if (!static::isDbValid($host, $port, $database, $username, $password)) {
return false;
}
// Set database details
static::saveDbVariables($host, $port, $database, $username, $password);
// Try to increase the maximum execution time
set_time_limit(300); // 5 minutes
// Create tables
Artisan::call('migrate', ['--force' => true]);
// Create Roles
Artisan::call('db:seed', ['--class' => 'Database\Seeds\Roles', '--force' => true]);
return true;
}
/** /**
* Check if the database exists and is accessible. * Check if the database exists and is accessible.
* *
@ -121,7 +139,8 @@ class AppConfigurer {
* *
* @return bool * @return bool
*/ */
public static function isDbValid($host, $port, $database, $username, $password){ public static function isDbValid($host, $port, $database, $username, $password)
{
Config::set('database.connections.install_test', [ Config::set('database.connections.install_test', [
'host' => $host, 'host' => $host,
'port' => $port, 'port' => $port,
@ -149,7 +168,7 @@ class AppConfigurer {
$prefix = strtolower(str_random(3) . '_'); $prefix = strtolower(str_random(3) . '_');
// Update .env file // Update .env file
self::updateEnv([ static::updateEnv([
'DB_HOST' => $host, 'DB_HOST' => $host,
'DB_PORT' => $port, 'DB_PORT' => $port,
'DB_DATABASE' => $database, 'DB_DATABASE' => $database,
@ -175,7 +194,7 @@ class AppConfigurer {
DB::reconnect($con); DB::reconnect($con);
} }
public static function createCompany($companyName, $companyEmail, $locale) public static function createCompany($name, $email, $locale)
{ {
// Create company // Create company
$company = Company::create([ $company = Company::create([
@ -183,14 +202,14 @@ class AppConfigurer {
]); ]);
// Set settings // Set settings
Setting::set([ setting()->set([
'general.company_name' => $companyName, 'general.company_name' => $name,
'general.company_email' => $companyEmail, 'general.company_email' => $email,
'general.default_currency' => 'USD', 'general.default_currency' => 'USD',
'general.default_locale' => $locale, 'general.default_locale' => $locale,
]); ]);
Setting::setExtraColumns(['company_id' => $company->id]); setting()->setExtraColumns(['company_id' => $company->id]);
Setting::save(); setting()->save();
} }
public static function createUser($email, $password, $locale) public static function createUser($email, $password, $locale)
@ -213,7 +232,7 @@ class AppConfigurer {
public static function finalTouches() public static function finalTouches()
{ {
// Update .env file // Update .env file
self::updateEnv([ static::updateEnv([
'APP_LOCALE' => session('locale'), 'APP_LOCALE' => session('locale'),
'APP_INSTALLED' => 'true', 'APP_INSTALLED' => 'true',
'APP_DEBUG' => 'false', 'APP_DEBUG' => 'false',
@ -229,7 +248,7 @@ class AppConfigurer {
public static function updateEnv($data) public static function updateEnv($data)
{ {
if (empty($data) || !is_array($data)) { if (empty($data) || !is_array($data) || !is_file(base_path('.env'))) {
return false; return false;
} }