From 4e43223f3a010b80e303531e4fcb572f2445f07a Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Tue, 20 Feb 2018 12:59:49 -0600 Subject: [PATCH] Refuse pirep prefile is user not allowed to use aircraft #170 --- app/Http/Controllers/Api/PirepController.php | 21 +++++- app/Models/Aircraft.php | 5 +- app/Services/UserService.php | 20 ++++- tests/AcarsTest.php | 78 +++++++++++++++----- tests/PIREPTest.php | 7 +- tests/TestCase.php | 4 +- tests/TestData.php | 26 ++++++- tests/UserTest.php | 18 ++--- 8 files changed, 137 insertions(+), 42 deletions(-) diff --git a/app/Http/Controllers/Api/PirepController.php b/app/Http/Controllers/Api/PirepController.php index 366ac465..ca810cdc 100644 --- a/app/Http/Controllers/Api/PirepController.php +++ b/app/Http/Controllers/Api/PirepController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\Api; use App\Http\Requests\Acars\EventRequest; use App\Http\Requests\Acars\UpdateRequest; use App\Models\Enums\PirepSource; +use App\Services\UserService; use Auth; use Log; use Illuminate\Http\Request; @@ -40,7 +41,8 @@ class PirepController extends RestController protected $acarsRepo, $geoSvc, $pirepRepo, - $pirepSvc; + $pirepSvc, + $userSvc; /** * PirepController constructor. @@ -53,12 +55,14 @@ class PirepController extends RestController AcarsRepository $acarsRepo, GeoService $geoSvc, PirepRepository $pirepRepo, - PIREPService $pirepSvc + PIREPService $pirepSvc, + UserService $userSvc ) { $this->acarsRepo = $acarsRepo; $this->geoSvc = $geoSvc; $this->pirepRepo = $pirepRepo; $this->pirepSvc = $pirepSvc; + $this->userSvc = $userSvc; } /** @@ -111,19 +115,30 @@ class PirepController extends RestController * * @param PrefileRequest $request * @return PirepResource + * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException */ public function prefile(PrefileRequest $request) { Log::info('PIREP Prefile, user '.Auth::id(), $request->post()); + $user = Auth::user(); + $attrs = $request->post(); - $attrs['user_id'] = Auth::id(); + $attrs['user_id'] = $user->id; $attrs['source'] = PirepSource::ACARS; $attrs['state'] = PirepState::IN_PROGRESS; $attrs['status'] = PirepStatus::PREFILE; $pirep = new Pirep($attrs); + # 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 BadRequestHttpException('User is not allowed to fly this aircraft'); + } + } + # Find if there's a duplicate, if so, let's work on that $dupe_pirep = $this->pirepSvc->findDuplicate($pirep); if($dupe_pirep !== false) { diff --git a/app/Models/Aircraft.php b/app/Models/Aircraft.php index b75be6a8..d53e4ba1 100644 --- a/app/Models/Aircraft.php +++ b/app/Models/Aircraft.php @@ -25,8 +25,9 @@ class Aircraft extends BaseModel * @var array */ protected $casts = [ - 'zfw' => 'float', - 'active' => 'boolean', + 'subfleet_id' => 'integer', + 'zfw' => 'float', + 'active' => 'boolean', ]; /** diff --git a/app/Services/UserService.php b/app/Services/UserService.php index 6b813020..eddbaf21 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -2,6 +2,7 @@ namespace App\Services; +use App\Repositories\AircraftRepository; use App\Repositories\SubfleetRepository; use Illuminate\Support\Collection; use Log; @@ -16,15 +17,17 @@ use App\Models\Enums\UserState; class UserService extends BaseService { - protected $subfleetRepo; + protected $aircraftRepo, $subfleetRepo; /** * UserService constructor. * @param SubfleetRepository $subfleetRepo */ public function __construct( + AircraftRepository $aircraftRepo, SubfleetRepository $subfleetRepo ) { + $this->aircraftRepo = $aircraftRepo; $this->subfleetRepo = $subfleetRepo; } @@ -83,6 +86,21 @@ class UserService extends BaseService return $subfleets->with('aircraft')->get(); } + /** + * Return a bool if a user is allowed to fly the current aircraft + * @param $user + * @param $aircraft_id + * @return bool + */ + public function aircraftAllowed($user, $aircraft_id) + { + $aircraft = $this->aircraftRepo->find($aircraft_id, ['subfleet_id']); + $subfleets = $this->getAllowableSubfleets($user); + $subfleet_ids = $subfleets->pluck('id')->toArray(); + + return \in_array($aircraft->subfleet_id, $subfleet_ids, true); + } + /** * Change the user's state. PENDING to ACCEPTED, etc * Send out an email diff --git a/tests/AcarsTest.php b/tests/AcarsTest.php index 599cc715..bedc40a0 100644 --- a/tests/AcarsTest.php +++ b/tests/AcarsTest.php @@ -2,6 +2,7 @@ use App\Models\Enums\PirepState; use App\Models\Enums\PirepStatus; +use Tests\TestData; /** * Test API calls and authentication, etc @@ -88,11 +89,16 @@ class AcarsTest extends TestCase */ public function testAcarsUpdates() { - $this->user = factory(App\Models\User::class)->create(); + $subfleet = $this->createSubfleetWithAircraft(2); + $rank = $this->createRank(10, [$subfleet['subfleet']->id]); + + $this->user = factory(App\Models\User::class)->create([ + 'rank_id' => $rank->id + ]); $airport = factory(App\Models\Airport::class)->create(); $airline = factory(App\Models\Airline::class)->create(); - $aircraft = factory(App\Models\Aircraft::class)->create(); + $aircraft = $subfleet['aircraft']->random(); $uri = '/api/pireps/prefile'; $pirep = [ @@ -217,13 +223,56 @@ class AcarsTest extends TestCase $this->assertCount(1, $comments); } + /** + * Test aircraft is allowed + */ + public function testAircraftAllowed() + { + $this->settingsRepo->store('pireps.restrict_aircraft_to_rank', true); + + $airport = factory(App\Models\Airport::class)->create(); + $airline = factory(App\Models\Airline::class)->create(); + + # Add subfleets and aircraft, but also add another set of subfleets + $subfleetA = $this->createSubfleetWithAircraft(1); + + // User not allowed aircraft from this subfleet + $subfleetB = $this->createSubfleetWithAircraft(1); + + $rank = $this->createRank(10, [$subfleetA['subfleet']->id]); + + $this->user = factory(App\Models\User::class)->create([ + 'rank_id' => $rank->id, + ]); + + $uri = '/api/pireps/prefile'; + $pirep = [ + 'airline_id' => $airline->id, + 'aircraft_id' => $subfleetB['aircraft']->random()->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' => 'Unit test' + ]; + + $response = $this->post($uri, $pirep); + $response->assertStatus(400); + + // Try refiling with a valid aircraft + $pirep['aircraft_id'] = $subfleetA['aircraft']->random()->id; + $response = $this->post($uri, $pirep); + $response->assertStatus(201); + } + /** * Test publishing multiple, batched updates */ public function testMultipleAcarsPositionUpdates() { - $this->user = factory(App\Models\User::class)->create(); - $pirep = factory(App\Models\Pirep::class)->make()->toArray(); + $pirep = $this->createPirep()->toArray(); $uri = '/api/pireps/prefile'; $response = $this->post($uri, $pirep); @@ -275,8 +324,7 @@ class AcarsTest extends TestCase */ public function testAcarsIsoDate() { - $this->user = factory(App\Models\User::class)->create(); - $pirep = factory(App\Models\Pirep::class)->make()->toArray(); + $pirep = $this->createPirep()->toArray(); $uri = '/api/pireps/prefile'; $response = $this->post($uri, $pirep); @@ -298,8 +346,7 @@ class AcarsTest extends TestCase */ public function testAcarsInvalidRoutePost() { - $this->user = factory(App\Models\User::class)->create(); - $pirep = factory(App\Models\Pirep::class)->make()->toArray(); + $pirep = $this->createPirep()->toArray(); $uri = '/api/pireps/prefile'; $response = $this->post($uri, $pirep); @@ -321,8 +368,7 @@ class AcarsTest extends TestCase public function testAcarsLogPost() { - $this->user = factory(App\Models\User::class)->create(); - $pirep = factory(App\Models\Pirep::class)->make()->toArray(); + $pirep = $this->createPirep()->toArray(); $uri = '/api/pireps/prefile'; $response = $this->post($uri, $pirep); @@ -362,8 +408,7 @@ class AcarsTest extends TestCase */ public function testAcarsRoutePost() { - $this->user = factory(App\Models\User::class)->create(); - $pirep = factory(App\Models\Pirep::class)->make()->toArray(); + $pirep = $this->createPirep()->toArray(); $uri = '/api/pireps/prefile'; $response = $this->post($uri, $pirep); @@ -418,16 +463,9 @@ class AcarsTest extends TestCase */ public function testDuplicatePirep() { - $this->user = factory(App\Models\User::class)->create(); + $pirep = $this->createPirep()->toArray(); $uri = '/api/pireps/prefile'; - - $this->user = factory(App\Models\User::class)->create(); - $pirep = factory(App\Models\Pirep::class)->make([ - 'airline_id' => $this->user->airline_id, - 'user_id' => $this->user->id, - ])->toArray(); - $response = $this->post($uri, $pirep); $response->assertStatus(201); $pirep_id = $response->json()['data']['id']; diff --git a/tests/PIREPTest.php b/tests/PIREPTest.php index a830cd77..e309ebc7 100644 --- a/tests/PIREPTest.php +++ b/tests/PIREPTest.php @@ -10,13 +10,15 @@ use App\Models\Enums\PirepState; class PIREPTest extends TestCase { - protected $pirepSvc; + protected $pirepSvc, $settingsRepo; public function setUp() { parent::setUp(); // TODO: Change the autogenerated stub $this->addData('base'); + $this->pirepSvc = app('App\Services\PIREPService'); + $this->settingsRepo = app(SettingRepository::class); } protected function createNewRoute() @@ -246,8 +248,7 @@ class PIREPTest extends TestCase */ public function testCancelViaAPI() { - $this->user = factory(App\Models\User::class)->create(); - $pirep = factory(App\Models\Pirep::class)->make(['id'=>''])->toArray(); + $pirep = $this->createPirep()->toArray(); $uri = '/api/pireps/prefile'; $response = $this->post($uri, $pirep); diff --git a/tests/TestCase.php b/tests/TestCase.php index e62aa917..1bf55beb 100755 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,13 +1,15 @@ createSubfleetWithAircraft(2); + $rank = $this->createRank(10, [$subfleet['subfleet']->id]); + $this->user = factory(\App\Models\User::class)->create([ + 'rank_id' => $rank->id + ]); + + // Return a Pirep model + return factory(\App\Models\Pirep::class)->make([ + 'aircraft_id' => $subfleet['aircraft']->random()->id + ]); + } + /** * Create a rank and associate the given subfleet IDs with it * @param int $hours * @param array $subfleet_ids * @return mixed */ - public static function createRank($hours=0, $subfleet_ids=[]) + public function createRank($hours=0, array $subfleet_ids) { $attrs = []; @@ -32,9 +51,10 @@ class TestData /** * Create a subfleet with a number of aircraft assigned * @param null $aircraft_count + * @param null $airport_id * @return mixed */ - public static function createSubfleetWithAircraft($aircraft_count = null, $airport_id=null) + public function createSubfleetWithAircraft($aircraft_count = null, $airport_id=null) { $subfleet = factory(\App\Models\Subfleet::class)->create(); diff --git a/tests/UserTest.php b/tests/UserTest.php index cd97f32c..64fedd13 100644 --- a/tests/UserTest.php +++ b/tests/UserTest.php @@ -25,10 +25,10 @@ class UserTest extends TestCase { # Add subfleets and aircraft, but also add another # set of subfleets - $subfleetA = TestData::createSubfleetWithAircraft(); - TestData::createSubfleetWithAircraft(); + $subfleetA = $this->createSubfleetWithAircraft(); + $this->createSubfleetWithAircraft(); - $rank = TestData::createRank(10, [$subfleetA['subfleet']->id]); + $rank = $this->createRank(10, [$subfleetA['subfleet']->id]); $user = factory(App\Models\User::class)->create([ 'rank_id' => $rank->id, @@ -81,15 +81,15 @@ class UserTest extends TestCase { # Add subfleets and aircraft, but also add another # set of subfleets - $subfleetA = TestData::createSubfleetWithAircraft(); - $subfleetB = TestData::createSubfleetWithAircraft(); + $subfleetA = $this->createSubfleetWithAircraft(); + $subfleetB = $this->createSubfleetWithAircraft(); $added_aircraft = array_merge( $subfleetA['aircraft']->pluck('id')->toArray(), $subfleetB['aircraft']->pluck('id')->toArray() ); - $rank = TestData::createRank(10, [$subfleetA['subfleet']->id]); + $rank = $this->createRank(10, [$subfleetA['subfleet']->id]); $user = factory(App\Models\User::class)->create([ 'rank_id' => $rank->id, @@ -134,10 +134,10 @@ class UserTest extends TestCase # Add subfleets and aircraft, but also add another # set of subfleets $airport = factory(App\Models\Airport::class)->create(); - $subfleetA = TestData::createSubfleetWithAircraft(2, $airport->id); - $subfleetB = TestData::createSubfleetWithAircraft(2); + $subfleetA = $this->createSubfleetWithAircraft(2, $airport->id); + $subfleetB = $this->createSubfleetWithAircraft(2); - $rank = TestData::createRank(10, [$subfleetA['subfleet']->id]); + $rank = $this->createRank(10, [$subfleetA['subfleet']->id]); $user = factory(App\Models\User::class)->create([ 'curr_airport_id' => $airport->id, 'rank_id' => $rank->id,