diff --git a/.env.travis b/.env.travis index 22a0c3047..f1d4f5698 100644 --- a/.env.travis +++ b/.env.travis @@ -16,3 +16,4 @@ MAIL_DRIVER=array QUEUE_DRIVER=sync HASHIDS_SALT=test123 +APP_ENVIRONMENT_ONLY=true diff --git a/app/Contracts/Repository/SettingsRepositoryInterface.php b/app/Contracts/Repository/SettingsRepositoryInterface.php new file mode 100644 index 000000000..dbf87f744 --- /dev/null +++ b/app/Contracts/Repository/SettingsRepositoryInterface.php @@ -0,0 +1,32 @@ +. - * - * This software is licensed under the terms of the MIT license. - * https://opensource.org/licenses/MIT - */ namespace Pterodactyl\Http\Controllers\Admin; -use Krucas\Settings\Settings; -use Prologue\Alerts\AlertsMessageBag; +use Illuminate\View\View; use Pterodactyl\Http\Controllers\Controller; -use Pterodactyl\Http\Requests\Admin\BaseFormRequest; use Pterodactyl\Services\Helpers\SoftwareVersionService; class BaseController extends Controller { - /** - * @var \Prologue\Alerts\AlertsMessageBag - */ - protected $alert; - - /** - * @var \Krucas\Settings\Settings - */ - protected $settings; - /** * @var \Pterodactyl\Services\Helpers\SoftwareVersionService */ - protected $version; + private $version; /** * BaseController constructor. * - * @param \Prologue\Alerts\AlertsMessageBag $alert - * @param \Krucas\Settings\Settings $settings * @param \Pterodactyl\Services\Helpers\SoftwareVersionService $version */ - public function __construct( - AlertsMessageBag $alert, - Settings $settings, - SoftwareVersionService $version - ) { - $this->alert = $alert; - $this->settings = $settings; + public function __construct(SoftwareVersionService $version) + { $this->version = $version; } @@ -54,34 +28,8 @@ class BaseController extends Controller * * @return \Illuminate\View\View */ - public function getIndex() + public function index(): View { return view('admin.index', ['version' => $this->version]); } - - /** - * Return the admin settings view. - * - * @return \Illuminate\View\View - */ - public function getSettings() - { - return view('admin.settings'); - } - - /** - * Handle settings post request. - * - * @param \Pterodactyl\Http\Requests\Admin\BaseFormRequest $request - * @return \Illuminate\Http\RedirectResponse - */ - public function postSettings(BaseFormRequest $request) - { - $this->settings->set('company', $request->input('company')); - $this->settings->set('2fa', $request->input('2fa')); - - $this->alert->success('Settings have been successfully updated.')->flash(); - - return redirect()->route('admin.settings'); - } } diff --git a/app/Http/Controllers/Admin/Settings/AdvancedController.php b/app/Http/Controllers/Admin/Settings/AdvancedController.php new file mode 100644 index 000000000..f8249acd3 --- /dev/null +++ b/app/Http/Controllers/Admin/Settings/AdvancedController.php @@ -0,0 +1,91 @@ +alert = $alert; + $this->config = $config; + $this->kernel = $kernel; + $this->settings = $settings; + } + + /** + * Render advanced Panel settings UI. + * + * @return \Illuminate\View\View + */ + public function index(): View + { + $showRecaptchaWarning = false; + if ( + $this->config->get('recaptcha._shipped_secret_key') === $this->config->get('recaptcha.secret_key') + || $this->config->get('recaptcha._shipped_website_key') === $this->config->get('recaptcha.website_key') + ) { + $showRecaptchaWarning = true; + } + + return view('admin.settings.advanced', [ + 'showRecaptchaWarning' => $showRecaptchaWarning, + ]); + } + + /** + * @param \Pterodactyl\Http\Requests\Admin\Settings\AdvancedSettingsFormRequest $request + * @return \Illuminate\Http\RedirectResponse + */ + public function update(AdvancedSettingsFormRequest $request): RedirectResponse + { + foreach ($request->normalize() as $key => $value) { + $this->settings->set('settings::' . $key, $value); + } + + $this->kernel->call('queue:restart'); + $this->alert->success('Advanced settings have been updated successfully and the queue worker was restarted to apply these changes.')->flash(); + + return redirect()->route('admin.settings.advanced'); + } +} diff --git a/app/Http/Controllers/Admin/Settings/IndexController.php b/app/Http/Controllers/Admin/Settings/IndexController.php new file mode 100644 index 000000000..604684da4 --- /dev/null +++ b/app/Http/Controllers/Admin/Settings/IndexController.php @@ -0,0 +1,89 @@ +alert = $alert; + $this->kernel = $kernel; + $this->settings = $settings; + $this->versionService = $versionService; + } + + /** + * Render the UI for basic Panel settings. + * + * @return \Illuminate\View\View + */ + public function index(): View + { + return view('admin.settings.index', [ + 'version' => $this->versionService, + 'languages' => $this->getAvailableLanguages(true), + ]); + } + + /** + * Handle settings update. + * + * @param \Pterodactyl\Http\Requests\Admin\Settings\BaseSettingsFormRequest $request + * @return \Illuminate\Http\RedirectResponse + */ + public function update(BaseSettingsFormRequest $request): RedirectResponse + { + foreach ($request->normalize() as $key => $value) { + $this->settings->set('settings::' . $key, $value); + } + + $this->kernel->call('queue:restart'); + $this->alert->success('Panel settings have been updated successfully and the queue worker was restarted to apply these changes.')->flash(); + + return redirect()->route('admin.settings'); + } +} diff --git a/app/Http/Controllers/Admin/Settings/MailController.php b/app/Http/Controllers/Admin/Settings/MailController.php new file mode 100644 index 000000000..0e5a1d737 --- /dev/null +++ b/app/Http/Controllers/Admin/Settings/MailController.php @@ -0,0 +1,112 @@ +alert = $alert; + $this->config = $config; + $this->encrypter = $encrypter; + $this->kernel = $kernel; + $this->settings = $settings; + } + + /** + * Render UI for editing mail settings. This UI should only display if + * the server is configured to send mail using SMTP. + * + * @return \Illuminate\View\View + */ + public function index(): View + { + return view('admin.settings.mail', [ + 'disabled' => $this->config->get('mail.driver') !== 'smtp', + ]); + } + + /** + * Handle request to update SMTP mail settings. + * + * @param \Pterodactyl\Http\Requests\Admin\Settings\MailSettingsFormRequest $request + * @return \Illuminate\Http\RedirectResponse + * + * @throws \Pterodactyl\Exceptions\DisplayException + */ + public function update(MailSettingsFormRequest $request): RedirectResponse + { + if ($this->config->get('mail.driver') !== 'smtp') { + throw new DisplayException('This feature is only available if SMTP is the selected email driver for the Panel.'); + } + + $values = $request->normalize(); + if (array_get($values, 'mail:password') === '!e') { + $values['mail:password'] = ''; + } + + foreach ($values as $key => $value) { + if (in_array($key, SettingsServiceProvider::getEncryptedKeys()) && ! empty($value)) { + $value = $this->encrypter->encrypt($value); + } + + $this->settings->set('settings::' . $key, $value); + } + + $this->kernel->call('queue:restart'); + $this->alert->success('Mail settings have been updated successfully and the queue worker was restarted to apply these changes.')->flash(); + + return redirect()->route('admin.settings.mail'); + } +} diff --git a/app/Http/Middleware/RequireTwoFactorAuthentication.php b/app/Http/Middleware/RequireTwoFactorAuthentication.php index bc5ff70ee..266983471 100644 --- a/app/Http/Middleware/RequireTwoFactorAuthentication.php +++ b/app/Http/Middleware/RequireTwoFactorAuthentication.php @@ -11,7 +11,6 @@ namespace Pterodactyl\Http\Middleware; use Closure; use Illuminate\Http\Request; -use Krucas\Settings\Settings; use Prologue\Alerts\AlertsMessageBag; class RequireTwoFactorAuthentication @@ -25,11 +24,6 @@ class RequireTwoFactorAuthentication */ private $alert; - /** - * @var \Krucas\Settings\Settings - */ - private $settings; - /** * The names of routes that should be accessable without 2FA enabled. * @@ -56,12 +50,10 @@ class RequireTwoFactorAuthentication * RequireTwoFactorAuthentication constructor. * * @param \Prologue\Alerts\AlertsMessageBag $alert - * @param \Krucas\Settings\Settings $settings */ - public function __construct(AlertsMessageBag $alert, Settings $settings) + public function __construct(AlertsMessageBag $alert) { $this->alert = $alert; - $this->settings = $settings; } /** @@ -81,10 +73,7 @@ class RequireTwoFactorAuthentication return $next($request); } - switch ((int) $this->settings->get('2fa', 0)) { - case self::LEVEL_NONE: - return $next($request); - break; + switch ((int) config('pterodactyl.auth.2fa_required')) { case self::LEVEL_ADMIN: if (! $request->user()->root_admin || $request->user()->use_totp) { return $next($request); @@ -95,6 +84,9 @@ class RequireTwoFactorAuthentication return $next($request); } break; + case self::LEVEL_NONE: + default: + return $next($request); } $this->alert->danger(trans('auth.2fa_must_be_enabled'))->flash(); diff --git a/app/Http/Requests/Admin/Settings/AdvancedSettingsFormRequest.php b/app/Http/Requests/Admin/Settings/AdvancedSettingsFormRequest.php new file mode 100644 index 000000000..a80d8dab9 --- /dev/null +++ b/app/Http/Requests/Admin/Settings/AdvancedSettingsFormRequest.php @@ -0,0 +1,42 @@ + 'required|in:true,false', + 'recaptcha:secret_key' => 'required|string|max:255', + 'recaptcha:website_key' => 'required|string|max:255', + 'pterodactyl:guzzle:timeout' => 'required|integer|between:1,60', + 'pterodactyl:guzzle:connect_timeout' => 'required|integer|between:1,60', + 'pterodactyl:console:count' => 'required|integer|min:1', + 'pterodactyl:console:frequency' => 'required|integer|min:10', + ]; + } + + /** + * @return array + */ + public function attributes() + { + return [ + 'recaptcha:enabled' => 'reCAPTCHA Enabled', + 'recaptcha:secret_key' => 'reCAPTCHA Secret Key', + 'recaptcha:website_key' => 'reCAPTCHA Website Key', + 'pterodactyl:guzzle:timeout' => 'HTTP Request Timeout', + 'pterodactyl:guzzle:connect_timeout' => 'HTTP Connection Timeout', + 'pterodactyl:console:count' => 'Console Message Count', + 'pterodactyl:console:frequency' => 'Console Frequency Tick', + ]; + } +} diff --git a/app/Http/Requests/Admin/Settings/BaseSettingsFormRequest.php b/app/Http/Requests/Admin/Settings/BaseSettingsFormRequest.php new file mode 100644 index 000000000..0b02561dd --- /dev/null +++ b/app/Http/Requests/Admin/Settings/BaseSettingsFormRequest.php @@ -0,0 +1,36 @@ + 'required|string|max:255', + 'pterodactyl:auth:2fa_required' => 'required|integer|in:0,1,2', + 'app:locale' => ['required', 'string', Rule::in(array_keys($this->getAvailableLanguages()))], + ]; + } + + /** + * @return array + */ + public function attributes() + { + return [ + 'app:name' => 'Company Name', + 'pterodactyl:auth:2fa_required' => 'Require 2-Factor Authentication', + 'app:locale' => 'Default Language', + ]; + } +} diff --git a/app/Http/Requests/Admin/Settings/MailSettingsFormRequest.php b/app/Http/Requests/Admin/Settings/MailSettingsFormRequest.php new file mode 100644 index 000000000..269c2f6c7 --- /dev/null +++ b/app/Http/Requests/Admin/Settings/MailSettingsFormRequest.php @@ -0,0 +1,44 @@ + 'required|string', + 'mail:port' => 'required|integer|between:1,65535', + 'mail:encryption' => 'present|string|in:"",tls,ssl', + 'mail:username' => 'string|max:255', + 'mail:password' => 'string|max:255', + 'mail:from:address' => 'required|string|email', + 'mail:from:name' => 'string|max:255', + ]; + } + + /** + * Override the default normalization function for this type of request + * as we need to accept empty values on the keys. + * + * @param array $only + * @return array + */ + public function normalize($only = []) + { + $keys = array_flip(array_keys($this->rules())); + + if (empty($this->input('mail:password'))) { + unset($keys['mail:password']); + } + + return $this->only(array_flip($keys)); + } +} diff --git a/app/Models/Setting.php b/app/Models/Setting.php new file mode 100644 index 000000000..90d41f3d4 --- /dev/null +++ b/app/Models/Setting.php @@ -0,0 +1,39 @@ + 'required|string|between:1,255', + 'value' => 'string', + ]; +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index b9b656dc1..b3a7c33ea 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -13,7 +13,6 @@ use Pterodactyl\Observers\UserObserver; use Pterodactyl\Observers\ServerObserver; use Pterodactyl\Observers\SubuserObserver; use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider; -use DaneEveritt\LoginNotifications\NotificationServiceProvider; use Barryvdh\Debugbar\ServiceProvider as DebugbarServiceProvider; class AppServiceProvider extends ServiceProvider @@ -42,10 +41,6 @@ class AppServiceProvider extends ServiceProvider $this->app->register(DebugbarServiceProvider::class); $this->app->register(IdeHelperServiceProvider::class); } - - if (config('pterodactyl.auth.notifications')) { - $this->app->register(NotificationServiceProvider::class); - } } /** diff --git a/app/Providers/RepositoryServiceProvider.php b/app/Providers/RepositoryServiceProvider.php index bc393a883..e34520962 100644 --- a/app/Providers/RepositoryServiceProvider.php +++ b/app/Providers/RepositoryServiceProvider.php @@ -26,6 +26,7 @@ use Pterodactyl\Repositories\Eloquent\SubuserRepository; use Pterodactyl\Repositories\Eloquent\DatabaseRepository; use Pterodactyl\Repositories\Eloquent\LocationRepository; use Pterodactyl\Repositories\Eloquent\ScheduleRepository; +use Pterodactyl\Repositories\Eloquent\SettingsRepository; use Pterodactyl\Repositories\Eloquent\DaemonKeyRepository; use Pterodactyl\Repositories\Eloquent\AllocationRepository; use Pterodactyl\Repositories\Eloquent\PermissionRepository; @@ -47,6 +48,7 @@ use Pterodactyl\Contracts\Repository\SubuserRepositoryInterface; use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; use Pterodactyl\Contracts\Repository\LocationRepositoryInterface; use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface; +use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface; use Pterodactyl\Contracts\Repository\DaemonKeyRepositoryInterface; use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; use Pterodactyl\Contracts\Repository\PermissionRepositoryInterface; @@ -86,10 +88,13 @@ class RepositoryServiceProvider extends ServiceProvider $this->app->bind(ServerRepositoryInterface::class, ServerRepository::class); $this->app->bind(ServerVariableRepositoryInterface::class, ServerVariableRepository::class); $this->app->bind(SessionRepositoryInterface::class, SessionRepository::class); + $this->app->bind(SettingsRepositoryInterface::class, SettingsRepository::class); $this->app->bind(SubuserRepositoryInterface::class, SubuserRepository::class); $this->app->bind(TaskRepositoryInterface::class, TaskRepository::class); $this->app->bind(UserRepositoryInterface::class, UserRepository::class); + $this->app->alias(SettingsRepositoryInterface::class, 'settings'); + // Daemon Repositories if ($this->app->make('config')->get('pterodactyl.daemon.use_new_daemon')) { $this->app->bind(ConfigurationRepositoryInterface::class, \Pterodactyl\Repositories\Wings\ConfigurationRepository::class); diff --git a/app/Providers/SettingsServiceProvider.php b/app/Providers/SettingsServiceProvider.php new file mode 100644 index 000000000..dc9e9cdc6 --- /dev/null +++ b/app/Providers/SettingsServiceProvider.php @@ -0,0 +1,101 @@ +get('pterodactyl.load_environment_only', false)) { + return; + } + + // Only set the email driver settings from the database if we + // are configured using SMTP as the driver. + if ($config->get('mail.driver') === 'smtp') { + $this->keys = array_merge($this->keys, $this->emailKeys); + } + + $values = $settings->all()->mapWithKeys(function ($setting) { + return [$setting->key => $setting->value]; + })->toArray(); + + foreach ($this->keys as $key) { + $value = array_get($values, 'settings::' . $key, $config->get(str_replace(':', '.', $key))); + if (in_array($key, self::$encrypted)) { + try { + $value = $encrypter->decrypt($value); + } catch (DecryptException $exception) { + } + } + + $config->set(str_replace(':', '.', $key), $value); + } + } + + /** + * @return array + */ + public static function getEncryptedKeys(): array + { + return self::$encrypted; + } +} diff --git a/app/Repositories/Eloquent/SettingsRepository.php b/app/Repositories/Eloquent/SettingsRepository.php new file mode 100644 index 000000000..b6937bf31 --- /dev/null +++ b/app/Repositories/Eloquent/SettingsRepository.php @@ -0,0 +1,96 @@ +clearCache($key); + $this->withoutFresh()->updateOrCreate(['key' => $key], ['value' => $value]); + } + + /** + * Retrieve a persistent setting from the database. + * + * @param string $key + * @param mixed $default + * @return mixed + */ + public function get(string $key, $default = null) + { + // If item has already been requested return it from the cache. If + // we already know it is missing, immediately return the default + // value. + if (array_key_exists($key, $this->cache)) { + return $this->cache[$key]; + } elseif (array_key_exists($key, $this->databaseMiss)) { + return $default; + } + + $instance = $this->getBuilder()->where('key', $key)->first(); + + if (is_null($instance)) { + $this->databaseMiss[$key] = true; + + return $default; + } + + $this->cache[$key] = $instance->value; + + return $this->cache[$key]; + } + + /** + * Remove a key from the database cache. + * + * @param string $key + * @return mixed + */ + public function forget(string $key) + { + $this->clearCache($key); + $this->deleteWhere(['key' => $key]); + } + + /** + * Remove a key from the cache. + * + * @param string $key + */ + protected function clearCache(string $key) + { + unset($this->cache[$key], $this->databaseMiss[$key]); + } +} diff --git a/app/Traits/Helpers/AvailableLanguages.php b/app/Traits/Helpers/AvailableLanguages.php new file mode 100644 index 000000000..f44771f6d --- /dev/null +++ b/app/Traits/Helpers/AvailableLanguages.php @@ -0,0 +1,56 @@ +getFilesystemInstance()->directories(resource_path('lang')))->mapWithKeys(function ($path) use ($localize) { + $code = basename($path); + $value = $localize ? $this->getIsoInstance()->nativeByCode1($code) : $this->getIsoInstance()->languageByCode1($code); + + return [$code => title_case($value)]; + })->toArray(); + } + + /** + * Return an instance of the filesystem for getting a folder listing. + * + * @return \Illuminate\Filesystem\Filesystem + */ + private function getFilesystemInstance(): Filesystem + { + return $this->filesystem = $this->filesystem ?: app()->make(Filesystem::class); + } + + /** + * Return an instance of the ISO639 class for generating names. + * + * @return \Matriphe\ISO639\ISO639 + */ + private function getIsoInstance(): ISO639 + { + return $this->iso639 = $this->iso639 ?: app()->make(ISO639::class); + } +} diff --git a/composer.json b/composer.json index fabe01f0f..6b1271f84 100644 --- a/composer.json +++ b/composer.json @@ -28,6 +28,7 @@ "laravel/framework": "5.4.27", "laravel/tinker": "1.0.1", "lord/laroute": "~2.4.5", + "matriphe/iso-639": "^1.2", "mtdowling/cron-expression": "^1.2", "nesbot/carbon": "^1.22", "nicolaslopezj/searchable": "^1.9", diff --git a/composer.lock b/composer.lock index 9895b8330..139e3c1c3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "a393763d136e25a93fd5b636229496cf", + "content-hash": "bd42f43877e96cca4d4af755c590eb25", "packages": [ { "name": "appstract/laravel-blade-directives", @@ -687,57 +687,6 @@ ], "time": "2014-09-09T13:34:57+00:00" }, - { - "name": "edvinaskrucas/settings", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/edvinaskrucas/settings.git", - "reference": "23f2a912ca8f5b6ba550721a6fc0e6d1acaa9022" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/edvinaskrucas/settings/zipball/23f2a912ca8f5b6ba550721a6fc0e6d1acaa9022", - "reference": "23f2a912ca8f5b6ba550721a6fc0e6d1acaa9022", - "shasum": "" - }, - "require": { - "illuminate/console": "^5.2", - "illuminate/database": "^5.2", - "illuminate/filesystem": "^5.2", - "illuminate/support": "^5.2", - "php": "^5.5|^7.0" - }, - "require-dev": { - "mockery/mockery": "0.9.*" - }, - "type": "library", - "autoload": { - "psr-0": { - "Krucas\\Settings\\": "src/" - }, - "files": [ - "src/helpers.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Edvinas Kručas", - "email": "edv.krucas@gmail.com" - } - ], - "description": "Persistent settings package for Laravel framework.", - "keywords": [ - "Settings", - "laravel", - "persistent settings" - ], - "time": "2016-01-19T13:50:39+00:00" - }, { "name": "erusev/parsedown", "version": "1.6.3", @@ -1674,6 +1623,50 @@ ], "time": "2017-09-04T02:25:29+00:00" }, + { + "name": "matriphe/iso-639", + "version": "1.2", + "source": { + "type": "git", + "url": "https://github.com/matriphe/php-iso-639.git", + "reference": "0245d844daeefdd22a54b47103ffdb0e03c323e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/matriphe/php-iso-639/zipball/0245d844daeefdd22a54b47103ffdb0e03c323e1", + "reference": "0245d844daeefdd22a54b47103ffdb0e03c323e1", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "^4.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Matriphe\\ISO639\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Muhammad Zamroni", + "email": "halo@matriphe.com" + } + ], + "description": "PHP library to convert ISO-639-1 code to language name.", + "keywords": [ + "639", + "iso", + "iso-639", + "lang", + "language", + "laravel" + ], + "time": "2017-07-19T15:11:19+00:00" + }, { "name": "monolog/monolog", "version": "1.23.0", diff --git a/config/app.php b/config/app.php index 2f9da6704..d56b80634 100644 --- a/config/app.php +++ b/config/app.php @@ -1,5 +1,6 @@ env('APP_ENV', 'production'), @@ -14,7 +15,7 @@ return [ | framework needs to place the application's name in a notification or | any other location as required by the application or its packages. */ - 'name' => 'Pterodactyl', + 'name' => env('APP_NAME', 'Pterodactyl'), /* |-------------------------------------------------------------------------- @@ -158,6 +159,7 @@ return [ /* * Application Service Providers... */ + Pterodactyl\Providers\SettingsServiceProvider::class, Pterodactyl\Providers\AppServiceProvider::class, Pterodactyl\Providers\AuthServiceProvider::class, Pterodactyl\Providers\EventServiceProvider::class, @@ -173,7 +175,6 @@ return [ */ igaster\laravelTheme\themeServiceProvider::class, Prologue\Alerts\AlertsServiceProvider::class, - Krucas\Settings\Providers\SettingsServiceProvider::class, Fideloper\Proxy\TrustedProxyServiceProvider::class, Laracasts\Utilities\JavaScript\JavaScriptServiceProvider::class, Lord\Laroute\LarouteServiceProvider::class, @@ -228,7 +229,6 @@ return [ 'Response' => Illuminate\Support\Facades\Response::class, 'Route' => Illuminate\Support\Facades\Route::class, 'Schema' => Illuminate\Support\Facades\Schema::class, - 'Settings' => Krucas\Settings\Facades\Settings::class, 'Session' => Illuminate\Support\Facades\Session::class, 'Storage' => Illuminate\Support\Facades\Storage::class, 'Theme' => igaster\laravelTheme\Facades\Theme::class, diff --git a/config/pterodactyl.php b/config/pterodactyl.php index ad371bce9..523080ae3 100644 --- a/config/pterodactyl.php +++ b/config/pterodactyl.php @@ -1,6 +1,18 @@ (bool) env('APP_ENVIRONMENT_ONLY', false), + /* |-------------------------------------------------------------------------- | Service Author @@ -22,7 +34,7 @@ return [ | Should login success and failure events trigger an email to the user? */ 'auth' => [ - 'notifications' => env('LOGIN_NOTIFICATIONS', false), + '2fa_required' => env('APP_2FA_REQUIRED', 0), '2fa' => [ 'bytes' => 32, 'window' => env('APP_2FA_WINDOW', 4), diff --git a/config/recaptcha.php b/config/recaptcha.php index 1bac5a877..22d739481 100644 --- a/config/recaptcha.php +++ b/config/recaptcha.php @@ -14,12 +14,14 @@ return [ /* * Use a custom secret key, we use our public one by default */ - 'secret_key' => env('RECAPTCHA_SECRET_KEY', '6LekAxoUAAAAAPW-PxNWaCLH76WkClMLSa2jImwD'), + 'secret_key' => env('RECAPTCHA_SECRET_KEY', '6LcJcjwUAAAAALOcDJqAEYKTDhwELCkzUkNDQ0J5'), + '_shipped_secret_key' => '6LcJcjwUAAAAALOcDJqAEYKTDhwELCkzUkNDQ0J5', /* * Use a custom website key, we use our public one by default */ - 'website_key' => env('RECAPTCHA_WEBSITE_KEY', '6LekAxoUAAAAADjWZJ4ufcDRZBBiH9vfHawqRbup'), + 'website_key' => env('RECAPTCHA_WEBSITE_KEY', '6LcJcjwUAAAAAO_Xqjrtj9wWufUpYRnK6BW8lnfn'), + '_shipped_website_key' => '6LcJcjwUAAAAAO_Xqjrtj9wWufUpYRnK6BW8lnfn', /* * Domain verification is enabled by default and compares the domain used when solving the captcha diff --git a/config/settings.php b/config/settings.php deleted file mode 100644 index c6a75fb01..000000000 --- a/config/settings.php +++ /dev/null @@ -1,113 +0,0 @@ - env('SETTINGS_DRIVER', 'database'), - - /* - |-------------------------------------------------------------------------- - | Enable / Disable caching - |-------------------------------------------------------------------------- - | - | If it is enabled all values gets cached after accessing it. - | - */ - 'cache' => true, - - /* - |-------------------------------------------------------------------------- - | Enable / Disable value encryption - |-------------------------------------------------------------------------- - | - | If it is enabled all values gets encrypted and decrypted. - | - */ - 'encryption' => env('SETTINGS_ENCRYPTION', false), - - /* - |-------------------------------------------------------------------------- - | Enable / Disable events - |-------------------------------------------------------------------------- - | - | If it is enabled various settings related events will be fired. - | - */ - 'events' => true, - - /* - |-------------------------------------------------------------------------- - | Repositories Configuration - |-------------------------------------------------------------------------- - | - | Here you may configure the driver information for each repository that - | is used by your application. A default configuration has been added - | for each back-end shipped with this package. You are free to add more. - | - */ - - 'repositories' => [ - 'database' => [ - 'driver' => 'database', - 'connection' => env('DB_CONNECTION', 'mysql'), - 'table' => 'settings', - ], - ], - - /* - |-------------------------------------------------------------------------- - | Key generator class - |-------------------------------------------------------------------------- - | - | Key generator is used to generate keys based on setting key and context. - | - */ - 'key_generator' => \Krucas\Settings\KeyGenerators\KeyGenerator::class, - - /* - |-------------------------------------------------------------------------- - | Context serializer class - |-------------------------------------------------------------------------- - | - | Context serializer serializes context. - | It is used with "Krucas\Settings\KeyGenerators\KeyGenerator" class. - | - */ - 'context_serializer' => \Krucas\Settings\ContextSerializers\ContextSerializer::class, - - /* - |-------------------------------------------------------------------------- - | Value serializer class - |-------------------------------------------------------------------------- - | - | Value serializer serializes / unserializes given value. - | - */ - 'value_serializer' => \Krucas\Settings\ValueSerializers\ValueSerializer::class, - - /* - |-------------------------------------------------------------------------- - | Override application config values - |-------------------------------------------------------------------------- - | - | If defined, settings package will override these config values from persistent - | settings repository. - | - | Sample: - | "app.fallback_locale", - | "app.locale" => "settings.locale", - | - */ - - 'override' => [ - ], -]; diff --git a/database/migrations/2017_12_12_220426_MigrateSettingsTableToNewFormat.php b/database/migrations/2017_12_12_220426_MigrateSettingsTableToNewFormat.php new file mode 100644 index 000000000..1bdaf6477 --- /dev/null +++ b/database/migrations/2017_12_12_220426_MigrateSettingsTableToNewFormat.php @@ -0,0 +1,30 @@ +truncate(); + Schema::table('settings', function (Blueprint $table) { + $table->increments('id')->first(); + }); + } + + /** + * Reverse the migrations. + */ + public function down() + { + Schema::table('settings', function (Blueprint $table) { + $table->dropColumn('id'); + }); + } +} diff --git a/phpunit.xml b/phpunit.xml index ceb832d08..89b3c0b22 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -32,5 +32,6 @@ + diff --git a/public/themes/pterodactyl/js/frontend/server.socket.js b/public/themes/pterodactyl/js/frontend/server.socket.js index ef6986168..f43409fd4 100644 --- a/public/themes/pterodactyl/js/frontend/server.socket.js +++ b/public/themes/pterodactyl/js/frontend/server.socket.js @@ -66,6 +66,7 @@ var Server = (function () { delay: 0, }); } + setStatusIcon(999); }); Socket.io.on('connect_error', function (err) { @@ -77,6 +78,7 @@ var Server = (function () { delay: 0, }); } + setStatusIcon(999); }); // Connected to Socket Successfully @@ -111,6 +113,7 @@ var Server = (function () { $('#server_status_icon').html(' Stopping'); break; default: + $('#server_status_icon').html(' Connection Error'); break; } } diff --git a/resources/themes/pterodactyl/admin/settings.blade.php b/resources/themes/pterodactyl/admin/settings.blade.php deleted file mode 100644 index 3e0407e67..000000000 --- a/resources/themes/pterodactyl/admin/settings.blade.php +++ /dev/null @@ -1,69 +0,0 @@ -{{-- Pterodactyl - Panel --}} -{{-- Copyright (c) 2015 - 2017 Dane Everitt --}} - -{{-- This software is licensed under the terms of the MIT license. --}} -{{-- https://opensource.org/licenses/MIT --}} -@extends('layouts.admin') - -@section('title') - Settings -@endsection - -@section('content-header') -

