resolves #5: modified the installer to write a flag to the .env file when installed so naughty people can't create admin accounts etc by directly accessing the installer. First version tested fully encoded with SG :)
This commit is contained in:
parent
227de6baf6
commit
e81dfcd1fd
@ -32,9 +32,4 @@ class Configuration extends Model
|
|||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $table = 'configuration';
|
protected $table = 'configuration';
|
||||||
|
|
||||||
public static function installCompleted()
|
|
||||||
{
|
|
||||||
return (!is_null(Configuration::where('key', 'install_completed')->first()));
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -37,6 +37,23 @@ class MiscHelper
|
|||||||
return (int) $val;
|
return (int) $val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getEnvironmentFilePath()
|
||||||
|
{
|
||||||
|
return sprintf('%s/.env', dirname(dirname(__DIR__)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getEnvironmentSetting($settingName)
|
||||||
|
{
|
||||||
|
$envFile = MiscHelper::getEnvironmentFilePath();
|
||||||
|
$matches = null;
|
||||||
|
if (preg_match(sprintf('/^\s*%s\s*=\s*(.+)$/im', preg_quote($settingName)), file_get_contents($envFile), $matches))
|
||||||
|
{
|
||||||
|
return trim($matches[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static function gravatarUrl($emailAddress, $size = 48, $default = 'identicon')
|
public static function gravatarUrl($emailAddress, $size = 48, $default = 'identicon')
|
||||||
{
|
{
|
||||||
$hash = md5(strtolower(trim($emailAddress)));
|
$hash = md5(strtolower(trim($emailAddress)));
|
||||||
@ -68,4 +85,14 @@ class MiscHelper
|
|||||||
|
|
||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function setEnvironmentSetting($settingName, $value)
|
||||||
|
{
|
||||||
|
if (is_null(MiscHelper::getEnvironmentSetting($settingName)))
|
||||||
|
{
|
||||||
|
return file_put_contents(MiscHelper::getEnvironmentFilePath(), sprintf('%s=%s', $settingName, $value) . PHP_EOL, FILE_APPEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
|||||||
|
|
||||||
use App\Configuration;
|
use App\Configuration;
|
||||||
use App\Helpers\MiscHelper;
|
use App\Helpers\MiscHelper;
|
||||||
|
use App\Http\Requests\StoreUserRequest;
|
||||||
use App\User;
|
use App\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
@ -11,7 +12,7 @@ use Illuminate\Support\Facades\DB;
|
|||||||
|
|
||||||
class InstallController extends Controller
|
class InstallController extends Controller
|
||||||
{
|
{
|
||||||
public function administrator(Request $request)
|
public function administrator(StoreUserRequest $request)
|
||||||
{
|
{
|
||||||
// Validate we're at the required stage
|
// Validate we're at the required stage
|
||||||
$stage = 3;
|
$stage = 3;
|
||||||
@ -20,6 +21,16 @@ class InstallController extends Controller
|
|||||||
return redirect(route('install.check'));
|
return redirect(route('install.check'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we already have an admin account, this step can be skipped
|
||||||
|
$canSkip = User::where('is_admin', true)->count() > 0;
|
||||||
|
|
||||||
|
if ($canSkip && $request->has('skip'))
|
||||||
|
{
|
||||||
|
MiscHelper::setEnvironmentSetting('APP_INSTALLED', true);
|
||||||
|
|
||||||
|
return redirect(route('home'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->method() == 'POST')
|
if ($request->method() == 'POST')
|
||||||
{
|
{
|
||||||
$user = new User();
|
$user = new User();
|
||||||
@ -30,10 +41,16 @@ class InstallController extends Controller
|
|||||||
$user->is_activated = true;
|
$user->is_activated = true;
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
return redirect(url('login'));
|
MiscHelper::setEnvironmentSetting('APP_INSTALLED', true);
|
||||||
|
|
||||||
|
$request->session()->flash('success', trans('installer.install_completed_message'));
|
||||||
|
|
||||||
|
return redirect(route('home'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('install.administrator');
|
return view('install.administrator', [
|
||||||
|
'can_skip' => $canSkip
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function check(Request $request)
|
public function check(Request $request)
|
||||||
@ -47,6 +64,15 @@ class InstallController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$canContinue = true;
|
$canContinue = true;
|
||||||
|
$runtimeMinimum = '5.6.4'; // this minimum is imposed by Laravel 5.3
|
||||||
|
$runtimeVersion = phpversion();
|
||||||
|
$phpIsValid = version_compare($runtimeVersion, $runtimeMinimum) >= 0;
|
||||||
|
|
||||||
|
if (!$phpIsValid)
|
||||||
|
{
|
||||||
|
$canContinue = false;
|
||||||
|
}
|
||||||
|
|
||||||
$requiredModules = [
|
$requiredModules = [
|
||||||
'curl' => 'installer.php_modules.curl',
|
'curl' => 'installer.php_modules.curl',
|
||||||
'pdo_mysql' => 'installer.php_modules.mysql',
|
'pdo_mysql' => 'installer.php_modules.mysql',
|
||||||
@ -71,6 +97,9 @@ class InstallController extends Controller
|
|||||||
return view('install.check', [
|
return view('install.check', [
|
||||||
'available_modules' => $availableModules,
|
'available_modules' => $availableModules,
|
||||||
'can_continue' => $canContinue,
|
'can_continue' => $canContinue,
|
||||||
|
'php_is_valid' => $phpIsValid,
|
||||||
|
'php_version_current' => $runtimeVersion,
|
||||||
|
'php_version_required' => $runtimeMinimum,
|
||||||
'post_max_size' => ($postMaxSize / 1024 / 1024),
|
'post_max_size' => ($postMaxSize / 1024 / 1024),
|
||||||
'post_max_size_warning' => $postMaxSize < $recommendedMinimum,
|
'post_max_size_warning' => $postMaxSize < $recommendedMinimum,
|
||||||
'recommended_minimum_upload' => ($recommendedMinimum / 1024 / 1024),
|
'recommended_minimum_upload' => ($recommendedMinimum / 1024 / 1024),
|
||||||
@ -126,7 +155,7 @@ class InstallController extends Controller
|
|||||||
Artisan::call('cache:clear');
|
Artisan::call('cache:clear');
|
||||||
Artisan::call('migrate', ['--force' => true]);
|
Artisan::call('migrate', ['--force' => true]);
|
||||||
|
|
||||||
$result = Configuration::where('key', 'install_date')->first();
|
$result = Configuration::where('key', 'install_completed')->first();
|
||||||
if (is_null($result))
|
if (is_null($result))
|
||||||
{
|
{
|
||||||
$result = new Configuration();
|
$result = new Configuration();
|
||||||
@ -135,6 +164,8 @@ class InstallController extends Controller
|
|||||||
$result->save();
|
$result->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now the database is up-to-date, we can enable database sessions
|
||||||
|
|
||||||
$request->session()->set('install_stage', 3);
|
$request->session()->set('install_stage', 3);
|
||||||
return redirect(route('install.administrator'));
|
return redirect(route('install.administrator'));
|
||||||
}
|
}
|
||||||
|
@ -44,23 +44,26 @@ class AppInstallation
|
|||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See if the successful flag has been written to the .env file
|
||||||
|
$isAppInstalled = MiscHelper::getEnvironmentSetting('APP_INSTALLED');
|
||||||
|
|
||||||
if ($request->is('install/*'))
|
if ($request->is('install/*'))
|
||||||
{
|
{
|
||||||
// Already in the installer
|
// Already in the installer
|
||||||
|
// For security reasons, don't allow the installer to be used if it has been previously completed
|
||||||
|
if (boolval($isAppInstalled))
|
||||||
|
{
|
||||||
|
return redirect(route('home'));
|
||||||
|
}
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
if ($isAppInstalled)
|
||||||
{
|
|
||||||
if (Configuration::installCompleted())
|
|
||||||
{
|
{
|
||||||
|
// App is configured, continue on
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (\Exception $ex)
|
|
||||||
{
|
|
||||||
// Empty catch block to allow falling through to the redirect below
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect(route('install.check'));
|
return redirect(route('install.check'));
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use App\Facade\Theme;
|
|||||||
use App\Facade\UserConfig;
|
use App\Facade\UserConfig;
|
||||||
use App\Helpers\DbHelper;
|
use App\Helpers\DbHelper;
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Illuminate\Foundation\Application;
|
use Illuminate\Foundation\Application;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Mail\Mailer;
|
use Illuminate\Mail\Mailer;
|
||||||
@ -67,8 +68,8 @@ class GlobalConfiguration
|
|||||||
|
|
||||||
if (function_exists('sg_get_const'))
|
if (function_exists('sg_get_const'))
|
||||||
{
|
{
|
||||||
$licenseName = sg_get_const('license_name');
|
$licenseName = sg_get_const('lic_name');
|
||||||
$licenseNo = sg_get_const('license_number');
|
$licenseNo = sg_get_const('lic_num');
|
||||||
}
|
}
|
||||||
|
|
||||||
View::share('license_name', strlen($licenseName) == 0 ? '**UNLICENSED**' : $licenseName);
|
View::share('license_name', strlen($licenseName) == 0 ? '**UNLICENSED**' : $licenseName);
|
||||||
@ -109,9 +110,16 @@ class GlobalConfiguration
|
|||||||
|
|
||||||
$password = UserConfig::get('smtp_password');
|
$password = UserConfig::get('smtp_password');
|
||||||
if (!is_null($password))
|
if (!is_null($password))
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
$transport->setPassword(decrypt($password));
|
$transport->setPassword(decrypt($password));
|
||||||
}
|
}
|
||||||
|
catch (DecryptException $ex)
|
||||||
|
{
|
||||||
|
// Unable to decrypt the password - presumably the app's key has changed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (UserConfig::get('smtp_encryption'))
|
if (UserConfig::get('smtp_encryption'))
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,10 @@
|
|||||||
RewriteCond %{REQUEST_FILENAME} !-d
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
RewriteRule ^(.*)/$ /$1 [L,R=301]
|
RewriteRule ^(.*)/$ /$1 [L,R=301]
|
||||||
|
|
||||||
|
# Remove index.php from URL...
|
||||||
|
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
|
||||||
|
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
|
||||||
|
|
||||||
# Handle Front Controller...
|
# Handle Front Controller...
|
||||||
RewriteCond %{REQUEST_FILENAME} !-d
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
RewriteCond %{REQUEST_FILENAME} !-f
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
@ -41,6 +41,7 @@ echo 'Removing build files...' . PHP_EOL . PHP_EOL;
|
|||||||
// Remove development-related files
|
// Remove development-related files
|
||||||
system(sprintf('rm -rf %s/resources/build', $appRoot));
|
system(sprintf('rm -rf %s/resources/build', $appRoot));
|
||||||
system(sprintf('rm -rf %s/tests', $appRoot));
|
system(sprintf('rm -rf %s/tests', $appRoot));
|
||||||
|
@unlink(sprintf('%s/composer.phar', $appRoot));
|
||||||
@unlink(sprintf('%s/server.php', $appRoot));
|
@unlink(sprintf('%s/server.php', $appRoot));
|
||||||
|
|
||||||
// Can't use Artisan once encoded
|
// Can't use Artisan once encoded
|
||||||
|
@ -3,8 +3,13 @@ return [
|
|||||||
'administrator_intro' => 'You will need an administrator account to access Blue Twilight. Complete the form below to create your administrator account.',
|
'administrator_intro' => 'You will need an administrator account to access Blue Twilight. Complete the form below to create your administrator account.',
|
||||||
'administrator_title' => 'Create an administrator account',
|
'administrator_title' => 'Create an administrator account',
|
||||||
'app_name' => 'Blue Twilight - Install',
|
'app_name' => 'Blue Twilight - Install',
|
||||||
|
'core' => [
|
||||||
|
'heading' => 'Core Requirements',
|
||||||
|
'php_version' => 'Requires PHP :minimum minimum'
|
||||||
|
],
|
||||||
'database_intro' => 'Please provide the connection details for an empty MySQL or MariaDB database.',
|
'database_intro' => 'Please provide the connection details for an empty MySQL or MariaDB database.',
|
||||||
'database_title' => 'Connect to a Database',
|
'database_title' => 'Connect to a Database',
|
||||||
|
'install_completed_message' => 'Congratulations, Blue Twilight has been installed successfully. You can now login with an administrator account using the "Login" link above.',
|
||||||
'php_config' => [
|
'php_config' => [
|
||||||
'heading' => 'PHP configuration:',
|
'heading' => 'PHP configuration:',
|
||||||
'post_max_size' => 'Maximum POST request size:',
|
'post_max_size' => 'Maximum POST request size:',
|
||||||
|
@ -4,9 +4,19 @@
|
|||||||
<h3>@lang('installer.administrator_title')</h3>
|
<h3>@lang('installer.administrator_title')</h3>
|
||||||
<p>@lang('installer.administrator_intro')</p>
|
<p>@lang('installer.administrator_intro')</p>
|
||||||
|
|
||||||
|
@if (count($errors) > 0)
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<ul>
|
||||||
|
@foreach ($errors->all() as $form_error)
|
||||||
|
<li>{{ $form_error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="row" style="margin-top: 30px;">
|
<div class="row" style="margin-top: 30px;">
|
||||||
<div class="col-md-6 col-md-offset-3">
|
<div class="col-md-6 col-md-offset-3">
|
||||||
<form action="{{ url('/install') }}" method="post">
|
<form action="{{ route('install.administrator') }}" method="post">
|
||||||
{{ csrf_field() }}
|
{{ csrf_field() }}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="name">Name:</label>
|
<label for="name">Name:</label>
|
||||||
@ -25,10 +35,13 @@
|
|||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password-confirm">Confirm Password:</label>
|
<label for="password-confirm">Confirm Password:</label>
|
||||||
<input type="password" class="form-control" id="password-confirm" name="password-confirm" value="{{ old('password-confirm') }}" />
|
<input type="password" class="form-control" id="password-confirm" name="password_confirmation" value="{{ old('password-confirm') }}" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group text-right">
|
<div class="form-group text-right">
|
||||||
|
@if ($can_skip)
|
||||||
|
<a class="btn btn-default" href="{{ route('install.administrator', ['skip' => 1]) }}">Skip</a>
|
||||||
|
@endif
|
||||||
<button type="submit" class="btn btn-success">Create account</button>
|
<button type="submit" class="btn btn-success">Create account</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -8,9 +8,20 @@
|
|||||||
<div class="col-md-8 col-md-offset-2">
|
<div class="col-md-8 col-md-offset-2">
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><b>@lang('installer.core.heading')</b></td>
|
||||||
|
<td style="width: 30%;"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>@lang('installer.core.php_version', ['minimum' => $php_version_required])</td>
|
||||||
|
<td>
|
||||||
|
{{ $php_version_current }}
|
||||||
|
<i class="fa fa-fw fa-{{ $php_is_valid ? 'check text-success' : 'times text-danger' }}"></i>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>@lang('installer.php_modules.heading')</b></td>
|
<td><b>@lang('installer.php_modules.heading')</b></td>
|
||||||
<td style="width: 15%;"></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
@foreach ($required_modules as $key => $value)
|
@foreach ($required_modules as $key => $value)
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
<li role="presentation"><a href="{{ route('albums.index') }}"><i class="fa fa-fw fa-picture-o"></i> @lang('navigation.breadcrumb.albums')</a></li>
|
<li role="presentation"><a href="{{ route('albums.index') }}"><i class="fa fa-fw fa-picture-o"></i> @lang('navigation.breadcrumb.albums')</a></li>
|
||||||
<li role="presentation"><a href="{{ route('user.index') }}"><i class="fa fa-fw fa-user"></i> @lang('navigation.breadcrumb.users')</a></li>
|
<li role="presentation"><a href="{{ route('user.index') }}"><i class="fa fa-fw fa-user"></i> @lang('navigation.breadcrumb.users')</a></li>
|
||||||
<li role="presentation"><a href="{{ route('admin.settings') }}"><i class="fa fa-fw fa-cog"></i> @lang('navigation.breadcrumb.settings')</a></li>
|
|
||||||
<li role="presentation"><a href="{{ route('storage.index') }}"><i class="fa fa-fw fa-folder"></i> @lang('navigation.breadcrumb.storage')</a></li>
|
<li role="presentation"><a href="{{ route('storage.index') }}"><i class="fa fa-fw fa-folder"></i> @lang('navigation.breadcrumb.storage')</a></li>
|
||||||
|
<li role="presentation"><a href="{{ route('admin.settings') }}"><i class="fa fa-fw fa-cog"></i> @lang('navigation.breadcrumb.settings')</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -3,5 +3,27 @@
|
|||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
"author": "Andy Heathershaw",
|
"author": "Andy Heathershaw",
|
||||||
"author_email": "andy@andys.eu",
|
"author_email": "andy@andys.eu",
|
||||||
"navbar_class": "navbar-default navbar-static-top"
|
"navbar_class": "navbar-default navbar-static-top",
|
||||||
|
"thumbnails": [
|
||||||
|
{
|
||||||
|
"name": "fullsize",
|
||||||
|
"height": 600,
|
||||||
|
"width": 800
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "preview",
|
||||||
|
"height": 300,
|
||||||
|
"width": 400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin-preview",
|
||||||
|
"height": 112,
|
||||||
|
"width": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "slideshow-tiny",
|
||||||
|
"height": 75,
|
||||||
|
"width": 100
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user