From 3e1d9080df2faa87819cb5bd1d042cb7b996272d Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Tue, 16 Jul 2019 13:54:14 -0400 Subject: [PATCH 01/11] Backend changes separating id from pilot_id --- app/Database/factories/UserFactory.php | 1 + .../2019_07_16_141152_users_add_pilot_id.php | 67 +++++ app/Exceptions/UserPilotIdExists.php | 9 + app/Http/Controllers/Admin/UserController.php | 2 +- app/Http/Controllers/Api/AcarsController.php | 2 +- app/Http/Controllers/Auth/LoginController.php | 2 +- .../Frontend/ProfileController.php | 6 +- app/Http/Resources/PirepComment.php | 1 + app/Http/Resources/User.php | 1 + app/Listeners/NotificationEvents.php | 2 +- app/Models/Observers/UserObserver.php | 26 ++ app/Models/User.php | 23 +- app/Providers/AppServiceProvider.php | 3 + app/Services/PirepService.php | 2 +- app/Services/UserService.php | 55 ++++- composer.json | 1 + composer.lock | 233 +++++++++++++++++- resources/views/admin/pireps/edit.blade.php | 2 +- .../layouts/default/profile/index.blade.php | 2 +- .../default/widgets/latest_pilots.blade.php | 2 +- tests/UserTest.php | 46 +++- 21 files changed, 454 insertions(+), 34 deletions(-) create mode 100644 app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php create mode 100644 app/Exceptions/UserPilotIdExists.php create mode 100644 app/Models/Observers/UserObserver.php diff --git a/app/Database/factories/UserFactory.php b/app/Database/factories/UserFactory.php index a6ae14f06..8d18fc151 100644 --- a/app/Database/factories/UserFactory.php +++ b/app/Database/factories/UserFactory.php @@ -8,6 +8,7 @@ return [ 'id' => null, + 'pilot_id' => 0, 'name' => $faker->name, 'email' => $faker->safeEmail, 'password' => $password ?: $password = Hash::make('secret'), diff --git a/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php b/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php new file mode 100644 index 000000000..45500ef60 --- /dev/null +++ b/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php @@ -0,0 +1,67 @@ +unsignedBigInteger('pilot_id') + ->after('id') + ->unique() + ->nullable() + ->index('users_pilot_id'); + }); + + // Migrate the current pilot IDs + DB::update('UPDATE `users` SET `pilot_id`=`id`'); + + // Drop the old ID column and add a new one + /*Schema::table('users', function (Blueprint $table) { + $table->dropPrimary('users_id_primary'); + $table->dropColumn('id'); + $table->string('id', Model::ID_MAX_LENGTH)->primary(); + }); + + // Update the users to use the `pilot_id` (so we don't need to migrate data from other tables) + $users = DB::table('users')->get(['id']); + foreach ($users as $user) { + $user->id = $user->pilot_id; + $user->save(); + }*/ + + // role_user + // permission_user + // sessions + // pireps + // bids + // news + // user_awards + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('pilot_id'); + }); + } +} diff --git a/app/Exceptions/UserPilotIdExists.php b/app/Exceptions/UserPilotIdExists.php new file mode 100644 index 000000000..3fd620829 --- /dev/null +++ b/app/Exceptions/UserPilotIdExists.php @@ -0,0 +1,9 @@ +pilot_id.'"'); + Log::info('Regenerating API key "'.$user->ident.'"'); $user->api_key = Utils::generateApiKey(); $user->save(); diff --git a/app/Http/Controllers/Api/AcarsController.php b/app/Http/Controllers/Api/AcarsController.php index 88d3676f7..71303e908 100644 --- a/app/Http/Controllers/Api/AcarsController.php +++ b/app/Http/Controllers/Api/AcarsController.php @@ -131,7 +131,7 @@ public function acars_store($id, PositionRequest $request) $this->checkCancelled($pirep); Log::debug( - 'Posting ACARS update (user: '.Auth::user()->pilot_id.', pirep id :'.$id.'): ', + 'Posting ACARS update (user: '.Auth::user()->ident.', pirep id :'.$id.'): ', $request->post() ); diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index dd6851231..40c4550a1 100755 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -49,7 +49,7 @@ protected function sendLoginResponse(Request $request) // TODO: How to handle ON_LEAVE? if ($user->state !== UserState::ACTIVE) { - Log::info('Trying to login '.$user->pilot_id.', state ' + Log::info('Trying to login '.$user->ident.', state ' .UserState::label($user->state)); // Log them out diff --git a/app/Http/Controllers/Frontend/ProfileController.php b/app/Http/Controllers/Frontend/ProfileController.php index 3fdc1290b..59e67a048 100644 --- a/app/Http/Controllers/Frontend/ProfileController.php +++ b/app/Http/Controllers/Frontend/ProfileController.php @@ -133,7 +133,7 @@ public function update(Request $request) ]); if ($validator->fails()) { - Log::info('validator failed for user '.$user->pilot_id); + Log::info('validator failed for user '.$user->ident); Log::info($validator->errors()->toArray()); return redirect(route('frontend.profile.edit', $id)) @@ -153,7 +153,7 @@ public function update(Request $request) } if ($request->hasFile('avatar')) { $avatar = $request->file('avatar'); - $file_name = $user->pilot_id.'.'.$avatar->getClientOriginalExtension(); + $file_name = $user->ident.'.'.$avatar->getClientOriginalExtension(); $path = "avatars/{$file_name}"; // Create the avatar, resizing it and keeping the aspect ratio. @@ -189,7 +189,7 @@ public function update(Request $request) public function regen_apikey(Request $request) { $user = User::find(Auth::user()->id); - Log::info('Regenerating API key "'.$user->pilot_id.'"'); + Log::info('Regenerating API key "'.$user->ident.'"'); $user->api_key = Utils::generateApiKey(); $user->save(); diff --git a/app/Http/Resources/PirepComment.php b/app/Http/Resources/PirepComment.php index 58336a5bd..ff0eabaae 100644 --- a/app/Http/Resources/PirepComment.php +++ b/app/Http/Resources/PirepComment.php @@ -27,6 +27,7 @@ public function toArray($request) 'user' => [ 'id' => $user->id, 'pilot_id' => $user->pilot_id, + 'ident' => $user->ident, 'name' => $user->name, ], ]; diff --git a/app/Http/Resources/User.php b/app/Http/Resources/User.php index 295d13437..5e0e1dd8e 100644 --- a/app/Http/Resources/User.php +++ b/app/Http/Resources/User.php @@ -11,6 +11,7 @@ public function toArray($request) return [ 'id' => $this->id, 'pilot_id' => $this->pilot_id, + 'ident' => $this->ident, 'name' => $this->name, 'email' => $this->email, 'apikey' => $this->apikey, diff --git a/app/Listeners/NotificationEvents.php b/app/Listeners/NotificationEvents.php index 52affeafa..86c923d22 100644 --- a/app/Listeners/NotificationEvents.php +++ b/app/Listeners/NotificationEvents.php @@ -68,7 +68,7 @@ protected function sendEmail($to, $email) public function onUserRegister(UserRegistered $event): void { Log::info('onUserRegister: ' - .$event->user->pilot_id.' is ' + .$event->user->ident.' is ' .UserState::label($event->user->state) .', sending active email'); diff --git a/app/Models/Observers/UserObserver.php b/app/Models/Observers/UserObserver.php new file mode 100644 index 000000000..7b648ebe1 --- /dev/null +++ b/app/Models/Observers/UserObserver.php @@ -0,0 +1,26 @@ +userSvc = $userSvc; + } + + /** + * After a user has been created, do some stuff + * + * @param User $user + */ + public function created(User $user): void + { + $this->userSvc->findAndSetPilotId($user); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index bd95c8701..1a63e2f1e 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -10,14 +10,17 @@ use Laratrust\Traits\LaratrustUserTrait; /** - * @property int id + * @property int id + * @property int pilot_id * @property string name * @property string email * @property string password * @property string api_key - * @property mixed ident + * @property mixed timezone + * @property string ident * @property string curr_airport_id * @property string home_airport_id + * @property Airline airline * @property Flight[] flights * @property string flight_time * @property string remember_token @@ -45,9 +48,11 @@ class User extends Authenticatable public $journal_type = JournalType::USER; protected $fillable = [ + 'id', 'name', 'email', 'password', + 'pilot_id', 'airline_id', 'rank_id', 'api_key', @@ -78,6 +83,8 @@ class User extends Authenticatable ]; protected $casts = [ + 'id' => 'integer', + 'pilot_id' => 'integer', 'flights' => 'integer', 'flight_time' => 'integer', 'transfer_time' => 'integer', @@ -96,19 +103,11 @@ class User extends Authenticatable /** * @return string */ - public function getPilotIdAttribute() + public function getIdentAttribute() { $length = setting('pilots.id_length'); - return $this->airline->icao.str_pad($this->id, $length, '0', STR_PAD_LEFT); - } - - /** - * @return string - */ - public function getIdentAttribute() - { - return $this->getPilotIdAttribute(); + return $this->airline->icao . str_pad($this->pilot_id, $length, '0', STR_PAD_LEFT); } /** diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 8979978af..7d718b8fb 100755 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -15,10 +15,12 @@ use App\Models\Observers\SettingObserver; use App\Models\Observers\Sluggable; use App\Models\Observers\SubfleetObserver; +use App\Models\Observers\UserObserver; use App\Models\PirepField; use App\Models\PirepFieldValue; use App\Models\Setting; use App\Models\Subfleet; +use App\Models\User; use App\Repositories\SettingRepository; use App\Services\ModuleService; use Illuminate\Support\Facades\Schema; @@ -53,6 +55,7 @@ public function boot(): void Setting::observe(SettingObserver::class); Subfleet::observe(SubfleetObserver::class); + User::observe(UserObserver::class); } /** diff --git a/app/Services/PirepService.php b/app/Services/PirepService.php index 739e8c7e6..24f9cc870 100644 --- a/app/Services/PirepService.php +++ b/app/Services/PirepService.php @@ -425,7 +425,7 @@ public function removeBid(Pirep $pirep) ]); if ($bid) { - Log::info('Bid for user: '.$pirep->user->pilot_id.' on flight '.$flight->ident); + Log::info('Bid for user: '.$pirep->user->ident.' on flight '.$flight->ident); $bid->delete(); } } diff --git a/app/Services/UserService.php b/app/Services/UserService.php index 74a24fe76..145fb384d 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -6,6 +6,7 @@ use App\Events\UserRegistered; use App\Events\UserStateChanged; use App\Events\UserStatsChanged; +use App\Exceptions\UserPilotIdExists; use App\Models\Enums\PirepState; use App\Models\Enums\UserState; use App\Models\Pirep; @@ -16,6 +17,7 @@ use App\Repositories\SubfleetRepository; use App\Support\Units\Time; use Illuminate\Support\Collection; +use function is_array; use Log; /** @@ -67,7 +69,7 @@ public function createUser(User $user, array $groups = null) // $user->attachRole($role); // Attach any additional roles - if (!empty($groups) && \is_array($groups)) { + if (!empty($groups) && is_array($groups)) { foreach ($groups as $group) { $role = Role::where('name', $group)->first(); $user->attachRole($role); @@ -83,6 +85,55 @@ public function createUser(User $user, array $groups = null) return $user; } + /** + * Find the next available pilot ID and set the current user's pilot_id to that +1 + * Called from UserObserver right now after a record is created + * + * @param User $user + * + * @return User + */ + public function findAndSetPilotId(User $user): User + { + if ($user->pilot_id !== null && $user->pilot_id > 0) { + return $user; + } + + $max = (int) User::max('pilot_id'); + $user->pilot_id = $max + 1; + $user->save(); + + Log::info('Set pilot ID for user ' . $user->id . ' to ' . $user->pilot_id); + + return $user; + } + + /** + * Change a user's pilot ID + * + * @param User $user + * @param int $pilot_id + * + * @throws UserPilotIdExists + * + * @return User + */ + public function changePilotId(User $user, int $pilot_id): User + { + if (User::where('pilot_id', '=', $pilot_id)->exists()) { + Log::error('User with id '.$pilot_id.' already exists'); + throw new UserPilotIdExists(); + } + + $old_id = $user->pilot_id; + $user->pilot_id = $pilot_id; + $user->save(); + + Log::info('Changed pilot ID for user '.$user->id.' from '.$old_id.' to '.$user->pilot_id); + + return $user; + } + /** * Return the subfleets this user is allowed access to, * based on their current rank @@ -133,7 +184,7 @@ public function changeUserState(User $user, $old_state): User return $user; } - Log::info('User '.$user->pilot_id.' state changing from ' + Log::info('User '.$user->ident.' state changing from ' .UserState::label($old_state).' to ' .UserState::label($user->state)); diff --git a/composer.json b/composer.json index 658d65b79..cff6ef6ba 100755 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ "anhskohbo/no-captcha": "3.0.*", "appstract/laravel-opcache": "^2.0", "arrilot/laravel-widgets": "3.13.*", + "doctrine/dbal": "2.9.*", "fzaninotto/faker": "^1.8", "guzzlehttp/guzzle": "6.3.*", "hashids/hashids": "2.0.*", diff --git a/composer.lock b/composer.lock index 443f8b438..118c2e99e 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "b4e5994cf5891923a2ed410bacad5fc4", + "content-hash": "99c96d01e78e1d4400295a887ac36667", "packages": [ { "name": "akaunting/money", @@ -857,6 +857,237 @@ ], "time": "2019-05-27T17:52:04+00:00" }, + { + "name": "doctrine/cache", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/d768d58baee9a4862ca783840eca1b9add7a7f57", + "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^4.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Caching library offering an object-oriented API for many cache backends", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "cache", + "caching" + ], + "time": "2018-08-21T18:01:43+00:00" + }, + { + "name": "doctrine/dbal", + "version": "v2.9.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "22800bd651c1d8d2a9719e2a3dc46d5108ebfcc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/22800bd651c1d8d2a9719e2a3dc46d5108ebfcc9", + "reference": "22800bd651c1d8d2a9719e2a3dc46d5108ebfcc9", + "shasum": "" + }, + "require": { + "doctrine/cache": "^1.0", + "doctrine/event-manager": "^1.0", + "ext-pdo": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^5.0", + "jetbrains/phpstorm-stubs": "^2018.1.2", + "phpstan/phpstan": "^0.10.1", + "phpunit/phpunit": "^7.4", + "symfony/console": "^2.0.5|^3.0|^4.0", + "symfony/phpunit-bridge": "^3.4.5|^4.0.5" + }, + "suggest": { + "symfony/console": "For helpful console commands such as SQL execution and import of files." + }, + "bin": [ + "bin/doctrine-dbal" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.9.x-dev", + "dev-develop": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\DBAL\\": "lib/Doctrine/DBAL" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.", + "homepage": "https://www.doctrine-project.org/projects/dbal.html", + "keywords": [ + "abstraction", + "database", + "dbal", + "mysql", + "persistence", + "pgsql", + "php", + "queryobject" + ], + "time": "2018-12-31T03:27:51+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Event Manager component", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "eventdispatcher", + "eventmanager" + ], + "time": "2018-06-11T11:59:03+00:00" + }, { "name": "doctrine/inflector", "version": "v1.3.0", diff --git a/resources/views/admin/pireps/edit.blade.php b/resources/views/admin/pireps/edit.blade.php index d10a3557b..3567a128b 100644 --- a/resources/views/admin/pireps/edit.blade.php +++ b/resources/views/admin/pireps/edit.blade.php @@ -11,7 +11,7 @@
Filed By: - {{ $pirep->user->pilot_id }} {{ $pirep->user->name }} + {{ $pirep->user->ident }} {{ $pirep->user->name }}
diff --git a/resources/views/layouts/default/profile/index.blade.php b/resources/views/layouts/default/profile/index.blade.php index 8a90fb8dd..73ef26ddc 100644 --- a/resources/views/layouts/default/profile/index.blade.php +++ b/resources/views/layouts/default/profile/index.blade.php @@ -13,7 +13,7 @@