Panel SettingsConfigure Pterodactyl to your liking.

- -@endsection - -@section('content') -
-
-
-
-

Panel Settings

-
-
-
-
-
- -
- -

This is the name that is used throughout the panel and in emails sent to clients.

-
-
-
- -
-
- - - -
-

For improved security you can require all administrators to have 2-Factor authentication enabled, or even require it for all users on the Panel.

-
-
-
-
-
-
In order to modify your SMTP settings for sending mail you will need to run php artisan p:environment:mail in this project's root folder.
-
-
-
- -
-
-
-
-@endsection diff --git a/resources/themes/pterodactyl/admin/settings/advanced.blade.php b/resources/themes/pterodactyl/admin/settings/advanced.blade.php new file mode 100644 index 000000000..5a7b4d724 --- /dev/null +++ b/resources/themes/pterodactyl/admin/settings/advanced.blade.php @@ -0,0 +1,117 @@ +@extends('layouts.admin') +@include('partials/admin.settings.nav', ['activeTab' => 'advanced']) + +@section('title') + Advanced Settings +@endsection + +@section('content-header') +

Advanced SettingsConfigure advanced settings for Pterodactyl.

+ +@endsection + +@section('content') + @yield('settings::nav') +
+
+
+
+
+

reCAPTCHA

