diff --git a/app/Configuration.php b/app/Configuration.php index 376e9c1..f1b1e27 100644 --- a/app/Configuration.php +++ b/app/Configuration.php @@ -32,4 +32,9 @@ class Configuration extends Model * @var string */ protected $table = 'configuration'; + + public static function installCompleted() + { + return (!is_null(Configuration::where('key', 'install_completed')->first())); + } } \ No newline at end of file diff --git a/app/Helpers/ConfigHelper.php b/app/Helpers/ConfigHelper.php index eb5521e..192064e 100644 --- a/app/Helpers/ConfigHelper.php +++ b/app/Helpers/ConfigHelper.php @@ -68,7 +68,8 @@ class ConfigHelper 'sender_address' => sprintf('hostmaster@%s', (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost')), 'sender_name' => (is_null($currentAppName) ? trans('global.app_name') : $currentAppName), 'smtp_server' => 'localhost', - 'smtp_port' => 25 + 'smtp_port' => 25, + 'theme' => 'bootstrap3' ); } @@ -78,8 +79,13 @@ class ConfigHelper if (is_null($config)) { - $defaults = $this->defaults(); - return ($defaultIfUnset && isset($defaults[$key]) ? $defaults[$key] : null); + if ($defaultIfUnset) + { + $defaults = $this->defaults(); + return (isset($defaults[$key]) ? $defaults[$key] : null); + } + + return null; } return $config->value; diff --git a/app/Helpers/ThemeHelper.php b/app/Helpers/ThemeHelper.php index db75587..f8d5ebc 100644 --- a/app/Helpers/ThemeHelper.php +++ b/app/Helpers/ThemeHelper.php @@ -3,6 +3,7 @@ namespace App\Helpers; use App\Configuration; +use App\Facade\UserConfig; class ThemeHelper { @@ -76,15 +77,7 @@ class ThemeHelper private function getThemeName() { - $themeName = ThemeHelper::DEFAULT_THEME; - - $currentTheme = Configuration::where('key', 'theme')->first(); - if (!is_null($currentTheme)) - { - $themeName = $currentTheme->value; - } - - return $this->sanitiseThemeName($themeName); + return $this->sanitiseThemeName(UserConfig::get('theme')); } private function sanitiseThemeName($themeName) diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 93f0bea..dc0280f 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -4,10 +4,13 @@ namespace App\Http\Controllers; use App\User; use Illuminate\Foundation\Bus\DispatchesJobs; +use Illuminate\Http\Request; use Illuminate\Routing\Controller as BaseController; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; +use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\DB; class Controller extends BaseController { diff --git a/app/Http/Controllers/InstallController.php b/app/Http/Controllers/InstallController.php new file mode 100644 index 0000000..295bb98 --- /dev/null +++ b/app/Http/Controllers/InstallController.php @@ -0,0 +1,130 @@ +isDatabaseWorking()) + { + return $this->databaseConnection($request); + } + else if (!$this->isAdministratorAccountCreated()) + { + return $this->administratorAccount($request); + } + } + + protected function administratorAccount(Request $request) + { + if (strtolower($request->method()) == 'post') + { + $user = new User(); + $user->name = $request->get('name'); + $user->email = $request->get('email'); + $user->password = bcrypt($request->get('password')); + $user->is_admin = true; + $user->is_activated = true; + $user->save(); + + $request->session()->flash('', ''); + + return redirect(route('home')); + } + + return view('install/administrator'); + } + + protected function databaseConnection(Request $request) + { + if (strtolower($request->method()) == 'post') + { + $baseDirectory = dirname(dirname(dirname(__DIR__))); + + $data = [ + 'APP_KEY=' . config('app.key'), + 'DB_CONNECTION=mysql', + 'DB_HOST=' . $request->get('mysql-server'), + 'DB_PORT=' . intval($request->get('mysql-port')), + 'DB_DATABASE=' . $request->get('mysql-database'), + 'DB_USERNAME=' . $request->get('mysql-username'), + 'DB_PASSWORD=' . $request->get('mysql-password') + ]; + file_put_contents(sprintf('%s/.env', $baseDirectory), join(PHP_EOL, $data) . PHP_EOL); + + // Update the in-memory configuration ready for Artisan :) + $configData = [ + 'connections' => [ + 'mysql' => [ + 'driver' => 'mysql', + 'host' => $request->get('mysql-server'), + 'port' => intval($request->get('mysql-port')), + 'database' => $request->get('mysql-database'), + 'username' => $request->get('mysql-username'), + 'password' => $request->get('mysql-password') + ] + ] + ]; + config(['database' => array_replace_recursive(config('database'), $configData)]); + + DB::reconnect(); + + try + { + Artisan::call('cache:clear'); + Artisan::call('migrate', ['--force' => true]); + + $result = Configuration::where('key', 'install_date')->first(); + if (is_null($result)) + { + $result = new Configuration(); + $result->key = 'install_completed'; + $result->value = true; + $result->save(); + } + + return redirect('/install'); + } + catch (\Exception $ex) + { + $request->session()->flash('database_error', $ex->getMessage()); + return redirect('/install') + ->withInput($request->input()); + } + } + + return view('install/database', [ + 'database_error' => $request->session()->get('database_error') + ]); + } + + private function isAdministratorAccountCreated() + { + return (count(User::administrators()) > 0); + } + + private function isDatabaseWorking() + { + try + { + if (!Configuration::installCompleted()) + { + throw new \Exception(sprintf('install_completed configuration record is not present!')); + } + + return true; + } + catch (\Exception $ex) + { + return false; + } + } +} \ No newline at end of file diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 39ceaaf..a69d6c3 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -3,13 +3,16 @@ namespace App\Providers; use App\Album; +use App\Configuration; use App\Facade\Theme; use App\Facade\UserConfig; use App\Helpers\ConfigHelper; use App\Helpers\ImageHelper; +use App\Helpers\MiscHelper; use App\Helpers\ThemeHelper; use Illuminate\Database\QueryException; use Illuminate\Mail\Mailer; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; @@ -22,28 +25,31 @@ class AppServiceProvider extends ServiceProvider */ public function boot() { - $this->app->singleton('image', function($app) + if ($this->checkIfInstalled()) { - return new ImageHelper(); - }); - $this->app->singleton('theme', function($app) - { - return new ThemeHelper(); - }); - $this->app->singleton('user_config', function($app) - { - return new ConfigHelper(); - }); + $this->app->singleton('image', function ($app) + { + return new ImageHelper(); + }); + $this->app->singleton('theme', function ($app) + { + return new ThemeHelper(); + }); + $this->app->singleton('user_config', function ($app) + { + return new ConfigHelper(); + }); - // When running migrations or CLI tasks, don't need to add things to the view - if (php_sapi_name() != 'cli') - { - $this->addThemeInfoToView(); - $this->addAlbumsToView(); + // When running migrations or CLI tasks, don't need to add things to the view + if (php_sapi_name() != 'cli') + { + $this->addThemeInfoToView(); + $this->addAlbumsToView(); + } + + // Set the default mail configuration as per user's requirements + $this->updateMailConfig(); } - - // Set the default mail configuration as per user's requirements - $this->updateMailConfig(); } /** @@ -56,6 +62,39 @@ class AppServiceProvider extends ServiceProvider // } + private function checkIfInstalled() + { + if ($_SERVER['REQUEST_URI'] == '/install') + { + $baseDirectory = dirname(dirname(__DIR__)); + + // Generate an application key and store to the .env file + if (!file_exists($baseDirectory . '/.env')) + { + $key = MiscHelper::randomString(32); + file_put_contents($baseDirectory . '/.env', sprintf('APP_KEY=%s', $key) . PHP_EOL); + app('config')->set(['app' => ['key' => $key]]); + } + + return false; + } + + try + { + if (!Configuration::installCompleted()) + { + throw new \Exception(sprintf('install_completed configuration record is not present!')); + } + + return true; + } + catch (\Exception $ex) + { + header(sprintf('Location: %s', url('/install'))); + die(); + } + } + private function addAlbumsToView() { $albums = Album::all()->sortBy('name'); diff --git a/app/User.php b/app/User.php index 6636862..6121de8 100644 --- a/app/User.php +++ b/app/User.php @@ -9,15 +9,6 @@ class User extends Authenticatable { use Notifiable; - public static function anonymous() - { - $user = new User(); - $user->id = -1; - $user->name = 'Anonymous'; - - return $user; - } - /** * The attributes that are mass assignable. * @@ -35,4 +26,18 @@ class User extends Authenticatable protected $hidden = [ 'password', 'remember_token', 'activation_token' ]; + + public static function administrators() + { + return User::where('is_admin', true)->get(); + } + + public static function anonymous() + { + $user = new User(); + $user->id = -1; + $user->name = 'Anonymous'; + + return $user; + } } diff --git a/public/.htaccess b/public/.htaccess index 903f639..b4480b8 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -5,6 +5,11 @@ RewriteEngine On + # If not installed, redirect to install folder + RewriteCond %{DOCUMENT_ROOT}/../blue-twilight.lic !-f + RewriteCond %{REQUEST_URI} !^/upload-license.php + RewriteRule .* /upload-license.php [L,R=302] + # Redirect Trailing Slashes If Not A Folder... RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)/$ /$1 [L,R=301] diff --git a/public/install.php b/public/install.php new file mode 100644 index 0000000..e1f6a3a --- /dev/null +++ b/public/install.php @@ -0,0 +1,99 @@ +baseDirectory = dirname(__DIR__); + + // Display errors so installer never gets a WSOD! + ini_set('display_errors', true); + + require $this->baseDirectory . '/vendor/autoload.php'; + } + + public function run() + { + $licenseFile = new \SplFileInfo(sprintf('%s/blue-twilight.lic', $this->baseDirectory)); + if (!$licenseFile->isReadable()) + { + return $this->needLicense(); + } + + try + { + $this->licenseInfo = $this->verifyLicense(); + } + catch (\Exception $ex) + { + unlink($licenseFile->getRealPath()); + return $this->needLicense(); + } + + $environmentFile = new \SplFileInfo(sprintf('%s/.env', $this->baseDirectory)); + if (!$environmentFile->isReadable()) + { + return $this->needEnvironmentSetup(); + } + } + + private function needEnvironmentSetup() + { + if ($_SERVER['REQUEST_METHOD'] != 'POST') + { + return $this->render('database-connection'); + } + else + { + $rc = Artisan::call('migrate'); + $output = Artisan::output(); + + var_dump($rc); + var_dump($output); + } + } + + private function needLicense() + { + if ($_SERVER['REQUEST_METHOD'] != 'POST') + { + return $this->render('license'); + } + else + { + move_uploaded_file($_FILES['license-file']['tmp_name'], sprintf('%s/blue-twilight.lic', $this->baseDirectory)); + header(sprintf('Location: %s', $_SERVER['REQUEST_URI']), true, 302); + die(); + } + } + + private function render($viewName) + { + $viewName = pathinfo($viewName, PATHINFO_BASENAME); + $viewPath = sprintf('%s/resources/views/installer/%s.php', $this->baseDirectory, $viewName); + + $translator = new Translator('en'); + $translator->addLoader('file', new PhpFileLoader()); + $translator->addResource('file', sprintf('%s/resources/lang/en/installer.php', $this->baseDirectory), 'en'); + $licenseInfo = $this->licenseInfo; + + require $viewPath; + } + + private function verifyLicense() + { + return (require $this->baseDirectory . '/verify-license.php'); + } +} + +$installer = new BlueTwilightInstaller(); +$installer->run(); \ No newline at end of file diff --git a/public/themes/bootstrap3/images/empty-fuel-gauge.jpg b/public/themes/bootstrap3/images/empty-fuel-gauge.jpg new file mode 100644 index 0000000..08371c8 Binary files /dev/null and b/public/themes/bootstrap3/images/empty-fuel-gauge.jpg differ diff --git a/public/upload-license.php b/public/upload-license.php new file mode 100644 index 0000000..fe6bf93 --- /dev/null +++ b/public/upload-license.php @@ -0,0 +1,41 @@ +getMessage(); + } +} +?> + + + + + + + + Blue Twilight - License Needed + + +

Blue Twilight - License Needed

+ +
+

+

+

+
+ + \ No newline at end of file diff --git a/resources/lang/en/installer.php b/resources/lang/en/installer.php new file mode 100644 index 0000000..7412473 --- /dev/null +++ b/resources/lang/en/installer.php @@ -0,0 +1,12 @@ + 'Blue Twilight Installer', + 'license_file_label' => 'Upload your license file:', + 'license_required_text' => 'Blue Twilight requires a license file to run. The license file is called "blue-twilight.lic" ' . + 'and can be downloaded from the %link_start%My Orders%link_end% page on the %link2_start%Apps by Andy - Web Store%link2_end%.', + 'license_required_text2' => 'The host name in the license file must be: ', + 'license_required_text3' => 'Once you have your license file, please upload it using the field below.', + 'licensed_to' => 'Licensed to: ', + 'save_button' => 'Save', + 'upload_button' => 'Upload' +]; \ No newline at end of file diff --git a/resources/views/install/administrator.blade.php b/resources/views/install/administrator.blade.php new file mode 100644 index 0000000..048f020 --- /dev/null +++ b/resources/views/install/administrator.blade.php @@ -0,0 +1,37 @@ +@extends('install.layout') + +@section('content') +

You will need an administrator account to access Blue Twilight.

+

Please enter the below details to create your administrator account:

+ +
+
+
+ {{ csrf_field() }} +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/install/database.blade.php b/resources/views/install/database.blade.php new file mode 100644 index 0000000..3979d41 --- /dev/null +++ b/resources/views/install/database.blade.php @@ -0,0 +1,47 @@ +@extends('install.layout') + +@section('content') +

Please provide the connection details to your MySQL database:

+ +
+
+ @if (!is_null($database_error)) +
+

Database error: {{ $database_error }}

+
+ @endif + +
+ {{ csrf_field() }} +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/install/layout.blade.php b/resources/views/install/layout.blade.php new file mode 100644 index 0000000..2f166ff --- /dev/null +++ b/resources/views/install/layout.blade.php @@ -0,0 +1,42 @@ + + + + + + + + + Blue Twilight - Installation + + + + + + + +
+
+
+

Install Blue Twilight

+ @yield('content') +
+
+
+ + + + + \ No newline at end of file diff --git a/resources/views/themes/base/gallery/index.blade.php b/resources/views/themes/base/gallery/index.blade.php index 6176ffd..dd7ba8f 100644 --- a/resources/views/themes/base/gallery/index.blade.php +++ b/resources/views/themes/base/gallery/index.blade.php @@ -4,27 +4,35 @@ @section('content')
- @foreach ($albums as $album) -
-
- -
-

- @php($albumUrl = $album->thumbnailUrl('preview')) - @if (strlen($albumUrl) > 0) - - @endif -

-

{{ $album->description }}

-
- - @endforeach + @endforeach + @else +
+ + +

Nothing to see here!

+
+ @endif
diff --git a/routes/web.php b/routes/web.php index e04168b..47e55d0 100644 --- a/routes/web.php +++ b/routes/web.php @@ -36,6 +36,8 @@ Route::group(['prefix' => 'admin'], function () { // Gallery Route::get('/', 'Gallery\DefaultController@index')->name('home'); +Route::get('/install', 'InstallController@start'); +Route::post('/install', 'InstallController@start'); Route::get('/activate/{token}', 'Auth\ActivateController@activate')->name('auth.activate'); Route::get('{albumUrlAlias}', 'Gallery\AlbumController@index')->name('viewAlbum'); Route::get('{albumUrlAlias}/{photoFilename}', 'Gallery\PhotoController@show')->name('viewPhoto'); diff --git a/verify-license.php b/verify-license.php new file mode 100644 index 0000000..80bc2f1 --- /dev/null +++ b/verify-license.php @@ -0,0 +1,5 @@ + sg_get_const('lic_name'), + 'lic_num' => sg_get_const('lic_num') +];