From bd30b1f900755cfe6755445be2a6e690a71db6c6 Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Fri, 30 Mar 2018 11:08:53 -0500 Subject: [PATCH] Check for departure airport restrictions #221 --- ...017_06_07_014930_create_settings_table.php | 2 +- app/Exceptions/AircraftNotAtAirport.php | 13 +++ app/Exceptions/AircraftPermissionDenied.php | 18 +---- app/Exceptions/InternalError.php | 9 ++- app/Exceptions/UserNotAtAirport.php | 14 ++++ app/Http/Controllers/Api/PirepController.php | 27 +++++-- .../Controllers/Frontend/PirepController.php | 35 +++++++- app/Interfaces/Controller.php | 12 +++ app/Models/Pirep.php | 5 +- app/Models/User.php | 2 + app/Services/FlightService.php | 2 +- tests/AcarsTest.php | 79 +++++++++++++++++++ 12 files changed, 189 insertions(+), 29 deletions(-) create mode 100644 app/Exceptions/AircraftNotAtAirport.php create mode 100644 app/Exceptions/UserNotAtAirport.php diff --git a/app/Database/migrations/2017_06_07_014930_create_settings_table.php b/app/Database/migrations/2017_06_07_014930_create_settings_table.php index ec2ccef1..5c9deb50 100644 --- a/app/Database/migrations/2017_06_07_014930_create_settings_table.php +++ b/app/Database/migrations/2017_06_07_014930_create_settings_table.php @@ -169,7 +169,7 @@ class CreateSettingsTable extends Migration 'description' => 'Aircraft that can be flown are restricted to a user\'s rank', ]); - $this->addSetting('pireps.only_aircraft_at_dep_airport', [ + $this->addSetting('pireps.only_aircraft_at_dpt_airport', [ 'name' => 'Restrict Aircraft At Departure', 'group' => 'pireps', 'value' => false, diff --git a/app/Exceptions/AircraftNotAtAirport.php b/app/Exceptions/AircraftNotAtAirport.php new file mode 100644 index 00000000..3bce547e --- /dev/null +++ b/app/Exceptions/AircraftNotAtAirport.php @@ -0,0 +1,13 @@ +errors()->add($field ?? static::FLASH_FIELD_NAME, $message); + $validator->errors()->add( + $field ?? static::FIELD, + $message ?? static::MESSAGE); parent::__construct($validator); } diff --git a/app/Exceptions/UserNotAtAirport.php b/app/Exceptions/UserNotAtAirport.php new file mode 100644 index 00000000..5ec73ee5 --- /dev/null +++ b/app/Exceptions/UserNotAtAirport.php @@ -0,0 +1,14 @@ +current_airport_id !== $pirep->dpt_airport_id) + { + throw new UserNotAtAirport(); + } + # See if this user is allowed to fly this aircraft - if (setting('pireps.restrict_aircraft_to_rank', false)) { - $can_use_ac = $this->userSvc->aircraftAllowed($user, $pirep->aircraft_id); - if (!$can_use_ac) { - throw new AircraftPermissionDenied(); - } + if (setting('pireps.restrict_aircraft_to_rank', false) + && !$this->userSvc->aircraftAllowed($user, $pirep->aircraft_id)) + { + throw new AircraftPermissionDenied(); + } + + # See if this aircraft is at the departure airport + if (setting('pireps.only_aircraft_at_dpt_airport') + && $pirep->aircraft_id !== $pirep->dpt_airport_id) + { + throw new AircraftNotAtAirport(); } # Find if there's a duplicate, if so, let's work on that diff --git a/app/Http/Controllers/Frontend/PirepController.php b/app/Http/Controllers/Frontend/PirepController.php index 446afa55..f3f3885f 100644 --- a/app/Http/Controllers/Frontend/PirepController.php +++ b/app/Http/Controllers/Frontend/PirepController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Frontend; +use App\Exceptions\UserNotAtAirport; use App\Facades\Utils; use App\Http\Requests\CreatePirepRequest; use App\Http\Requests\UpdatePirepRequest; @@ -241,12 +242,40 @@ class PirepController extends Controller $pirep = new Pirep($request->post()); $pirep->user_id = Auth::user()->id; + # Are they allowed at this airport? + if (setting('pilots.only_flights_from_current') + && Auth::user()->current_airport_id !== $pirep->dpt_airport_id) { + return $this->flashError( + 'You are currently not at the departure airport!', + 'frontend.pireps.create' + ); + } + + # Can they fly this aircraft? + if (setting('pireps.restrict_aircraft_to_rank', false) + && !$this->userSvc->aircraftAllowed(Auth::user(), $pirep->aircraft_id)) { + return $this->flashError( + 'You are not allowed to fly this aircraft!', + 'frontend.pireps.create' + ); + } + + # is the aircraft in the right place? + if (setting('pireps.only_aircraft_at_dpt_airport') + && $pirep->aircraft_id !== $pirep->dpt_airport_id) { + return $this->flashError( + 'This aircraft is not positioned at the departure airport!', + 'frontend.pireps.create' + ); + } + # Make sure this isn't a duplicate $dupe_pirep = $this->pirepSvc->findDuplicate($pirep); if ($dupe_pirep !== false) { - flash()->error('This PIREP has already been filed.'); - - return redirect(route('frontend.pireps.create'))->withInput(); + return $this->flashError( + 'This PIREP has already been filed.', + 'frontend.pireps.create' + ); } // Any special fields diff --git a/app/Interfaces/Controller.php b/app/Interfaces/Controller.php index 98c68583..5967c4c7 100755 --- a/app/Interfaces/Controller.php +++ b/app/Interfaces/Controller.php @@ -15,6 +15,18 @@ abstract class Controller extends \Illuminate\Routing\Controller { use AuthorizesRequests, DispatchesJobs, ValidatesRequests; + /** + * Write a error to the flash and redirect the user to a route + * @param $message + * @param $route + * @return mixed + */ + public function flashError($message, $route) + { + flash()->error($message); + return redirect(route($route))->withInput(); + } + /** * Shortcut function to get the attributes from a request while running the validations * @param Request $request diff --git a/app/Models/Pirep.php b/app/Models/Pirep.php index 6a47a477..9cb94a65 100644 --- a/app/Models/Pirep.php +++ b/app/Models/Pirep.php @@ -20,10 +20,13 @@ use PhpUnitsOfMeasure\Exception\NonStringUnitName; * @property string route_leg * @property integer airline_id * @property integer user_id + * @property integer aircraft_id * @property Aircraft aircraft * @property Airline airline * @property Airport arr_airport - * @property Airport dep_airport + * @property string arr_airport_id + * @property Airport dpt_airport + * @property string dpt_airport_id * @property integer block_time * @property integer flight_time In minutes * @property User user diff --git a/app/Models/User.php b/app/Models/User.php index a1e5a784..78ab6f7b 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -15,6 +15,8 @@ use Laratrust\Traits\LaratrustUserTrait; * @property string $email * @property string $password * @property string $api_key + * @property string current_airport_id + * @property string home_airport_id * @property Flight[] $flights * @property string $flight_time * @property string $remember_token diff --git a/app/Services/FlightService.php b/app/Services/FlightService.php index 78ec454b..af26a857 100644 --- a/app/Services/FlightService.php +++ b/app/Services/FlightService.php @@ -83,7 +83,7 @@ class FlightService extends Service /** * Only allow aircraft that are at the current departure airport */ - if (setting('pireps.only_aircraft_at_dep_airport', false)) { + if (setting('pireps.only_aircraft_at_dpt_airport', false)) { foreach ($subfleets as $subfleet) { $subfleet->aircraft = $subfleet->aircraft->filter( function ($aircraft, $i) use ($flight) { diff --git a/tests/AcarsTest.php b/tests/AcarsTest.php index 7462af8f..c091dc1e 100644 --- a/tests/AcarsTest.php +++ b/tests/AcarsTest.php @@ -92,6 +92,85 @@ class AcarsTest extends TestCase } + /** + * Make sure an error is thrown if the pilot is not at the current airport + */ + public function testPilotNotAtAirport(): void + { + $this->settingsRepo->store('pilots.only_flights_from_current', true); + $this->settingsRepo->store('pireps.restrict_aircraft_to_rank', false); + + $this->user = factory(App\Models\User::class)->create([ + 'curr_airport_id' => 'KJFK', + ]); + + $airport = factory(App\Models\Airport::class)->create(); + $airline = factory(App\Models\Airline::class)->create(); + $aircraft = factory(App\Models\Aircraft::class)->create(); + + /** + * INVALID AIRLINE_ID FIELD + */ + $uri = '/api/pireps/prefile'; + $pirep = [ + 'airline_id' => $airline->id, + 'aircraft_id' => $aircraft->id, + 'dpt_airport_id' => $airport->icao, + 'arr_airport_id' => $airport->icao, + 'flight_number' => '6000', + 'level' => 38000, + 'planned_flight_time' => 120, + 'route' => 'POINTA POINTB', + 'source_name' => 'phpunit', + ]; + + $response = $this->post($uri, $pirep); + $response->assertStatus(400); + $body = $response->json(); + $this->assertEquals(\App\Exceptions\UserNotAtAirport::MESSAGE, $body['error']['message']); + } + + /** + * Make sure an error is thrown if the pilot is not at the current airport + */ + public function testAircraftNotAtAirport(): void + { + $this->settingsRepo->store('pireps.only_aircraft_at_dpt_airport', true); + $this->settingsRepo->store('pireps.restrict_aircraft_to_rank', false); + $this->settingsRepo->store('pireps.restrict_aircraft_to_rank', false); + + $this->user = factory(App\Models\User::class)->create([ + 'curr_airport_id' => 'KJFK', + ]); + + $airport = factory(App\Models\Airport::class)->create(); + $airline = factory(App\Models\Airline::class)->create(); + $aircraft = factory(App\Models\Aircraft::class)->create([ + 'airport_id' => 'KAUS' + ]); + + /** + * INVALID AIRLINE_ID FIELD + */ + $uri = '/api/pireps/prefile'; + $pirep = [ + 'airline_id' => $airline->id, + 'aircraft_id' => $aircraft->id, + 'dpt_airport_id' => $airport->icao, + 'arr_airport_id' => $airport->icao, + 'flight_number' => '6000', + 'level' => 38000, + 'planned_flight_time' => 120, + 'route' => 'POINTA POINTB', + 'source_name' => 'phpunit', + ]; + + $response = $this->post($uri, $pirep); + $response->assertStatus(400); + $body = $response->json(); + $this->assertEquals(\App\Exceptions\AircraftNotAtAirport::MESSAGE, $body['error']['message']); + } + /** * Post a PIREP into a PREFILE state and post ACARS */