+
+
+
+
+ +
+ +

If enabled, login forms and password reset forms will do a silent captcha check and display a visible captcha if needed.

+
+
+
+ +
+ +

Used for communication between your site and Google. Be sure to keep it a secret.

+
+
+
+ +
+ +
+
+
+ @if($showRecaptchaWarning) +
+
+
+ You are currently using reCAPTCHA keys that were shipped with this Panel. For improved security it is recommended to generate new invisible reCAPTCHA keys that tied specifically to your website. +
+
+
+ @endif +
+
+
+
+

HTTP Connections

+
+
+
+
+ +
+ +

The amount of time in seconds to wait for a connection to be opened before throwing an error.

+
+
+
+ +
+ +

The amount of time in seconds to wait for a request to be completed before throwing an error.

+
+
+
+
+
+
+
+

Console

+
+
+
+
+ +
+ +

The number of messages to be pushed to the console per frequency tick.

+
+
+
+ +
+ +

The amount of time in milliseconds between each console message sending tick.

+
+
+
+
+
+
+ +
+
+
+
+@endsection diff --git a/resources/themes/pterodactyl/admin/settings/index.blade.php b/resources/themes/pterodactyl/admin/settings/index.blade.php new file mode 100644 index 000000000..62ef09631 --- /dev/null +++ b/resources/themes/pterodactyl/admin/settings/index.blade.php @@ -0,0 +1,75 @@ +@extends('layouts.admin') +@include('partials/admin.settings.nav', ['activeTab' => 'basic']) + +@section('title') + Settings +@endsection + +@section('content-header') +

