Compare commits
12 Commits
snyk-fix-8
...
patch-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db34d0e3e7 | ||
|
|
fffbab7201 | ||
|
|
b9e7a2efc9 | ||
|
|
76a2a16fa6 | ||
|
|
73f88fce0c | ||
|
|
cfbd1c901a | ||
|
|
e70ee5aa6f | ||
|
|
617813bdbf | ||
|
|
f1c54bcc7c | ||
|
|
d94d754961 | ||
|
|
9abfbd6c8c | ||
|
|
97fc1dd43d |
19
app/Database/migrations/2021_03_05_044305_add_kvp_table.php
Normal file
19
app/Database/migrations/2021_03_05_044305_add_kvp_table.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
use App\Contracts\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* Add a hub to the subfleet is
|
||||
*/
|
||||
class AddKvpTable extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::create('kvp', function (Blueprint $table) {
|
||||
$table->string('key')->index();
|
||||
$table->string('value');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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: ''
|
||||
|
||||
37
app/Exceptions/CronInvalid.php
Normal file
37
app/Exceptions/CronInvalid.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
class CronInvalid extends AbstractHttpException
|
||||
{
|
||||
public const MESSAGE = 'Cron ID is disabled or invalid';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(400, static::MESSAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the RFC 7807 error type (without the URL root)
|
||||
*/
|
||||
public function getErrorType(): string
|
||||
{
|
||||
return 'cron-invalid';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the detailed error string
|
||||
*/
|
||||
public function getErrorDetails(): string
|
||||
{
|
||||
return $this->getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array with the error details, merged with the RFC7807 response
|
||||
*/
|
||||
public function getErrorMetadata(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ use App\Contracts\Controller;
|
||||
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 @@ class MaintenanceController extends Controller
|
||||
|
||||
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 @@ class MaintenanceController extends Controller
|
||||
|
||||
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('Web cron refreshed!');
|
||||
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 disabled!');
|
||||
return redirect(route('admin.maintenance.index'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class SettingsController extends Controller
|
||||
*/
|
||||
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', [
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Http\Controllers\Api;
|
||||
|
||||
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;
|
||||
|
||||
35
app/Http/Controllers/Api/MaintenanceController.php
Normal file
35
app/Http/Controllers/Api/MaintenanceController.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Contracts\Controller;
|
||||
use App\Exceptions\CronInvalid;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
class MaintenanceController extends Controller
|
||||
{
|
||||
/**
|
||||
* Run the cron job from the web
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $id The ID passed in for the cron
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function cron(Request $request, string $id)
|
||||
{
|
||||
$cron_id = setting('cron.random_id');
|
||||
if (empty($cron_id) || $id !== $cron_id) {
|
||||
throw new CronInvalid();
|
||||
}
|
||||
|
||||
$output = '';
|
||||
Artisan::call('schedule:run');
|
||||
$output .= trim(Artisan::output());
|
||||
|
||||
return response([
|
||||
'content' => $output,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ class ApiAuth implements Middleware
|
||||
return $this->unauthorized('User not found with key "'.$api_key.'"');
|
||||
}
|
||||
|
||||
if ($user->state !== UserState::ACTIVE) {
|
||||
if ($user->state !== UserState::ACTIVE && $user->state !== UserState::ON_LEAVE) {
|
||||
return $this->unauthorized('User is not ACTIVE, please contact an administrator');
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,13 @@ class Pirep extends Resource
|
||||
$distance = new Distance($res['distance'], config('phpvms.internal_units.distance'));
|
||||
$res['distance'] = $distance->getResponseUnits();
|
||||
|
||||
if (!array_key_exists('block_fuel', $res)) {
|
||||
$res['block_fuel'] = 0;
|
||||
}
|
||||
|
||||
$block_fuel = new Fuel($res['block_fuel'], config('phpvms.internal_units.fuel'));
|
||||
$res['block_fuel'] = $block_fuel->getResponseUnits();
|
||||
|
||||
if (!array_key_exists('fuel_used', $res)) {
|
||||
$res['fuel_used'] = 0;
|
||||
}
|
||||
|
||||
23
app/Models/Kvp.php
Normal file
23
app/Models/Kvp.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Contracts\Model;
|
||||
|
||||
/**
|
||||
* @property string key
|
||||
* @property string value
|
||||
*/
|
||||
class Kvp extends Model
|
||||
{
|
||||
public $table = 'kvp';
|
||||
public $timestamps = false;
|
||||
public $incrementing = false;
|
||||
|
||||
protected $keyType = 'string';
|
||||
|
||||
public $fillable = [
|
||||
'key',
|
||||
'value',
|
||||
];
|
||||
}
|
||||
@@ -326,6 +326,22 @@ class Pirep extends Model
|
||||
return $field_values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of block fuel
|
||||
*
|
||||
* @param $value
|
||||
*/
|
||||
public function setBlockFuelAttribute($value): void
|
||||
{
|
||||
if ($value instanceof Fuel) {
|
||||
$this->attributes['block_fuel'] = $value->toUnit(
|
||||
config('phpvms.internal_units.fuel')
|
||||
);
|
||||
} else {
|
||||
$this->attributes['block_fuel'] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of fuel used
|
||||
*
|
||||
|
||||
@@ -10,6 +10,7 @@ use Illuminate\Support\Collection;
|
||||
* @property int $user_id The user that generated this
|
||||
* @property string $flight_id Optional, if attached to a flight, removed if attached to PIREP
|
||||
* @property string $pirep_id Optional, if attached to a PIREP, removed if attached to flight
|
||||
* @property string $aircraft_id The aircraft this is for
|
||||
* @property string $acars_xml
|
||||
* @property string $ofp_xml
|
||||
* @property string $ofp_html
|
||||
|
||||
@@ -392,6 +392,12 @@ class RouteServiceProvider extends ServiceProvider
|
||||
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');
|
||||
@@ -459,7 +465,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
Route::group([
|
||||
'as' => 'modules.',
|
||||
'prefix' => 'modules',
|
||||
'middleware' => ['ability:admin, modules'],
|
||||
'middleware' => ['ability:admin,modules'],
|
||||
], function () {
|
||||
|
||||
//Modules Index
|
||||
@@ -508,6 +514,8 @@ class RouteServiceProvider extends ServiceProvider
|
||||
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');
|
||||
|
||||
@@ -1772,7 +1772,7 @@ class Metar implements \ArrayAccess
|
||||
*/
|
||||
private function calculate_wind_chill($temperature_f): void
|
||||
{
|
||||
if ($temperature_f < 51 && $this->result['wind_speed'] !== 0) {
|
||||
if ($temperature_f < 51 && $this->result['wind_speed'] && $this->result['wind_speed'] !== 0) {
|
||||
$windspeed = $this->result['wind_speed']->toUnit('mph');
|
||||
if ($windspeed > 3) {
|
||||
$chill_f = 35.74 + 0.6215 * $temperature_f - 35.75 * ($windspeed ** 0.16);
|
||||
|
||||
@@ -61,7 +61,8 @@
|
||||
"madnest/madzipper": "^1.1.0",
|
||||
"elcobvg/laravel-opcache": "^0.4.1",
|
||||
"laravel/legacy-factories": "^1.1",
|
||||
"fakerphp/faker": "^1.13"
|
||||
"fakerphp/faker": "^1.13",
|
||||
"wildbit/swiftmailer-postmark": "^3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-debugbar": "^3.5",
|
||||
|
||||
46
composer.lock
generated
46
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "9c810647ebea1e88f066d7c0679d9b4c",
|
||||
"content-hash": "4180601e7a77313a007604954b01f071",
|
||||
"packages": [
|
||||
{
|
||||
"name": "akaunting/money",
|
||||
@@ -9348,6 +9348,50 @@
|
||||
},
|
||||
"time": "2020-12-14T12:45:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "wildbit/swiftmailer-postmark",
|
||||
"version": "3.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wildbit/swiftmailer-postmark.git",
|
||||
"reference": "44ccab7834de8b220d292647ecb2cb683f9962ee"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/wildbit/swiftmailer-postmark/zipball/44ccab7834de8b220d292647ecb2cb683f9962ee",
|
||||
"reference": "44ccab7834de8b220d292647ecb2cb683f9962ee",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6.0|^7.0",
|
||||
"swiftmailer/swiftmailer": "^6.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Postmark\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Postmark",
|
||||
"email": "support@postmarkapp.com"
|
||||
}
|
||||
],
|
||||
"description": "A Swiftmailer Transport for Postmark.",
|
||||
"support": {
|
||||
"issues": "https://github.com/wildbit/swiftmailer-postmark/issues",
|
||||
"source": "https://github.com/wildbit/swiftmailer-postmark/tree/3.3.0"
|
||||
},
|
||||
"time": "2020-09-10T10:54:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "willdurand/geocoder",
|
||||
"version": "4.4.0",
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
</h6>
|
||||
<div class="row" style="padding-top: 5px">
|
||||
<div class="col-sm-12">
|
||||
<p>A cron must be created that runs every minute calling artisan. Example:</p>
|
||||
<p>A cron must be created that runs every minute calling artisan. An example is below.
|
||||
<strong><a href="{{ docs_link('cron') }}" target="_blank">See the docs</a></strong></p>
|
||||
<label style="width: 100%">
|
||||
<input type="text" value="{{ $cron_path }}" class="form-control" style="width: 100%"/>
|
||||
</label>
|
||||
@@ -20,6 +21,45 @@
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="row" style="padding-top: 5px">
|
||||
<div class="col-sm-12">
|
||||
<h5>Web Cron</h5>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-6 pull-right">
|
||||
<table class="table-condensed">
|
||||
<tr class="text-right">
|
||||
<td style="padding-right: 10px;" class="text-right">
|
||||
{{ Form::open(['url' => route('admin.maintenance.cron_enable'),
|
||||
'method' => 'post']) }}
|
||||
{{ Form::button('Enable/Change ID', ['type' => 'submit', 'class' => 'btn btn-success']) }}
|
||||
{{ Form::close() }}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{ Form::open(['url' => route('admin.maintenance.cron_disable'),
|
||||
'method' => 'post']) }}
|
||||
{{ Form::button('Disable', ['type' => 'submit', 'class' => 'btn btn-warning']) }}
|
||||
{{ Form::close() }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
|
||||
<label style="width: 100%">
|
||||
<input type="text" value="{{ $cron_url }}" class="form-control" style="width: 100%"/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ use App\Models\News;
|
||||
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 @@ class ApiTest extends TestCase
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +151,19 @@ class MetarTest extends TestCase
|
||||
$this->assertEquals('Few at 1500 feet; few at 25000 feet', $metar['clouds_report_ft']);
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/nabeelio/phpvms/issues/1071
|
||||
*/
|
||||
public function testMetarWindSpeedChill()
|
||||
{
|
||||
$metar = 'EKYT 091020Z /////KT CAVOK 02/M03 Q1019';
|
||||
$metar = Metar::parse($metar);
|
||||
|
||||
$this->assertEquals('VFR', $metar['category']);
|
||||
$this->assertNull($metar['wind_speed']);
|
||||
$this->assertEquals(6.21, $metar['visibility']['mi']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visibility in KM not parsed
|
||||
*
|
||||
|
||||
@@ -21,6 +21,7 @@ use App\Services\BidService;
|
||||
use App\Services\FlightService;
|
||||
use App\Services\PirepService;
|
||||
use App\Services\UserService;
|
||||
use App\Support\Units\Fuel;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
@@ -164,6 +165,8 @@ class PIREPTest extends TestCase
|
||||
$body = $response->json('data');
|
||||
|
||||
// Check that it has the fuel units
|
||||
$this->assertHasKeys($body['block_fuel'], ['lbs', 'kg']);
|
||||
$this->assertEquals($pirep->block_fuel, $body['block_fuel']['lbs']);
|
||||
$this->assertHasKeys($body['fuel_used'], ['lbs', 'kg']);
|
||||
$this->assertEquals($pirep->fuel_used, $body['fuel_used']['lbs']);
|
||||
|
||||
@@ -174,6 +177,24 @@ class PIREPTest extends TestCase
|
||||
// Check the planned_distance field
|
||||
$this->assertHasKeys($body['planned_distance'], ['km', 'nmi', 'mi']);
|
||||
$this->assertEquals($pirep->planned_distance, $body['planned_distance']['nmi']);
|
||||
|
||||
//Check conversion on save
|
||||
$val = random_int(1000, 9999999);
|
||||
$pirep->block_fuel = $val;
|
||||
$pirep->fuel_used = $val;
|
||||
// no conversion with plain numbers
|
||||
$this->assertEquals($pirep->block_fuel, $val);
|
||||
$this->assertEquals($pirep->fuel_used, $val);
|
||||
// no conversion with lbs
|
||||
$pirep->block_fuel = new Fuel($val, 'lbs');
|
||||
$this->assertEquals($pirep->block_fuel, $val);
|
||||
$pirep->fuel_used = new Fuel($val, 'lbs');
|
||||
$this->assertEquals($pirep->fuel_used, $val);
|
||||
// conversion of kg to lbs
|
||||
$pirep->block_fuel = new Fuel($val, 'kg');
|
||||
$this->assertEquals($pirep->block_fuel, (new Fuel($val, 'kg'))->toUnit('lbs'));
|
||||
$pirep->fuel_used = new Fuel($val, 'kg');
|
||||
$this->assertEquals($pirep->fuel_used, (new Fuel($val, 'kg'))->toUnit('lbs'));
|
||||
}
|
||||
|
||||
public function testGetUserPireps()
|
||||
|
||||
@@ -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 @@ class UtilsTest extends TestCase
|
||||
$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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user