diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..1562590ee --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM php:apache + +RUN apt-get update && apt-get install -y zip libzip-dev libpng-dev \ + && docker-php-ext-install pdo_mysql gd zip \ + && rm -rf /var/lib/apt/lists/* + +COPY . /var/www/html/ + +# Authorize these folders to be edited +RUN chmod -R 777 /var/www/html/storage +RUN chmod -R 777 /var/www/html/bootstrap/cache + +# Allow rewrite +RUN a2enmod rewrite diff --git a/README.md b/README.md index 84d98fe95..83315acf9 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,27 @@ Akaunting uses [Laravel](http://laravel.com), the best existing PHP framework, a * Run the following command: `composer install` * Finally, launch the [installer](https://akaunting.com/docs/installation) +## Docker + +It is possible to containerise Akaunting using the [`docker-compose`](docker/docker-compose.build.yaml) file. Here are a few commands: + +``` +# Make sure you the dependencies are installed +composer install + +# Build the app +docker-compose -f docker/docker-compose.build.yaml build + +# Run the app +docker-compose up + +# Access the container +docker exec -it CONTAINER_ID /bin/sh +``` + +## docker-compose examples +In the `docker/` folder you'll find some example file to run the image with several databases. + ## Contributing Fork the repository, make the code changes then submit a pull request. diff --git a/app/Console/Commands/ConfigureApp.php b/app/Console/Commands/ConfigureApp.php new file mode 100644 index 000000000..fcedb1819 --- /dev/null +++ b/app/Console/Commands/ConfigureApp.php @@ -0,0 +1,238 @@ +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; + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 116597687..3e78423d2 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -17,6 +17,7 @@ class Kernel extends ConsoleKernel Commands\BillReminder::class, Commands\InvoiceReminder::class, Commands\ModuleInstall::class, + Commands\ConfigureApp::class, ]; /** diff --git a/app/Http/Controllers/Install/Database.php b/app/Http/Controllers/Install/Database.php index 1afc0a9b8..bcaf03b9e 100644 --- a/app/Http/Controllers/Install/Database.php +++ b/app/Http/Controllers/Install/Database.php @@ -3,123 +3,56 @@ namespace App\Http\Controllers\Install; use Artisan; -use Config; -use DB; -use DotenvEditor; use App\Http\Requests\Install\Database as Request; +use App\Utilities\AppConfigurer; use Illuminate\Routing\Controller; -class Database extends Controller -{ - /** - * Show the form for creating a new resource. - * - * @return Response - */ - public function create() - { - return view('install.database.create'); - } +class Database extends Controller { + /** + * Show the form for creating a new resource. + * + * @return Response + */ + public function create() { + return view( 'install.database.create' ); + } - /** - * Store a newly created resource in storage. - * - * @param Request $request - * - * @return Response - */ - public function store(Request $request) - { - // Check database connection - if (!$this->canConnect($request)) { - $message = trans('install.error.connection'); + /** + * Store a newly created resource in storage. + * + * @param Request $request + * + * @return Response + */ + public function store( Request $request ) { + $host = $request['hostname']; + $port = env( 'DB_PORT', '3306' ); + $database = $request['database']; + $username = $request['username']; + $password = $request['password']; - flash($message)->error()->important(); + // Check database connection + if ( ! AppConfigurer::isDbValid($host,$port,$database,$username,$password) ) { + $message = trans( 'install.error.connection' ); - return redirect('install/database')->withInput(); - } + flash( $message )->error()->important(); - // Set database details - $this->saveVariables($request); + return redirect( 'install/database' )->withInput(); + } - // Try to increase the maximum execution time - set_time_limit(300); // 5 minutes + // Set database details + AppConfigurer::saveDbVariables($host, $port, $database, $username, $password); - // Create tables - Artisan::call('migrate', ['--force' => true]); + // Try to increase the maximum execution time + set_time_limit( 300 ); // 5 minutes - // Create Roles - Artisan::call('db:seed', ['--class' => 'Database\Seeds\Roles', '--force' => true]); + // Create tables + Artisan::call( 'migrate', [ '--force' => true ] ); - return redirect('install/settings'); - } + // Create Roles + Artisan::call( 'db:seed', [ '--class' => 'Database\Seeds\Roles', '--force' => true ] ); - private function canConnect($request) - { - Config::set('database.connections.install_test', [ - 'host' => $request['hostname'], - 'database' => $request['database'], - 'username' => $request['username'], - 'password' => $request['password'], - 'driver' => env('DB_CONNECTION', 'mysql'), - 'port' => env('DB_PORT', '3306'), - 'charset' => env('DB_CHARSET', 'utf8mb4'), - ]); + return redirect( 'install/settings' ); + } - try { - DB::connection('install_test')->getPdo(); - } catch (\Exception $e) { - return false; - } - - // Purge test connection - DB::purge('install_test'); - - return true; - } - - private function saveVariables($request) - { - $prefix = strtolower(str_random(3) . '_'); - - // Save to file - DotenvEditor::setKeys([ - [ - 'key' => 'DB_HOST', - 'value' => $request['hostname'], - ], - [ - 'key' => 'DB_DATABASE', - 'value' => $request['database'], - ], - [ - 'key' => 'DB_USERNAME', - 'value' => $request['username'], - ], - [ - 'key' => 'DB_PASSWORD', - 'value' => $request['password'], - ], - [ - 'key' => 'DB_PREFIX', - 'value' => $prefix, - ], - ])->save(); - - $con = env('DB_CONNECTION', 'mysql'); - - // Change current connection - $db = Config::get('database.connections.' . $con); - - $db['host'] = $request['hostname']; - $db['database'] = $request['database']; - $db['username'] = $request['username']; - $db['password'] = $request['password']; - $db['prefix'] = $prefix; - - Config::set('database.connections.' . $con, $db); - - DB::purge($con); - DB::reconnect($con); - } } diff --git a/app/Http/Controllers/Install/Requirements.php b/app/Http/Controllers/Install/Requirements.php index 993867b89..a09bfe706 100644 --- a/app/Http/Controllers/Install/Requirements.php +++ b/app/Http/Controllers/Install/Requirements.php @@ -2,8 +2,8 @@ namespace App\Http\Controllers\Install; -use DotenvEditor; use File; +use App\Utilities\AppConfigurer; use Illuminate\Routing\Controller; class Requirements extends Controller @@ -16,12 +16,12 @@ class Requirements extends Controller public function show() { // Check requirements - $requirements = $this->check(); + $requirements = AppConfigurer::checkServerRequirements(); if (empty($requirements)) { // Create the .env file if (!File::exists(base_path('.env'))) { - $this->createEnvFile(); + AppConfigurer::createDefaultEnvFile(); } redirect('install/language')->send(); @@ -33,208 +33,4 @@ class Requirements extends Controller return view('install.requirements.show'); } } - - /** - * Check the requirements. - * - * @return array - */ - private function check() - { - $requirements = array(); - - if (ini_get('safe_mode')) { - $requirements[] = trans('install.requirements.disabled', ['feature' => 'Safe Mode']); - } - - if (ini_get('register_globals')) { - $requirements[] = trans('install.requirements.disabled', ['feature' => 'Register Globals']); - } - - if (ini_get('magic_quotes_gpc')) { - $requirements[] = trans('install.requirements.disabled', ['feature' => 'Magic Quotes']); - } - - if (!ini_get('file_uploads')) { - $requirements[] = trans('install.requirements.enabled', ['feature' => 'File Uploads']); - } - - if (!class_exists('PDO')) { - $requirements[] = trans('install.requirements.extension', ['extension' => 'MySQL PDO']); - } - - if (!extension_loaded('openssl')) { - $requirements[] = trans('install.requirements.extension', ['extension' => 'OpenSSL']); - } - - if (!extension_loaded('tokenizer')) { - $requirements[] = trans('install.requirements.extension', ['extension' => 'Tokenizer']); - } - - if (!extension_loaded('mbstring')) { - $requirements[] = trans('install.requirements.extension', ['extension' => 'mbstring']); - } - - if (!extension_loaded('curl')) { - $requirements[] = trans('install.requirements.extension', ['extension' => 'cURL']); - } - - if (!extension_loaded('xml')) { - $requirements[] = trans('install.requirements.extension', ['extension' => 'XML']); - } - - if (!extension_loaded('zip')) { - $requirements[] = trans('install.requirements.extension', ['extension' => 'ZIP']); - } - - if (!is_writable(base_path('storage/app'))) { - $requirements[] = trans('install.requirements.directory', ['directory' => 'storage/app']); - } - - if (!is_writable(base_path('storage/app/uploads'))) { - $requirements[] = trans('install.requirements.directory', ['directory' => 'storage/app/uploads']); - } - - if (!is_writable(base_path('storage/framework'))) { - $requirements[] = trans('install.requirements.directory', ['directory' => 'storage/framework']); - } - - if (!is_writable(base_path('storage/logs'))) { - $requirements[] = trans('install.requirements.directory', ['directory' => 'storage/logs']); - } - - return $requirements; - } - - /** - * Create the .env file. - * - * @return void - */ - private function createEnvFile() - { - // App - DotenvEditor::setKeys([ - [ - 'key' => 'APP_NAME', - 'value' => 'Akaunting', - ], - [ - 'key' => 'APP_ENV', - 'value' => 'production', - ], - [ - 'key' => 'APP_LOCALE', - 'value' => 'en-GB', - ], - [ - 'key' => 'APP_INSTALLED', - 'value' => 'false', - ], - [ - 'key' => 'APP_KEY', - 'value' => 'base64:'.base64_encode(random_bytes(32)), - ], - [ - 'key' => 'APP_DEBUG', - 'value' => 'true', - ], - [ - 'key' => 'APP_LOG_LEVEL', - 'value' => 'debug', - ], - [ - 'key' => 'APP_URL', - 'value' => url('/'), - ], - ]); - - DotenvEditor::addEmpty(); - - // Database - DotenvEditor::setKeys([ - [ - 'key' => 'DB_CONNECTION', - 'value' => 'mysql', - ], - [ - 'key' => 'DB_HOST', - 'value' => 'localhost', - ], - [ - 'key' => 'DB_PORT', - 'value' => '3306', - ], - [ - 'key' => 'DB_DATABASE', - 'value' => '', - ], - [ - 'key' => 'DB_USERNAME', - 'value' => '', - ], - [ - 'key' => 'DB_PASSWORD', - 'value' => '', - ], - [ - 'key' => 'DB_PREFIX', - 'value' => '', - ], - ]); - - DotenvEditor::addEmpty(); - - // Drivers - DotenvEditor::setKeys([ - [ - 'key' => 'BROADCAST_DRIVER', - 'value' => 'log', - ], - [ - 'key' => 'CACHE_DRIVER', - 'value' => 'file', - ], - [ - 'key' => 'SESSION_DRIVER', - 'value' => 'file', - ], - [ - 'key' => 'QUEUE_DRIVER', - 'value' => 'database', - ], - ]); - - DotenvEditor::addEmpty(); - - // Mail - DotenvEditor::setKeys([ - [ - 'key' => 'MAIL_DRIVER', - 'value' => 'mail', - ], - [ - 'key' => 'MAIL_HOST', - 'value' => 'localhost', - ], - [ - 'key' => 'MAIL_PORT', - 'value' => '2525', - ], - [ - 'key' => 'MAIL_USERNAME', - 'value' => 'null', - ], - [ - 'key' => 'MAIL_PASSWORD', - 'value' => 'null', - ], - [ - 'key' => 'MAIL_ENCRYPTION', - 'value' => 'null', - ], - ]); - - DotenvEditor::save(); - } } diff --git a/app/Http/Controllers/Install/Settings.php b/app/Http/Controllers/Install/Settings.php index a7d6a40f1..80f80e4ae 100644 --- a/app/Http/Controllers/Install/Settings.php +++ b/app/Http/Controllers/Install/Settings.php @@ -2,14 +2,9 @@ namespace App\Http\Controllers\Install; -use Artisan; use App\Http\Requests\Install\Setting as Request; -use App\Models\Auth\User; -use App\Models\Company\Company; -use DotenvEditor; -use File; +use App\Utilities\AppConfigurer; use Illuminate\Routing\Controller; -use Setting; class Settings extends Controller { @@ -33,80 +28,21 @@ class Settings extends Controller public function store(Request $request) { // Create company - $this->createCompany($request); + $companyName = $request['company_name']; + $companyEmail= $request['company_email']; + $locale= session('locale'); + AppConfigurer::createCompany($companyName, $companyEmail, $locale); // Create user - $this->createUser($request); + $adminEmail = $request['user_email']; + $adminPassword = $request['user_password']; + $locale= session('locale'); + AppConfigurer::createUser($adminEmail, $adminPassword, $locale); // Make the final touches - $this->finalTouches(); + AppConfigurer::finalTouches(); // Redirect to dashboard return redirect('auth/login'); } - - private function createCompany($request) - { - // Create company - $company = Company::create([ - 'domain' => '', - ]); - - // Set settings - Setting::set([ - 'general.company_name' => $request['company_name'], - 'general.company_email' => $request['company_email'], - 'general.default_currency' => 'USD', - 'general.default_locale' => session('locale'), - ]); - Setting::setExtraColumns(['company_id' => $company->id]); - Setting::save(); - } - - private function createUser($request) - { - // Create the user - $user = User::create([ - 'name' => $request[''], - 'email' => $request['user_email'], - 'password' => $request['user_password'], - 'locale' => session('locale'), - ]); - - // Attach admin role - $user->roles()->attach('1'); - - // Attach company - $user->companies()->attach('1'); - } - - private function finalTouches() - { - // Caching the config and route - //Artisan::call('config:cache'); - //Artisan::call('route:cache'); - - // Update .env file - DotenvEditor::setKeys([ - [ - 'key' => 'APP_LOCALE', - 'value' => session('locale'), - ], - [ - 'key' => 'APP_INSTALLED', - 'value' => 'true', - ], - [ - 'key' => 'APP_DEBUG', - 'value' => 'false', - ], - ])->save(); - - // Rename the robots.txt file - try { - File::move(base_path('robots.txt.dist'), base_path('robots.txt')); - } catch (\Exception $e) { - // nothing to do - } - } } diff --git a/app/Utilities/AppConfigurer.php b/app/Utilities/AppConfigurer.php new file mode 100644 index 000000000..b99a22ff9 --- /dev/null +++ b/app/Utilities/AppConfigurer.php @@ -0,0 +1,372 @@ + 'Safe Mode']); + } + + if (ini_get('register_globals')) { + $requirements[] = trans('install.requirements.disabled', ['feature' => 'Register Globals']); + } + + if (ini_get('magic_quotes_gpc')) { + $requirements[] = trans('install.requirements.disabled', ['feature' => 'Magic Quotes']); + } + + if (!ini_get('file_uploads')) { + $requirements[] = trans('install.requirements.enabled', ['feature' => 'File Uploads']); + } + + if (!class_exists('PDO')) { + $requirements[] = trans('install.requirements.extension', ['extension' => 'MySQL PDO']); + } + + if (!extension_loaded('openssl')) { + $requirements[] = trans('install.requirements.extension', ['extension' => 'OpenSSL']); + } + + if (!extension_loaded('tokenizer')) { + $requirements[] = trans('install.requirements.extension', ['extension' => 'Tokenizer']); + } + + if (!extension_loaded('mbstring')) { + $requirements[] = trans('install.requirements.extension', ['extension' => 'mbstring']); + } + + if (!extension_loaded('curl')) { + $requirements[] = trans('install.requirements.extension', ['extension' => 'cURL']); + } + + if (!extension_loaded('xml')) { + $requirements[] = trans('install.requirements.extension', ['extension' => 'XML']); + } + + if (!extension_loaded('zip')) { + $requirements[] = trans('install.requirements.extension', ['extension' => 'ZIP']); + } + + if (!is_writable(base_path('storage/app'))) { + $requirements[] = trans('install.requirements.directory', ['directory' => 'storage/app']); + } + + if (!is_writable(base_path('storage/app/uploads'))) { + $requirements[] = trans('install.requirements.directory', ['directory' => 'storage/app/uploads']); + } + + if (!is_writable(base_path('storage/framework'))) { + $requirements[] = trans('install.requirements.directory', ['directory' => 'storage/framework']); + } + + if (!is_writable(base_path('storage/logs'))) { + $requirements[] = trans('install.requirements.directory', ['directory' => 'storage/logs']); + } + + return $requirements; + } + + /** + * Create a default .env file. + * + * @return void + */ + public static function createDefaultEnvFile() + { + // App + DotenvEditor::setKeys([ + [ + 'key' => 'APP_NAME', + 'value' => 'Akaunting', + ], + [ + 'key' => 'APP_ENV', + 'value' => 'production', + ], + [ + 'key' => 'APP_LOCALE', + 'value' => 'en-GB', + ], + [ + 'key' => 'APP_INSTALLED', + 'value' => 'false', + ], + [ + 'key' => 'APP_KEY', + 'value' => 'base64:'.base64_encode(random_bytes(32)), + ], + [ + 'key' => 'APP_DEBUG', + 'value' => 'true', + ], + [ + 'key' => 'APP_LOG_LEVEL', + 'value' => 'debug', + ], + [ + 'key' => 'APP_URL', + 'value' => url('/'), + ], + ]); + + DotenvEditor::addEmpty(); + + // Database + DotenvEditor::setKeys([ + [ + 'key' => 'DB_CONNECTION', + 'value' => 'mysql', + ], + [ + 'key' => 'DB_HOST', + 'value' => 'localhost', + ], + [ + 'key' => 'DB_PORT', + 'value' => '3306', + ], + [ + 'key' => 'DB_DATABASE', + 'value' => '', + ], + [ + 'key' => 'DB_USERNAME', + 'value' => '', + ], + [ + 'key' => 'DB_PASSWORD', + 'value' => '', + ], + [ + 'key' => 'DB_PREFIX', + 'value' => '', + ], + ]); + + DotenvEditor::addEmpty(); + + // Drivers + DotenvEditor::setKeys([ + [ + 'key' => 'BROADCAST_DRIVER', + 'value' => 'log', + ], + [ + 'key' => 'CACHE_DRIVER', + 'value' => 'file', + ], + [ + 'key' => 'SESSION_DRIVER', + 'value' => 'file', + ], + [ + 'key' => 'QUEUE_DRIVER', + 'value' => 'database', + ], + ]); + + DotenvEditor::addEmpty(); + + // Mail + DotenvEditor::setKeys([ + [ + 'key' => 'MAIL_DRIVER', + 'value' => 'mail', + ], + [ + 'key' => 'MAIL_HOST', + 'value' => 'localhost', + ], + [ + 'key' => 'MAIL_PORT', + 'value' => '2525', + ], + [ + 'key' => 'MAIL_USERNAME', + 'value' => 'null', + ], + [ + 'key' => 'MAIL_PASSWORD', + 'value' => 'null', + ], + [ + 'key' => 'MAIL_ENCRYPTION', + 'value' => 'null', + ], + ]); + + DotenvEditor::save(); + } + + /** + * Check if the database exists and is accessible. + * + * @param $host + * @param $port + * @param $database + * @param $host + * @param $database + * @param $username + * @param $password + * + * @return bool + */ + public static function isDbValid($host, $port, $database, $username, $password){ + Config::set('database.connections.install_test', [ + 'host' => $host, + 'port' => $port, + 'database' => $database, + 'username' => $username, + 'password' => $password, + 'driver' => env('DB_CONNECTION', 'mysql'), + 'charset' => env('DB_CHARSET', 'utf8mb4'), + ]); + + try { + DB::connection('install_test')->getPdo(); + } catch (\Exception $e) {; + return false; + } + + // Purge test connection + DB::purge('install_test'); + + return true; + } + + public static function saveDbVariables($host, $port, $database, $username, $password) + { + $prefix = strtolower(str_random(3) . '_'); + + // Save to file + DotenvEditor::setKeys([ + [ + 'key' => 'DB_HOST', + 'value' => $host, + ], + [ + 'key' => 'DB_PORT', + 'value' => $port, + ], + [ + 'key' => 'DB_DATABASE', + 'value' => $database, + ], + [ + 'key' => 'DB_USERNAME', + 'value' => $username, + ], + [ + 'key' => 'DB_PASSWORD', + 'value' => $password, + ], + [ + 'key' => 'DB_PREFIX', + 'value' => $prefix, + ], + ])->save(); + + $con = env('DB_CONNECTION', 'mysql'); + + // Change current connection + $db = Config::get('database.connections.' . $con); + + $db['host'] = $host; + $db['database'] = $database; + $db['username'] = $username; + $db['password'] = $password; + $db['prefix'] = $prefix; + + Config::set('database.connections.' . $con, $db); + + DB::purge($con); + DB::reconnect($con); + } + + public static function createCompany($companyName, $companyEmail, $locale) + { + // Create company + $company = Company::create([ + 'domain' => '', + ]); + + // Set settings + Setting::set([ + 'general.company_name' => $companyName, + 'general.company_email' => $companyEmail, + 'general.default_currency' => 'USD', + 'general.default_locale' => $locale, + ]); + Setting::setExtraColumns(['company_id' => $company->id]); + Setting::save(); + } + + public static function createUser($email, $password, $locale) + { + // Create the user + $user = User::create([ + 'name' => '', + 'email' => $email, + 'password' => $password, + 'locale' => $locale, + ]); + + // Attach admin role + $user->roles()->attach('1'); + + // Attach company + $user->companies()->attach('1'); + } + + public static function finalTouches() + { + // Update .env file + DotenvEditor::setKeys([ + [ + 'key' => 'APP_LOCALE', + 'value' => session('locale'), + ], + [ + 'key' => 'APP_INSTALLED', + 'value' => 'true', + ], + [ + 'key' => 'APP_DEBUG', + 'value' => 'false', + ], + ])->save(); + + // Rename the robots.txt file + try { + File::move(base_path('robots.txt.dist'), base_path('robots.txt')); + } catch (\Exception $e) { + // nothing to do + } + } +} \ No newline at end of file diff --git a/docker/docker-compose.build.yaml b/docker/docker-compose.build.yaml new file mode 100644 index 000000000..f24d8e392 --- /dev/null +++ b/docker/docker-compose.build.yaml @@ -0,0 +1,7 @@ +version: '3' +services: + web: + image: akaunting + build: ../ + ports: + - "80:80" \ No newline at end of file diff --git a/docker/docker-compose.mysql.yaml b/docker/docker-compose.mysql.yaml new file mode 100644 index 000000000..f330cd829 --- /dev/null +++ b/docker/docker-compose.mysql.yaml @@ -0,0 +1,22 @@ +version: '3' +services: + mysql: + image: mysql + ports: + - 3306:3306 + environment: + MYSQL_ROOT_PASSWORD: akaunting_root_password + MYSQL_DATABASE: akaunting_db + MYSQL_USER: akaunting_admin + MYSQL_PASSWORD: akaunting_password + web: + image: akaunting + ## Uncomment if you wish to use this configuration as development environment. + # volumes: + # - ../:/var/www/html + ports: + - 8080:80 + environment: + APP_DEBUG: "true" + links: + - mysql \ No newline at end of file