Panel SettingsConfigure Pterodactyl to your liking.

+ +@endsection + +@section('content') + @yield('settings::nav') +
+
+
+
+

Panel Settings

+
+
+
+
+
+ +
+ +

This is the name that is used throughout the panel and in emails sent to clients.

+
+
+
+ +
+
+ @php + $level = old('pterodactyl:auth:2fa_required', config('pterodactyl.auth.2fa_required')); + @endphp + + + +
+

If enabled, any account falling into the selected grouping will be required to have 2-Factor authentication enabled to use the Panel.

+
+
+
+ +
+ +

The default language to use when rendering UI components.

+
+
+
+
+ +
+
+
+
+@endsection diff --git a/resources/themes/pterodactyl/admin/settings/mail.blade.php b/resources/themes/pterodactyl/admin/settings/mail.blade.php new file mode 100644 index 000000000..40403993f --- /dev/null +++ b/resources/themes/pterodactyl/admin/settings/mail.blade.php @@ -0,0 +1,108 @@ +@extends('layouts.admin') +@include('partials/admin.settings.nav', ['activeTab' => 'mail']) + +@section('title') + Mail Settings +@endsection + +@section('content-header') +

Mail SettingsConfigure how Pterodactyl should handle sending emails.

+ +@endsection + +@section('content') + @yield('settings::nav') +
+
+
+
+

