From 4ead450ff4c8249d60aa0eebad5623e65b859433 Mon Sep 17 00:00:00 2001 From: nabeelio Date: Fri, 5 Mar 2021 16:53:16 -0500 Subject: [PATCH 1/5] Use database for kvp storage --- .../2021_03_05_044305_add_kvp_table.php | 19 +++++++++++ .../Controllers/Admin/SettingsController.php | 2 +- app/Models/Kvp.php | 26 ++++++++++++++ app/Models/SimBrief.php | 1 + app/Repositories/KvpRepository.php | 34 ++++++++----------- composer.json | 1 - tests/UtilsTest.php | 19 +++++++++++ 7 files changed, 81 insertions(+), 21 deletions(-) create mode 100644 app/Database/migrations/2021_03_05_044305_add_kvp_table.php create mode 100644 app/Models/Kvp.php diff --git a/app/Database/migrations/2021_03_05_044305_add_kvp_table.php b/app/Database/migrations/2021_03_05_044305_add_kvp_table.php new file mode 100644 index 000000000..e7b75b6e0 --- /dev/null +++ b/app/Database/migrations/2021_03_05_044305_add_kvp_table.php @@ -0,0 +1,19 @@ +string('key')->index(); + $table->string('value'); + }); + } +} diff --git a/app/Http/Controllers/Admin/SettingsController.php b/app/Http/Controllers/Admin/SettingsController.php index 5f6c74a20..6371f73b1 100644 --- a/app/Http/Controllers/Admin/SettingsController.php +++ b/app/Http/Controllers/Admin/SettingsController.php @@ -62,7 +62,7 @@ private function getCurrencyList(): array */ public function index() { - $settings = Setting::orderBy('order', 'asc')->get(); + $settings = Setting::where('type', '!=', 'hidden')->orderBy('order')->get(); $settings = $settings->groupBy('group'); return view('admin.settings.index', [ diff --git a/app/Models/Kvp.php b/app/Models/Kvp.php new file mode 100644 index 000000000..5e097cc7b --- /dev/null +++ b/app/Models/Kvp.php @@ -0,0 +1,26 @@ +valueStore = Valuestore::make(config('phpvms.kvp_storage_path')); } /** @@ -34,36 +32,34 @@ public function retrieve($key, $default = null) */ public function get($key, $default = null) { - if (!$this->valueStore->has($key)) { - return $default; - } - - return $this->valueStore->get($key); + $value = Kvp::where(['key' => $key])->first(['value']); + return optional($value)->value ?? $default; } /** * @alias store($key,$value) * * @param string $key - * @param mixed $value + * @param string $value * - * @return null + * @return void */ - public function save($key, $value) + public function save(string $key, $value): void { - return $this->store($key, $value); + Kvp::updateOrCreate( + ['key' => $key], + ['value' => $value] + ); } /** * Save a value to the KVP store * - * @param $key - * @param $value - * - * @return null + * @param string $key + * @param string $value */ - public function store($key, $value) + public function store($key, $value): void { - return $this->valueStore->put($key, $value); + $this->save($key, $value); } } diff --git a/composer.json b/composer.json index 162031958..256bd4140 100755 --- a/composer.json +++ b/composer.json @@ -51,7 +51,6 @@ "santigarcor/laratrust": "~6.3", "sebastiaanluca/laravel-helpers": "~6.0", "semver/semver": "~1.1.0", - "spatie/valuestore": "~1.2", "symfony/polyfill-iconv": "~1.22.0", "tivie/php-os-detector": "~1.1.0", "vlucas/phpdotenv": "^5.3.0", diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index 11ec1714e..486f1bf56 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -2,6 +2,7 @@ namespace Tests; +use App\Repositories\KvpRepository; use App\Support\ICAO; use App\Support\Units\Time; use App\Support\Utils; @@ -15,6 +16,24 @@ public function testDates() $this->assertNotNull($carbon); } + /** + * Simple test for KVP + */ + public function testKvp() + { + /** @var KvpRepository $kvpRepo */ + $kvpRepo = app(KvpRepository::class); + $kvpRepo->save('testkey', 'some value'); + $this->assertEquals('some value', $kvpRepo->get('testkey')); + + // test that default value is working + $this->assertEquals('default value', $kvpRepo->get('unknownkey', 'default value')); + + // try saving an integer + $kvpRepo->save('intval', 1); + $this->assertEquals(1, $kvpRepo->get('intval')); + } + /** * @throws \Exception */ From 8640406f03e01f52a2d5af360fe9576e556e08e4 Mon Sep 17 00:00:00 2001 From: nabeelio Date: Fri, 5 Mar 2021 16:55:49 -0500 Subject: [PATCH 2/5] Read kvpstore --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 256bd4140..162031958 100755 --- a/composer.json +++ b/composer.json @@ -51,6 +51,7 @@ "santigarcor/laratrust": "~6.3", "sebastiaanluca/laravel-helpers": "~6.0", "semver/semver": "~1.1.0", + "spatie/valuestore": "~1.2", "symfony/polyfill-iconv": "~1.22.0", "tivie/php-os-detector": "~1.1.0", "vlucas/phpdotenv": "^5.3.0", From 62d0046b6b5d1b5ce3581096f285584fe468e7ea Mon Sep 17 00:00:00 2001 From: nabeelio Date: Tue, 9 Mar 2021 11:11:46 -0500 Subject: [PATCH 3/5] Add web cron ability through API #821 --- app/Database/seeds/settings.yml | 6 +++ app/Exceptions/CronInvalid.php | 37 ++++++++++++++++ .../Admin/MaintenanceController.php | 35 ++++++++++++++++ app/Http/Controllers/Api/FlightController.php | 1 - .../Controllers/Api/MaintenanceController.php | 38 +++++++++++++++++ app/Providers/RouteServiceProvider.php | 8 ++++ app/Repositories/KvpRepository.php | 34 ++++++++------- .../views/admin/maintenance/cron.blade.php | 42 ++++++++++++++++++- tests/ApiTest.php | 18 ++++++++ 9 files changed, 202 insertions(+), 17 deletions(-) create mode 100644 app/Exceptions/CronInvalid.php create mode 100644 app/Http/Controllers/Api/MaintenanceController.php diff --git a/app/Database/seeds/settings.yml b/app/Database/seeds/settings.yml index 4ac3adbdb..b2ba89104 100644 --- a/app/Database/seeds/settings.yml +++ b/app/Database/seeds/settings.yml @@ -361,3 +361,9 @@ options: '' type: 'text' description: 'Discord public channel ID for broadcasat notifications' +- key: 'cron.random_id' + name: 'Cron Randomized ID' + group: 'cron' + value: '' + type: 'hidden' + description: '' diff --git a/app/Exceptions/CronInvalid.php b/app/Exceptions/CronInvalid.php new file mode 100644 index 000000000..e629a3790 --- /dev/null +++ b/app/Exceptions/CronInvalid.php @@ -0,0 +1,37 @@ +getMessage(); + } + + /** + * Return an array with the error details, merged with the RFC7807 response + */ + public function getErrorMetadata(): array + { + return []; + } +} diff --git a/app/Http/Controllers/Admin/MaintenanceController.php b/app/Http/Controllers/Admin/MaintenanceController.php index 3453b24ba..8970e1a58 100644 --- a/app/Http/Controllers/Admin/MaintenanceController.php +++ b/app/Http/Controllers/Admin/MaintenanceController.php @@ -6,6 +6,7 @@ use App\Repositories\KvpRepository; use App\Services\CronService; use App\Services\VersionService; +use App\Support\Utils; use Codedge\Updater\UpdaterManager; use Illuminate\Http\Request; use Illuminate\Support\Facades\Artisan; @@ -34,7 +35,12 @@ public function __construct( public function index() { + // Get the cron URL + $cron_id = setting('cron.random_id'); + $cron_url = empty($cron_id) ? 'Not enabled' : url(route('api.maintenance.cron', $cron_id)); + return view('admin.maintenance.index', [ + 'cron_url' => $cron_url, 'cron_path' => $this->cronSvc->getCronExecString(), 'cron_problem_exists' => $this->cronSvc->cronProblemExists(), 'new_version' => $this->kvpRepo->get('new_version_available', false), @@ -117,4 +123,33 @@ public function update(Request $request) return redirect('/update/downloader'); } + + /** + * Enable the cron, or if it's enabled, change the ID that is used + * + * @param Request $request + */ + public function cron_enable(Request $request) + { + $id = Utils::generateNewId(24); + setting_save('cron.random_id', $id); + + Flash::success('Cron ID renewed!'); + return redirect(route('admin.maintenance.index')); + } + + /** + * Disable the web cron + * + * @param Request $request + * + * @return mixed + */ + public function cron_disable(Request $request) + { + setting_save('cron.random_id', ''); + + Flash::success('Web cron ID disabled!'); + return redirect(route('admin.maintenance.index')); + } } diff --git a/app/Http/Controllers/Api/FlightController.php b/app/Http/Controllers/Api/FlightController.php index c1f186a44..7f51c399d 100644 --- a/app/Http/Controllers/Api/FlightController.php +++ b/app/Http/Controllers/Api/FlightController.php @@ -4,7 +4,6 @@ use App\Contracts\Controller; use App\Exceptions\AssetNotFound; -use App\Exceptions\Unauthorized; use App\Http\Resources\Flight as FlightResource; use App\Http\Resources\Navdata as NavdataResource; use App\Models\SimBrief; diff --git a/app/Http/Controllers/Api/MaintenanceController.php b/app/Http/Controllers/Api/MaintenanceController.php new file mode 100644 index 000000000..491cc9ee1 --- /dev/null +++ b/app/Http/Controllers/Api/MaintenanceController.php @@ -0,0 +1,38 @@ + $output, + ]); + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index aff100a3f..b9f92d0a3 100755 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -392,6 +392,12 @@ private function mapAdminRoutes() Route::match(['post'], 'maintenance/forcecheck', 'MaintenanceController@forcecheck') ->name('maintenance.forcecheck')->middleware('ability:admin,maintenance'); + Route::match(['post'], 'maintenance/cron_enable', 'MaintenanceController@cron_enable') + ->name('maintenance.cron_enable')->middleware('ability:admin,maintenance'); + + Route::match(['post'], 'maintenance/cron_disable', 'MaintenanceController@cron_disable') + ->name('maintenance.cron_disable')->middleware('ability:admin,maintenance'); + // subfleet Route::get('subfleets/export', 'SubfleetController@export') ->name('subfleets.export')->middleware('ability:admin,fleet'); @@ -508,6 +514,8 @@ private function mapApiRoutes() Route::get('pireps/{pirep_id}', 'PirepController@get'); Route::get('pireps/{pirep_id}/acars/geojson', 'AcarsController@acars_geojson'); + Route::get('cron/{id}', 'MaintenanceController@cron')->name('maintenance.cron'); + Route::get('news', 'NewsController@index'); Route::get('status', 'StatusController@status'); Route::get('version', 'StatusController@status'); diff --git a/app/Repositories/KvpRepository.php b/app/Repositories/KvpRepository.php index 246e540e0..131849fa1 100644 --- a/app/Repositories/KvpRepository.php +++ b/app/Repositories/KvpRepository.php @@ -2,13 +2,15 @@ namespace App\Repositories; -use App\Models\Kvp; -use Illuminate\Support\Facades\Cache; +use Spatie\Valuestore\Valuestore; class KvpRepository { + private $valueStore; + public function __construct() { + $this->valueStore = Valuestore::make(config('phpvms.kvp_storage_path')); } /** @@ -32,34 +34,36 @@ public function retrieve($key, $default = null) */ public function get($key, $default = null) { - $value = Kvp::where(['key' => $key])->first(['value']); - return optional($value)->value ?? $default; + if (!$this->valueStore->has($key)) { + return $default; + } + + return $this->valueStore->get($key); } /** * @alias store($key,$value) * * @param string $key - * @param string $value + * @param mixed $value * - * @return void + * @return null */ - public function save(string $key, $value): void + public function save($key, $value) { - Kvp::updateOrCreate( - ['key' => $key], - ['value' => $value] - ); + return $this->store($key, $value); } /** * Save a value to the KVP store * - * @param string $key - * @param string $value + * @param $key + * @param $value + * + * @return null */ - public function store($key, $value): void + public function store($key, $value) { - $this->save($key, $value); + return $this->valueStore->put($key, $value); } } diff --git a/resources/views/admin/maintenance/cron.blade.php b/resources/views/admin/maintenance/cron.blade.php index 1244fdfbf..e80065af9 100644 --- a/resources/views/admin/maintenance/cron.blade.php +++ b/resources/views/admin/maintenance/cron.blade.php @@ -6,7 +6,8 @@
-

A cron must be created that runs every minute calling artisan. Example:

+

A cron must be created that runs every minute calling artisan. An example is below. + See the docs

@@ -20,6 +21,45 @@ @endif
+ +
+ +
+
+
Web Cron
+
+
+

+ If you don't have cron access on your server, you can use a web-cron service to + access this URL every minute. Keep it disabled if you're not using it. It's a + unique ID that can be reset/changed if needed for security. +

+
+
+ + + + + +
+ {{ Form::open(['url' => route('admin.maintenance.cron_enable'), + 'method' => 'post']) }} + {{ Form::button('Enable/Change ID', ['type' => 'submit', 'class' => 'btn btn-success']) }} + {{ Form::close() }} + + {{ Form::open(['url' => route('admin.maintenance.cron_disable'), + 'method' => 'post']) }} + {{ Form::button('Disable', ['type' => 'submit', 'class' => 'btn btn-warning']) }} + {{ Form::close() }} +
+
+
+ + +
+
diff --git a/tests/ApiTest.php b/tests/ApiTest.php index cdbef75bd..74c1020a1 100644 --- a/tests/ApiTest.php +++ b/tests/ApiTest.php @@ -12,6 +12,7 @@ use App\Models\Subfleet; use App\Models\User; use App\Services\FareService; +use App\Support\Utils; use Exception; use function random_int; @@ -312,4 +313,21 @@ public function testGetUser() $this->assertNotNull($user); $this->assertTrue(strpos($user['avatar'], 'gravatar') !== -1); } + + /** + * Test that the web cron runs + */ + public function testWebCron() + { + $this->updateSetting('cron.random_id', ''); + $this->get('/api/cron/sdf')->assertStatus(400); + + $id = Utils::generateNewId(24); + $this->updateSetting('cron.random_id', $id); + + $this->get('/api/cron/sdf')->assertStatus(400); + + $res = $this->get('/api/cron/'.$id); + $res->assertStatus(200); + } } From 06693d83fa8ee3a19ab68cd420d88940a69408cd Mon Sep 17 00:00:00 2001 From: nabeelio Date: Tue, 9 Mar 2021 11:19:48 -0500 Subject: [PATCH 4/5] Style fixes --- app/Http/Controllers/Api/MaintenanceController.php | 3 --- app/Models/Kvp.php | 3 --- 2 files changed, 6 deletions(-) diff --git a/app/Http/Controllers/Api/MaintenanceController.php b/app/Http/Controllers/Api/MaintenanceController.php index 491cc9ee1..053873eb2 100644 --- a/app/Http/Controllers/Api/MaintenanceController.php +++ b/app/Http/Controllers/Api/MaintenanceController.php @@ -1,7 +1,4 @@ Date: Tue, 9 Mar 2021 11:24:09 -0500 Subject: [PATCH 5/5] Fix text --- app/Http/Controllers/Admin/MaintenanceController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Admin/MaintenanceController.php b/app/Http/Controllers/Admin/MaintenanceController.php index 8970e1a58..dde5d9956 100644 --- a/app/Http/Controllers/Admin/MaintenanceController.php +++ b/app/Http/Controllers/Admin/MaintenanceController.php @@ -134,7 +134,7 @@ public function cron_enable(Request $request) $id = Utils::generateNewId(24); setting_save('cron.random_id', $id); - Flash::success('Cron ID renewed!'); + Flash::success('Web cron refreshed!'); return redirect(route('admin.maintenance.index')); } @@ -149,7 +149,7 @@ public function cron_disable(Request $request) { setting_save('cron.random_id', ''); - Flash::success('Web cron ID disabled!'); + Flash::success('Web cron disabled!'); return redirect(route('admin.maintenance.index')); } }