{{ $user->name }}

-
{{ $user->pilot_id }}
+
{{ $user->ident }}
{{ $user->rank->name }}

{{ $user->airline->name }} diff --git a/resources/views/layouts/default/widgets/latest_pilots.blade.php b/resources/views/layouts/default/widgets/latest_pilots.blade.php index 7e25ea9e0..4ea5bdd4e 100644 --- a/resources/views/layouts/default/widgets/latest_pilots.blade.php +++ b/resources/views/layouts/default/widgets/latest_pilots.blade.php @@ -2,7 +2,7 @@ @foreach($users as $u) - {{ $u->pilot_id }} + {{ $u->ident }} {{ $u->name }} diff --git a/tests/UserTest.php b/tests/UserTest.php index 905d8d466..9e47cec1c 100644 --- a/tests/UserTest.php +++ b/tests/UserTest.php @@ -1,5 +1,7 @@ id, ]); - /* - * Now we can do some actual tests - */ - - /* - * Do some sanity checks first - */ - // Make sure no flights are filtered out $this->settingsRepo->store('pilots.only_flights_from_current', false); @@ -195,4 +189,40 @@ public function testGetAircraftAllowedFromFlight() $body = $response->json()['data']; $this->assertCount(1, $body[0]['subfleets']); } + + /** + * Test the pilot ID being added when a new user is created + * @expectedException \App\Exceptions\UserPilotIdExists + */ + public function testUserPilotIdChangeAlreadyExists() + { + $user1 = factory(App\Models\User::class)->create(['id' => 1]); + $user2 = factory(App\Models\User::class)->create(['id' => 2]); + + // Now try to change the original user's pilot_id to 2 (should conflict) + $this->userSvc->changePilotId($user1, 2); + } + + /** + * Test the pilot ID being added when a new user is created + */ + public function testUserPilotIdAdded() + { + $new_user = factory(App\Models\User::class)->create(['id' => 1]); + $user = $this->userSvc->createUser($new_user); + $this->assertEquals($user->id, $user->pilot_id); + + // Add a second user + $new_user = factory(App\Models\User::class)->create(['id' => 2]); + $user2 = $this->userSvc->createUser($new_user); + $this->assertEquals($user2->id, $user2->pilot_id); + + // Now try to change the original user's pilot_id to 3 + $user = $this->userSvc->changePilotId($user, 3); + $this->assertEquals(3, $user->pilot_id); + + // Create a new user and the pilot_id should be 4 + $user3 = factory(App\Models\User::class)->create(['id' => 3]); + $this->assertEquals(4, $user3->pilot_id); + } } From 80560ec20c93693d7890f749474cbf078c82b60b Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Tue, 16 Jul 2019 14:06:13 -0400 Subject: [PATCH 02/11] Formatting --- .../migrations/2019_07_16_141152_users_add_pilot_id.php | 5 ++--- app/Models/User.php | 2 +- app/Services/UserService.php | 5 +++-- tests/UserTest.php | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php b/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php index 45500ef60..29ad73a47 100644 --- a/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php +++ b/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php @@ -1,10 +1,9 @@ airline->icao . str_pad($this->pilot_id, $length, '0', STR_PAD_LEFT); + return $this->airline->icao.str_pad($this->pilot_id, $length, '0', STR_PAD_LEFT); } /** diff --git a/app/Services/UserService.php b/app/Services/UserService.php index 145fb384d..7c91ca0f7 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -103,7 +103,7 @@ public function findAndSetPilotId(User $user): User $user->pilot_id = $max + 1; $user->save(); - Log::info('Set pilot ID for user ' . $user->id . ' to ' . $user->pilot_id); + Log::info('Set pilot ID for user '.$user->id.' to '.$user->pilot_id); return $user; } @@ -112,7 +112,7 @@ public function findAndSetPilotId(User $user): User * Change a user's pilot ID * * @param User $user - * @param int $pilot_id + * @param int $pilot_id * * @throws UserPilotIdExists * @@ -122,6 +122,7 @@ public function changePilotId(User $user, int $pilot_id): User { if (User::where('pilot_id', '=', $pilot_id)->exists()) { Log::error('User with id '.$pilot_id.' already exists'); + throw new UserPilotIdExists(); } diff --git a/tests/UserTest.php b/tests/UserTest.php index 9e47cec1c..374f49f6c 100644 --- a/tests/UserTest.php +++ b/tests/UserTest.php @@ -1,6 +1,5 @@ Date: Wed, 17 Jul 2019 08:56:38 -0400 Subject: [PATCH 03/11] Fix the avatars directory #316 --- .travis/deploy_script.sh | 2 +- storage/app/public/.gitignore | 2 +- storage/app/public/{avatar => avatars}/.gitignore | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename storage/app/public/{avatar => avatars}/.gitignore (100%) diff --git a/.travis/deploy_script.sh b/.travis/deploy_script.sh index b9cbfe134..40b41b132 100755 --- a/.travis/deploy_script.sh +++ b/.travis/deploy_script.sh @@ -90,7 +90,7 @@ if [ "$TRAVIS" = "true" ]; then # clear any app specific stuff that might have been loaded in find storage/app -mindepth 1 -not -name '.gitignore' -not -name public -not -name import -print0 -exec rm -rf {} + find storage/app/public -mindepth 1 -not -name '.gitignore' -not -name avatar -not -name uploads -print0 -exec rm -rf {} + - find storage/app/public/avatar -mindepth 1 -not -name '.gitignore' -print0 -exec rm -rf {} + + find storage/app/public/avatars -mindepth 1 -not -name '.gitignore' -print0 -exec rm -rf {} + find storage/app/public/uploads -mindepth 1 -not -name '.gitignore' -print0 -exec rm -rf {} + find storage/debugbar -mindepth 1 -not -name '.gitignore' -print0 -exec rm -rf {} + find storage/docker -mindepth 1 -not -name '.gitignore' -print0 -exec rm -rf {} + diff --git a/storage/app/public/.gitignore b/storage/app/public/.gitignore index f2e1cac8c..a7c5d2a95 100755 --- a/storage/app/public/.gitignore +++ b/storage/app/public/.gitignore @@ -1,4 +1,4 @@ * -!avatar +!avatars !uploads !.gitignore diff --git a/storage/app/public/avatar/.gitignore b/storage/app/public/avatars/.gitignore similarity index 100% rename from storage/app/public/avatar/.gitignore rename to storage/app/public/avatars/.gitignore From ec81a6d157540817621cea20651f8be541a14743 Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Wed, 17 Jul 2019 08:57:45 -0400 Subject: [PATCH 04/11] Fix errors in the METAR parsing for clouds; display error for pressure units --- app/Support/Metar.php | 13 ++++++++----- .../views/layouts/default/widgets/weather.blade.php | 4 ++-- tests/MetarTest.php | 9 +++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/app/Support/Metar.php b/app/Support/Metar.php index 1e9ffaac0..6fdb90874 100644 --- a/app/Support/Metar.php +++ b/app/Support/Metar.php @@ -8,6 +8,7 @@ use App\Support\Units\Temperature; use App\Support\Units\Velocity; use function count; +use Illuminate\Support\Facades\Log; use PhpUnitsOfMeasure\Exception\NonNumericValue; use PhpUnitsOfMeasure\Exception\NonStringUnitName; @@ -341,6 +342,7 @@ class Metar implements \ArrayAccess public function __construct($raw, $taf = false, $debug = false, $icao = true) { $this->debug_enabled = $debug; + // Log::info('Parsing metar="'.$raw.'"'); $raw_lines = explode("\n", $raw, 2); if (isset($raw_lines[1])) { @@ -408,7 +410,7 @@ public function __get($parameter) */ protected function createAltitude($value, $unit) { - return new Altitude($value, $unit); + return new Altitude((float) $value, $unit); } /** @@ -424,7 +426,7 @@ protected function createAltitude($value, $unit) */ protected function createDistance($value, $unit) { - return new Distance($value, $unit); + return new Distance((float) $value, $unit); } /** @@ -440,7 +442,7 @@ protected function createDistance($value, $unit) */ protected function createPressure($value, $unit) { - return new Pressure($value, $unit); + return new Pressure((float) $value, $unit); } /** @@ -456,7 +458,7 @@ protected function createPressure($value, $unit) */ protected function createTemperature($value, $unit) { - return new Temperature($value, $unit); + return new Temperature((float) $value, $unit); } /** @@ -472,7 +474,7 @@ protected function createTemperature($value, $unit) */ protected function createVelocity($value, $unit) { - return new Velocity($value, $unit); + return new Velocity((float) $value, $unit); } /** @@ -1118,6 +1120,7 @@ private function get_clouds($part) $report = implode(' ', $report); $report_ft = implode(' ', $report_ft); + $observed['report'] = $this->createAltitude($report_ft, 'ft'); $observed['report'] = ucfirst($report); $observed['report_ft'] = ucfirst($report_ft); diff --git a/resources/views/layouts/default/widgets/weather.blade.php b/resources/views/layouts/default/widgets/weather.blade.php index 3da30262e..5ef12fa97 100644 --- a/resources/views/layouts/default/widgets/weather.blade.php +++ b/resources/views/layouts/default/widgets/weather.blade.php @@ -30,8 +30,8 @@ @lang('widgets.weather.barometer') - {{ number_format($metar['barometer'], 2) }} hPa - / {{ number_format($metar['barometer_in'], 2) }} inHg + {{ number_format($metar['barometer']['hPa'], 2) }} hPa + / {{ number_format($metar['barometer']['inHg'], 2) }} inHg @if($metar['clouds']) diff --git a/tests/MetarTest.php b/tests/MetarTest.php index ec2cf0753..cee14eca6 100644 --- a/tests/MetarTest.php +++ b/tests/MetarTest.php @@ -138,4 +138,13 @@ public function testMetarTrends3() $this->assertEquals('VFR', $metar['category']); $this->assertNotNull($metar); } + + public function testMetar4Clouds() + { + $metar = 'KAUS 171153Z 18006KT 9SM FEW015 FEW250 26/24 A3003 RMK AO2 SLP156 T02560244 10267 20239 $'; + $metar = Metar::parse($metar); + + $this->assertNotNull($metar); + $this->assertEquals(2, count($metar->clouds)); + } } From 337fe5cfaad2f36f8bdb3f7780923bb472d00306 Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Wed, 17 Jul 2019 08:58:10 -0400 Subject: [PATCH 05/11] Rename "Administration" to "Admin" --- resources/lang/en/common.php | 2 +- resources/lang/es/common.php | 2 +- resources/views/admin/menu.blade.php | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php index 1010bf89e..12f128b15 100644 --- a/resources/lang/en/common.php +++ b/resources/lang/en/common.php @@ -2,7 +2,7 @@ return [ 'dashboard' => 'Dashboard', - 'administration' => 'Administration', + 'administration' => 'Admin', 'flight' => 'Flight|Flights', 'livemap' => 'Live Map', 'pilot' => 'Pilot|Pilots', diff --git a/resources/lang/es/common.php b/resources/lang/es/common.php index 7bf2f9447..787edca9f 100644 --- a/resources/lang/es/common.php +++ b/resources/lang/es/common.php @@ -2,7 +2,7 @@ return [ 'dashboard' => 'Tablero', - 'administration' => 'Administración', + 'administration' => 'Admin', 'flight' => 'Vuelo|Vuelos', 'livemap' => 'Mapa en vivo', 'pilot' => 'Piloto|Pilotos', diff --git a/resources/views/admin/menu.blade.php b/resources/views/admin/menu.blade.php index 25833a335..0d265f67d 100644 --- a/resources/views/admin/menu.blade.php +++ b/resources/views/admin/menu.blade.php @@ -32,6 +32,10 @@ @ability('admin', 'finances')

  • finances
  • @endability + + @ability('admin', 'users') +
  • users
  • + @endability @@ -55,10 +59,6 @@
  • expenses
  • @endability - @ability('admin', 'users') -
  • users
  • - @endability - @ability('admin', 'ranks')
  • ranks
  • @endability From 567ff91de0a69f4824254953751bf0b73d21ca33 Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Wed, 17 Jul 2019 09:48:20 -0400 Subject: [PATCH 06/11] Add pilot ID change fields to the admin screen --- app/Database/seeds/sample.yml | 3 +++ app/Http/Requests/CreatePirepRequest.php | 2 +- app/Http/Requests/UpdateUserRequest.php | 10 +++++++++- app/Models/User.php | 5 +++-- app/Services/UserService.php | 11 ++++++++++- resources/views/admin/users/fields.blade.php | 13 ++++++++++--- resources/views/admin/users/table.blade.php | 2 ++ 7 files changed, 38 insertions(+), 8 deletions(-) diff --git a/app/Database/seeds/sample.yml b/app/Database/seeds/sample.yml index b2a66172f..cf67a87a3 100644 --- a/app/Database/seeds/sample.yml +++ b/app/Database/seeds/sample.yml @@ -15,6 +15,7 @@ roles: users: - id: 1 + pilot_id: 1 name: Admin User email: admin@phpvms.net password: admin @@ -34,6 +35,7 @@ users: created_at: now updated_at: now - id: 2 + pilot_id: 2 name: Carla Walters email: carla.walters68@example.com password: admin @@ -50,6 +52,7 @@ users: opt_in: 1 toc_accepted: 1 - id: 3 + pilot_id: 3 name: Raymond Pearson email: raymond.pearson56@example.com password: admin diff --git a/app/Http/Requests/CreatePirepRequest.php b/app/Http/Requests/CreatePirepRequest.php index 5a2b39b2b..ff87570d8 100644 --- a/app/Http/Requests/CreatePirepRequest.php +++ b/app/Http/Requests/CreatePirepRequest.php @@ -5,7 +5,7 @@ use App\Models\Pirep; use App\Repositories\PirepFieldRepository; use Illuminate\Foundation\Http\FormRequest; -use Log; +use Illuminate\Support\Facades\Log; class CreatePirepRequest extends FormRequest { diff --git a/app/Http/Requests/UpdateUserRequest.php b/app/Http/Requests/UpdateUserRequest.php index 06eba56b5..ef8eb5585 100644 --- a/app/Http/Requests/UpdateUserRequest.php +++ b/app/Http/Requests/UpdateUserRequest.php @@ -4,6 +4,7 @@ use App\Models\User; use Illuminate\Foundation\Http\FormRequest; +use function request; class UpdateUserRequest extends FormRequest { @@ -24,6 +25,13 @@ public function authorize() */ public function rules() { - return User::$rules; + $rules = User::$rules; + + $user_id = request('id', null); + + // Validate if the pilot ID is already being used or not + $rules['pilot_id'] = 'required|integer|unique:users,pilot_id,'.$user_id.',id'; + + return $rules; } } diff --git a/app/Models/User.php b/app/Models/User.php index fd1fecfc9..eddb38395 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -96,8 +96,9 @@ class User extends Authenticatable ]; public static $rules = [ - 'name' => 'required', - 'email' => 'required|email', + 'pilot_id' => 'required|integer|unique:users,pilot_id', + 'name' => 'required', + 'email' => 'required|email', ]; /** diff --git a/app/Services/UserService.php b/app/Services/UserService.php index 7c91ca0f7..96bd20b1b 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -108,6 +108,11 @@ public function findAndSetPilotId(User $user): User return $user; } + public function isPilotIdAlreadyUsed(int $pilot_id): bool + { + return User::where('pilot_id', '=', $pilot_id)->exists(); + } + /** * Change a user's pilot ID * @@ -120,7 +125,11 @@ public function findAndSetPilotId(User $user): User */ public function changePilotId(User $user, int $pilot_id): User { - if (User::where('pilot_id', '=', $pilot_id)->exists()) { + if ($user->pilot_id === $pilot_id) { + return $user; + } + + if ($this->isPilotIdAlreadyUsed($pilot_id)) { Log::error('User with id '.$pilot_id.' already exists'); throw new UserPilotIdExists(); diff --git a/resources/views/admin/users/fields.blade.php b/resources/views/admin/users/fields.blade.php index 997259d82..3d2ddd4f7 100644 --- a/resources/views/admin/users/fields.blade.php +++ b/resources/views/admin/users/fields.blade.php @@ -1,17 +1,24 @@
    -
    + {{ Form::hidden('id') }} +
    + {{ Form::label('pilot_id', 'Pilot ID:') }} + {{ Form::number('pilot_id', null, ['class' => 'form-control']) }} +

    {{ $errors->first('pilot_id') }}

    +
    + +
    {{ Form::label('name', 'Name:') }} {{ Form::text('name', null, ['class' => 'form-control']) }}

    {{ $errors->first('name') }}

    -
    +
    {{ Form::label('email', 'Email:') }} {{ Form::text('email', null, ['class' => 'form-control']) }}

    {{ $errors->first('email') }}

    -
    +
    {{ Form::label('password', 'Password:') }} {{ Form::password('password', ['class' => 'form-control']) }}

    {{ $errors->first('password') }}

    diff --git a/resources/views/admin/users/table.blade.php b/resources/views/admin/users/table.blade.php index 381e03760..ecac353f2 100644 --- a/resources/views/admin/users/table.blade.php +++ b/resources/views/admin/users/table.blade.php @@ -1,5 +1,6 @@ + @@ -9,6 +10,7 @@ @foreach($users as $user) +
    ID Name Email Registered
    {{ $user->ident }} @if(filled($user->country)) Date: Wed, 17 Jul 2019 09:56:16 -0400 Subject: [PATCH 07/11] Fix metar clouds test --- tests/MetarTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/MetarTest.php b/tests/MetarTest.php index cee14eca6..c2b0297ab 100644 --- a/tests/MetarTest.php +++ b/tests/MetarTest.php @@ -145,6 +145,8 @@ public function testMetar4Clouds() $metar = Metar::parse($metar); $this->assertNotNull($metar); - $this->assertEquals(2, count($metar->clouds)); + $this->assertEquals(2, count($metar['clouds'])); + $this->assertEquals('A few at 457 meters; a few at 7620 meters', $metar['clouds_report']); + $this->assertEquals('A few at 1500 feet; a few at 25000 feet', $metar['clouds_report_ft']); } } From f5dcd068383cc55d22b2a6ba553cef4e2a02311f Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Wed, 17 Jul 2019 09:57:05 -0400 Subject: [PATCH 08/11] Remove the NotNull checks --- tests/MetarTest.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/MetarTest.php b/tests/MetarTest.php index c2b0297ab..d1f3834c5 100644 --- a/tests/MetarTest.php +++ b/tests/MetarTest.php @@ -127,7 +127,6 @@ public function testMetarTrends2() $parsed['clouds_report_ft'] ); - $this->assertNotNull($parsed); } public function testMetarTrends3() @@ -136,7 +135,6 @@ public function testMetarTrends3() $metar = Metar::parse($metar); $this->assertEquals('VFR', $metar['category']); - $this->assertNotNull($metar); } public function testMetar4Clouds() @@ -144,7 +142,6 @@ public function testMetar4Clouds() $metar = 'KAUS 171153Z 18006KT 9SM FEW015 FEW250 26/24 A3003 RMK AO2 SLP156 T02560244 10267 20239 $'; $metar = Metar::parse($metar); - $this->assertNotNull($metar); $this->assertEquals(2, count($metar['clouds'])); $this->assertEquals('A few at 457 meters; a few at 7620 meters', $metar['clouds_report']); $this->assertEquals('A few at 1500 feet; a few at 25000 feet', $metar['clouds_report_ft']); From 482a9cb04f98128cbfe62b37026a687d839e403d Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Wed, 17 Jul 2019 10:04:22 -0400 Subject: [PATCH 09/11] formatting --- tests/MetarTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/MetarTest.php b/tests/MetarTest.php index d1f3834c5..03ddf0092 100644 --- a/tests/MetarTest.php +++ b/tests/MetarTest.php @@ -126,7 +126,6 @@ public function testMetarTrends2() 'Scattered at 4500 feet, cumulonimbus; broken sky at 6000 feet; overcast sky at 8000 feet', $parsed['clouds_report_ft'] ); - } public function testMetarTrends3() From 95ae3aacb3b74771915108c1088b3635d430bfc3 Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Wed, 17 Jul 2019 10:59:11 -0400 Subject: [PATCH 10/11] Unique email check --- app/Http/Requests/UpdateUserRequest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/Http/Requests/UpdateUserRequest.php b/app/Http/Requests/UpdateUserRequest.php index ef8eb5585..2285657e5 100644 --- a/app/Http/Requests/UpdateUserRequest.php +++ b/app/Http/Requests/UpdateUserRequest.php @@ -32,6 +32,9 @@ public function rules() // Validate if the pilot ID is already being used or not $rules['pilot_id'] = 'required|integer|unique:users,pilot_id,'.$user_id.',id'; + // Add additional rules for when we're modifying + $rules['email'] .= '|unique:users,email,'.$user_id.',id'; + return $rules; } } From bb15119bf0d69571df354a29fa0b5768846350cd Mon Sep 17 00:00:00 2001 From: Nabeel Shahzad Date: Wed, 17 Jul 2019 11:00:30 -0400 Subject: [PATCH 11/11] Append rules for Create/Update --- app/Http/Requests/CreateUserRequest.php | 3 +++ app/Http/Requests/UpdateUserRequest.php | 5 +---- app/Models/User.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/Http/Requests/CreateUserRequest.php b/app/Http/Requests/CreateUserRequest.php index a1ad752c6..65d01813b 100644 --- a/app/Http/Requests/CreateUserRequest.php +++ b/app/Http/Requests/CreateUserRequest.php @@ -25,7 +25,10 @@ public function authorize(): bool public function rules(): array { $rules = User::$rules; + $rules['email'] .= '|unique:users,email'; + $rules['pilot_id'] .= '|unique:users,pilot_id'; + return $rules; } } diff --git a/app/Http/Requests/UpdateUserRequest.php b/app/Http/Requests/UpdateUserRequest.php index 2285657e5..8be4df022 100644 --- a/app/Http/Requests/UpdateUserRequest.php +++ b/app/Http/Requests/UpdateUserRequest.php @@ -29,11 +29,8 @@ public function rules() $user_id = request('id', null); - // Validate if the pilot ID is already being used or not - $rules['pilot_id'] = 'required|integer|unique:users,pilot_id,'.$user_id.',id'; - - // Add additional rules for when we're modifying $rules['email'] .= '|unique:users,email,'.$user_id.',id'; + $rules['pilot_id'] .= '|unique:users,pilot_id,'.$user_id.',id'; return $rules; } diff --git a/app/Models/User.php b/app/Models/User.php index eddb38395..2dd899d9e 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -96,9 +96,9 @@ class User extends Authenticatable ]; public static $rules = [ - 'pilot_id' => 'required|integer|unique:users,pilot_id', 'name' => 'required', 'email' => 'required|email', + 'pilot_id' => 'required|integer', ]; /**