Email Settings

+
+ @if($disabled) +
+
+
+
+ This interface is limited to instances using SMTP as the mail driver. Please either use php artisan p:environment:mail command to update your email settings, or set MAIL_DRIVER=smtp in your environment file. +
+
+
+
+ @else +
+
+
+
+ +
+ +

Enter the SMTP server address that mail should be sent through.

+
+
+
+ +
+ +

Enter the SMTP server port that mail should be sent through.

+
+
+
+ +
+ @php + $encryption = old('mail:encryption', config('mail.encryption')); + @endphp + +

Select the type of encryption to use when sending mail.

+
+
+
+ +
+ +

The username to use when connecting to the SMTP server.

+
+
+
+ +
+ +

The password to use in conjunction with the SMTP username. Leave blank to continue using the existing password. To set the password to an empty value enter !e into the field.

+
+
+
+
+
+
+ +
+ +

Enter an email address that all outgoing emails will originate from.

+
+
+
+ +
+ +

The name that emails should appear to come from.

+
+
+
+
+ +
+ @endif +
+
+
+@endsection diff --git a/resources/themes/pterodactyl/layouts/admin.blade.php b/resources/themes/pterodactyl/layouts/admin.blade.php index 0c2108ffa..262e59cd5 100644 --- a/resources/themes/pterodactyl/layouts/admin.blade.php +++ b/resources/themes/pterodactyl/layouts/admin.blade.php @@ -8,7 +8,7 @@ - {{ Settings::get('company', 'Pterodactyl') }} - @yield('title') + {{ config('app.name', 'Pterodactyl') }} - @yield('title') @@ -44,7 +44,7 @@