create .env if non-existing

This commit is contained in:
Tony Murray 2020-06-20 08:10:52 -05:00
parent b1f526be48
commit d1ceb14b9a
8 changed files with 102 additions and 60 deletions

View File

@ -1,7 +1,3 @@
#
# Remember to run "php artisan optimize" after changing this file
#
APP_KEY= APP_KEY=
#DB_HOST= #DB_HOST=

View File

@ -26,6 +26,7 @@
namespace LibreNMS; namespace LibreNMS;
use Composer\Script\Event; use Composer\Script\Event;
use LibreNMS\Exceptions\FileWriteFailedException;
use LibreNMS\Util\EnvHelper; use LibreNMS\Util\EnvHelper;
class ComposerHelper class ComposerHelper
@ -78,13 +79,6 @@ class ComposerHelper
*/ */
private static function populateEnv() private static function populateEnv()
{ {
$install = false;
if (!file_exists('.env')) {
copy('.env.example', '.env');
self::exec('php artisan key:generate');
$install = true;
}
$config = [ $config = [
'db_host' => '', 'db_host' => '',
'db_port' => '', 'db_port' => '',
@ -99,19 +93,23 @@ class ComposerHelper
@include 'config.php'; @include 'config.php';
EnvHelper::writeEnv([ try {
'NODE_ID' => uniqid(), EnvHelper::init();
'DB_HOST' => $config['db_host'], EnvHelper::writeEnv([
'DB_PORT' => $config['db_port'], 'NODE_ID' => uniqid(),
'DB_USERNAME' => $config['db_user'], 'DB_HOST' => $config['db_host'],
'DB_PASSWORD' => $config['db_pass'], 'DB_PORT' => $config['db_port'],
'DB_DATABASE' => $config['db_name'], 'DB_USERNAME' => $config['db_user'],
'DB_SOCKET' => $config['db_socket'], 'DB_PASSWORD' => $config['db_pass'],
'APP_URL' => $config['base_url'], 'DB_DATABASE' => $config['db_name'],
'LIBRENMS_USER' => $config['user'], 'DB_SOCKET' => $config['db_socket'],
'LIBRENMS_GROUP' => $config['group'], 'APP_URL' => $config['base_url'],
'INSTALL' => $install, 'LIBRENMS_USER' => $config['user'],
]); 'LIBRENMS_GROUP' => $config['group'],
]);
} catch (FileWriteFailedException $exception) {
echo $exception->getMessage() . PHP_EOL;
}
} }
private static function setPermissions() private static function setPermissions()

View File

@ -29,8 +29,31 @@ use Throwable;
class FileWriteFailedException extends \Exception class FileWriteFailedException extends \Exception
{ {
protected $file;
public function __construct($file, $code = 0, Throwable $previous = null) public function __construct($file, $code = 0, Throwable $previous = null)
{ {
$this->file = $file;
parent::__construct("Failed to write file: $file", $code, $previous); parent::__construct("Failed to write file: $file", $code, $previous);
} }
// /**
// * Render the exception into an HTTP or JSON response.
// *
// * @param \Illuminate\Http\Request
// * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse
// */
// public function render(\Illuminate\Http\Request $request)
// {
// $title = trans('exceptions.file_write_failed.title');
// $message = trans('exceptions.file_write_failed.message', ['file' => $this->file]);
//
// return $request->wantsJson() ? response()->json([
// 'status' => 'error',
// 'message' => "$title: $message",
// ]) : response()->view('errors.generic', [
// 'title' => $title,
// 'content' => $message,
// ]);
// }
} }

View File

@ -25,6 +25,8 @@
namespace LibreNMS\Util; namespace LibreNMS\Util;
use Artisan;
use ErrorException;
use LibreNMS\Exceptions\FileWriteFailedException; use LibreNMS\Exceptions\FileWriteFailedException;
class EnvHelper class EnvHelper
@ -37,49 +39,30 @@ class EnvHelper
* @param array $unset Remove the given KEYS from the config * @param array $unset Remove the given KEYS from the config
* @param string $file * @param string $file
* @return string * @return string
* @throws \LibreNMS\Exceptions\FileWriteFailedException
*/ */
public static function writeEnv($settings, $unset = [], $file = '.env') public static function writeEnv($settings, $unset = [], $file = '.env')
{ {
$original_content = file_get_contents($file); try {
$original_content = file_get_contents($file);
$new_content = self::setEnv($original_content, $settings, $unset); $new_content = self::setEnv($original_content, $settings, $unset);
// only write if the content has changed // only write if the content has changed
if ($new_content !== $original_content) { if ($new_content !== $original_content) {
file_put_contents($file, $new_content); if (!file_put_contents($file, $new_content)) {
} throw new FileWriteFailedException($file);
}
return $new_content;
}
/**
* Set a setting in .env file.
* Will only set non-empty unset variables
*
* @param array $settings KEY => value list of settings
* @param array $unset Remove the given KEYS from the config
* @param string $file
* @return string
* @throws \LibreNMS\Exceptions\FileWriteFailedException
*/
public static function tryWriteEnv($settings, $unset = [], $file = '.env')
{
$original_content = file_get_contents($file);
$new_content = self::setEnv($original_content, $settings, $unset);
// only write if the content has changed
if ($new_content !== $original_content) {
if(!file_put_contents($file, $new_content)) {
throw new FileWriteFailedException($file);
} }
}
return $new_content; return $new_content;
} catch (ErrorException $e) {
throw new FileWriteFailedException($file, 0, $e);
}
} }
/** /**
* Set a setting in .env file. * Set a setting in .env file content.
* Will only set non-empty unset variables * Will only set non-empty unset variables
* *
* @param string $content * @param string $content
@ -120,6 +103,36 @@ class EnvHelper
return self::fixComments($content); return self::fixComments($content);
} }
/**
* Copy the example .env file and set APP_KEY
*
* @return bool|string
* @throws \LibreNMS\Exceptions\FileWriteFailedException
*/
public static function init()
{
$env_file = base_path('.env');
try {
if (!file_exists($env_file)) {
Artisan::call('key:generate', ['--show' => true]);
$key = trim(Artisan::output());
config(['app.key' => $key]);
copy(base_path('.env.example'), $env_file);
self::writeEnv([
'APP_KEY' => $key,
'INSTALL' => !file_exists(base_path('config.php')) ? 'true' : false, // if both .env and config.php are missing, assume install is needed
], [], $env_file);
return $key;
}
return false;
} catch (ErrorException $e) {
throw new FileWriteFailedException($env_file, 0, $e);
}
}
/** /**
* Fix .env with # in them without a space before it * Fix .env with # in them without a space before it
* *

View File

@ -79,7 +79,7 @@ class FinalizeController extends InstallationController implements InstallerStep
{ {
$this->configureDatabase(); $this->configureDatabase();
$connection = config('database.default', $this->connection); $connection = config('database.default', $this->connection);
return EnvHelper::tryWriteEnv([ return EnvHelper::writeEnv([
'NODE_ID' => uniqid(), 'NODE_ID' => uniqid(),
'DB_HOST' => config("database.connections.$connection.host"), 'DB_HOST' => config("database.connections.$connection.host"),
'DB_PORT' => config("database.connections.$connection.port"), 'DB_PORT' => config("database.connections.$connection.port"),

View File

@ -28,6 +28,7 @@ namespace App\Http\Controllers\Install;
use App\Models\User; use App\Models\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use LibreNMS\DB\Eloquent;
use LibreNMS\Interfaces\InstallerStep; use LibreNMS\Interfaces\InstallerStep;
class MakeUserController extends InstallationController implements InstallerStep class MakeUserController extends InstallationController implements InstallerStep
@ -76,7 +77,7 @@ class MakeUserController extends InstallationController implements InstallerStep
public function complete(): bool public function complete(): bool
{ {
return User::adminOnly()->exists(); return Eloquent::isConnected() && User::adminOnly()->exists();
} }
public function enabled(): bool public function enabled(): bool

View File

@ -27,6 +27,7 @@ namespace App\Http\Middleware;
use Closure; use Closure;
use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Auth\Access\AuthorizationException;
use LibreNMS\Util\EnvHelper;
class CheckInstalled class CheckInstalled
{ {
@ -39,11 +40,17 @@ class CheckInstalled
*/ */
public function handle($request, Closure $next) public function handle($request, Closure $next)
{ {
config(['app.debug' => true]);
$installed = !config('librenms.install') && file_exists(base_path('.env')); $installed = !config('librenms.install') && file_exists(base_path('.env'));
$is_install_route = $request->is('install*'); $is_install_route = $request->is('install*');
// further middleware will fail without an app key, init one
if (empty(config('app.key'))) {
config(['app.key' => EnvHelper::init()]);
}
if (!$installed && !$is_install_route) { if (!$installed && !$is_install_route) {
// no config.php does so let's redirect to the install // redirect to install if not installed
return redirect()->route('install'); return redirect()->route('install');
} elseif ($installed && $is_install_route) { } elseif ($installed && $is_install_route) {
throw new AuthorizationException('This should only be called during install'); throw new AuthorizationException('This should only be called during install');

View File

@ -7,6 +7,10 @@ return [
'title' => 'It is unsafe to run Dusk in production', 'title' => 'It is unsafe to run Dusk in production',
'message' => 'Run ":command" to remove Dusk or if you are a developer set the appropriate APP_ENV' 'message' => 'Run ":command" to remove Dusk or if you are a developer set the appropriate APP_ENV'
], ],
'file_write_failed' => [
'title' => 'Error: Could not write to file',
'message' => 'Failed to write to file (:file). Please check permissions and SELinux/AppArmor if applicable.'
],
'ldap_missing' => [ 'ldap_missing' => [
'title' => 'PHP LDAP support missing', 'title' => 'PHP LDAP support missing',
'message' => 'PHP does not support LDAP, please install or enable the PHP LDAP extension' 'message' => 'PHP does not support LDAP, please install or enable the PHP LDAP extension'