From 92267d528404b1b1d2106cdcf142c3b1e6876def Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Sat, 11 Apr 2020 17:07:07 +0800 Subject: [PATCH 1/9] System admin can edit any user profile --- app/Helpers/functions.php | 12 ++++++++++++ app/Policies/UserPolicy.php | 2 +- tests/Unit/Policies/UserPolicyTest.php | 25 ++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/app/Helpers/functions.php b/app/Helpers/functions.php index 7d01353..ea13fae 100644 --- a/app/Helpers/functions.php +++ b/app/Helpers/functions.php @@ -58,3 +58,15 @@ function userPhotoPath($photoPath, $genderId) return asset('images/icon_user_'.$genderId.'.png'); } + +function is_system_admin(User $user) +{ + if ($user->email) { + if (env('SYSTEM_ADMIN_EMAILS')) { + $adminEmails = explode(';', env('SYSTEM_ADMIN_EMAILS')); + return in_array($user->email, $adminEmails); + } + } + + return false; +} diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index 9338d94..4dd7b41 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -18,7 +18,7 @@ class UserPolicy */ public function edit(User $user, User $editableUser) { - return $editableUser->id == $user->id || $editableUser->manager_id == $user->id; + return $editableUser->id == $user->id || $editableUser->manager_id == $user->id || is_system_admin($user); } /** diff --git a/tests/Unit/Policies/UserPolicyTest.php b/tests/Unit/Policies/UserPolicyTest.php index 8e15134..793eeaa 100644 --- a/tests/Unit/Policies/UserPolicyTest.php +++ b/tests/Unit/Policies/UserPolicyTest.php @@ -3,8 +3,9 @@ namespace Tests\Unit\Policies; use App\User; -use Tests\TestCase; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Str; +use Tests\TestCase; class UserPolicyTest extends TestCase { @@ -13,10 +14,32 @@ class UserPolicyTest extends TestCase /** @test */ public function manager_can_edit_users_profile() { + $otherUserManagerId = Str::random(); + $manager = factory(User::class)->create(); + $user = factory(User::class)->create(['manager_id' => $manager->id]); + $otherUser = factory(User::class)->create(['manager_id' => $otherUserManagerId]); + + $this->assertTrue($manager->can('edit', $user)); + $this->assertFalse($manager->can('edit', $otherUser)); + } + + /** @test */ + public function admins_can_edit_any_user_profile() + { + $adminEmail = 'admin@example.net'; + $otherUserManagerId = Str::random(); + putenv('SYSTEM_ADMIN_EMAILS='.$adminEmail); + $manager = factory(User::class)->create(); + $admin = factory(User::class)->create(['email' => $adminEmail]); $user = factory(User::class)->create(['manager_id' => $manager->id]); + $otherUser = factory(User::class)->create(['manager_id' => $otherUserManagerId]); + + $this->assertTrue($admin->can('edit', $user)); + $this->assertTrue($admin->can('edit', $otherUser)); $this->assertTrue($manager->can('edit', $user)); + $this->assertFalse($manager->can('edit', $otherUser)); } /** @test */ From a37645fafaf26f11a98e530d8531f6e1841e0bdd Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Sat, 11 Apr 2020 17:10:37 +0800 Subject: [PATCH 2/9] System admin can delete any user --- app/Policies/UserPolicy.php | 2 +- tests/Unit/Policies/UserPolicyTest.php | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index 4dd7b41..9004da0 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -30,6 +30,6 @@ class UserPolicy */ public function delete(User $user, User $editableUser) { - return $editableUser->manager_id == $user->id && $editableUser->id != $user->id; + return ($editableUser->manager_id == $user->id || is_system_admin($user)) && $editableUser->id != $user->id; } } diff --git a/tests/Unit/Policies/UserPolicyTest.php b/tests/Unit/Policies/UserPolicyTest.php index 793eeaa..d41dcf5 100644 --- a/tests/Unit/Policies/UserPolicyTest.php +++ b/tests/Unit/Policies/UserPolicyTest.php @@ -53,10 +53,32 @@ class UserPolicyTest extends TestCase /** @test */ public function manager_can_delete_a_user() { + $otherUserManagerId = Str::random(); $manager = factory(User::class)->create(); $user = factory(User::class)->create(['manager_id' => $manager->id]); + $otherUser = factory(User::class)->create(['manager_id' => $otherUserManagerId]); + + $this->assertTrue($manager->can('delete', $user)); + $this->assertFalse($manager->can('delete', $otherUser)); + } + + /** @test */ + public function admins_can_delete_any_user() + { + $adminEmail = 'admin@example.net'; + $otherUserManagerId = Str::random(); + putenv('SYSTEM_ADMIN_EMAILS='.$adminEmail); + + $manager = factory(User::class)->create(); + $admin = factory(User::class)->create(['email' => $adminEmail]); + $user = factory(User::class)->create(['manager_id' => $manager->id]); + $otherUser = factory(User::class)->create(['manager_id' => $otherUserManagerId]); + + $this->assertTrue($admin->can('delete', $user)); + $this->assertTrue($admin->can('delete', $otherUser)); $this->assertTrue($manager->can('delete', $user)); + $this->assertFalse($manager->can('delete', $otherUser)); } /** @test */ From 4b05c2f907b19cf76429c99306e69627be5e0cba Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Sat, 11 Apr 2020 17:19:03 +0800 Subject: [PATCH 3/9] Add test for is_system_admin helper --- tests/Unit/Helpers/IsSystemAdminHelperTest.php | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/Unit/Helpers/IsSystemAdminHelperTest.php diff --git a/tests/Unit/Helpers/IsSystemAdminHelperTest.php b/tests/Unit/Helpers/IsSystemAdminHelperTest.php new file mode 100644 index 0000000..a2ce3e9 --- /dev/null +++ b/tests/Unit/Helpers/IsSystemAdminHelperTest.php @@ -0,0 +1,27 @@ +make(['email' => $adminEmail1]); + $admin2 = factory(User::class)->make(['email' => $adminEmail2]); + $userWithEmail = factory(User::class)->make(['email' => 'user@example.net']); + $userWithNoEmail = factory(User::class)->make(['email' => null]); + + $this->assertTrue(is_system_admin($admin1)); + $this->assertTrue(is_system_admin($admin2)); + $this->assertFalse(is_system_admin($userWithEmail)); + $this->assertFalse(is_system_admin($userWithNoEmail)); + } +} From 444a313fe4e385eb440363fba139dd29d2a5416c Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Sat, 11 Apr 2020 17:29:12 +0800 Subject: [PATCH 4/9] User laravel config for admin emails --- app/Helpers/functions.php | 4 ++-- config/app.php | 12 ++++++++++++ tests/Unit/Helpers/IsSystemAdminHelperTest.php | 19 ++++++++++++++++++- tests/Unit/Policies/UserPolicyTest.php | 4 ++-- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/app/Helpers/functions.php b/app/Helpers/functions.php index ea13fae..0d49361 100644 --- a/app/Helpers/functions.php +++ b/app/Helpers/functions.php @@ -62,8 +62,8 @@ function userPhotoPath($photoPath, $genderId) function is_system_admin(User $user) { if ($user->email) { - if (env('SYSTEM_ADMIN_EMAILS')) { - $adminEmails = explode(';', env('SYSTEM_ADMIN_EMAILS')); + if (config('app.system_admin_emails')) { + $adminEmails = explode(';', config('app.system_admin_emails')); return in_array($user->email, $adminEmails); } } diff --git a/config/app.php b/config/app.php index 0541103..c0b9eb0 100644 --- a/config/app.php +++ b/config/app.php @@ -29,6 +29,18 @@ return [ /* |-------------------------------------------------------------------------- + | System Administrator Emails + |-------------------------------------------------------------------------- + | + | This is config stores emails of users who have role of administrators. + | The user can edit and delete any users and marriages int he system. + | + */ + + 'system_admin_emails' => env('SYSTEM_ADMIN_EMAILS'), + + /* + |-------------------------------------------------------------------------- | Application Debug Mode |-------------------------------------------------------------------------- | diff --git a/tests/Unit/Helpers/IsSystemAdminHelperTest.php b/tests/Unit/Helpers/IsSystemAdminHelperTest.php index a2ce3e9..b3af215 100644 --- a/tests/Unit/Helpers/IsSystemAdminHelperTest.php +++ b/tests/Unit/Helpers/IsSystemAdminHelperTest.php @@ -12,7 +12,7 @@ class IsSystemAdminHelperTest extends TestCase { $adminEmail1 = 'admin1@example.net'; $adminEmail2 = 'admin2@example.net'; - putenv('SYSTEM_ADMIN_EMAILS='.$adminEmail1.';'.$adminEmail2); + config(['app.system_admin_emails' => $adminEmail1.';'.$adminEmail2]); $admin1 = factory(User::class)->make(['email' => $adminEmail1]); $admin2 = factory(User::class)->make(['email' => $adminEmail2]); @@ -24,4 +24,21 @@ class IsSystemAdminHelperTest extends TestCase $this->assertFalse(is_system_admin($userWithEmail)); $this->assertFalse(is_system_admin($userWithNoEmail)); } + + /** @test */ + public function if_config_is_null() + { + $adminEmail1 = 'admin1@example.net'; + $adminEmail2 = 'admin2@example.net'; + + $admin1 = factory(User::class)->make(['email' => $adminEmail1]); + $admin2 = factory(User::class)->make(['email' => $adminEmail2]); + $userWithEmail = factory(User::class)->make(['email' => 'user@example.net']); + $userWithNoEmail = factory(User::class)->make(['email' => null]); + + $this->assertFalse(is_system_admin($admin1)); + $this->assertFalse(is_system_admin($admin2)); + $this->assertFalse(is_system_admin($userWithEmail)); + $this->assertFalse(is_system_admin($userWithNoEmail)); + } } diff --git a/tests/Unit/Policies/UserPolicyTest.php b/tests/Unit/Policies/UserPolicyTest.php index d41dcf5..be79a75 100644 --- a/tests/Unit/Policies/UserPolicyTest.php +++ b/tests/Unit/Policies/UserPolicyTest.php @@ -28,7 +28,7 @@ class UserPolicyTest extends TestCase { $adminEmail = 'admin@example.net'; $otherUserManagerId = Str::random(); - putenv('SYSTEM_ADMIN_EMAILS='.$adminEmail); + config(['app.system_admin_emails' => $adminEmail]); $manager = factory(User::class)->create(); $admin = factory(User::class)->create(['email' => $adminEmail]); @@ -67,7 +67,7 @@ class UserPolicyTest extends TestCase { $adminEmail = 'admin@example.net'; $otherUserManagerId = Str::random(); - putenv('SYSTEM_ADMIN_EMAILS='.$adminEmail); + config(['app.system_admin_emails' => $adminEmail]); $manager = factory(User::class)->create(); $admin = factory(User::class)->create(['email' => $adminEmail]); From e3ab5b5a56b042255f4d339c9db6bef8608d7845 Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Sat, 11 Apr 2020 19:27:10 +0800 Subject: [PATCH 5/9] Add SYSTEM_ADMIN_EMAILS on .env.example --- .env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.example b/.env.example index c8f3f95..73273f2 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,7 @@ APP_KEY= APP_DEBUG=true APP_LOG_LEVEL=debug APP_URL=http://localhost +SYSTEM_ADMIN_EMAILS= LOG_CHANNEL=stack From 0b4acf04f1be764f835f9d412273a274d9d11839 Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Sat, 11 Apr 2020 19:32:59 +0800 Subject: [PATCH 6/9] System admin can edit any couple data --- app/Policies/CouplePolicy.php | 2 +- tests/Unit/Policies/CouplePolicyTest.php | 30 +++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/app/Policies/CouplePolicy.php b/app/Policies/CouplePolicy.php index 60ef143..c09d29d 100644 --- a/app/Policies/CouplePolicy.php +++ b/app/Policies/CouplePolicy.php @@ -19,6 +19,6 @@ class CouplePolicy */ public function edit(User $user, Couple $couple) { - return $couple->manager_id == $user->id; + return $couple->manager_id == $user->id || is_system_admin($user); } } diff --git a/tests/Unit/Policies/CouplePolicyTest.php b/tests/Unit/Policies/CouplePolicyTest.php index c6efe71..5e2639e 100644 --- a/tests/Unit/Policies/CouplePolicyTest.php +++ b/tests/Unit/Policies/CouplePolicyTest.php @@ -3,7 +3,9 @@ namespace Tests\Unit\Policies; use App\Couple; +use App\User; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Str; use Tests\TestCase; class CouplePolicyTest extends TestCase @@ -11,11 +13,33 @@ class CouplePolicyTest extends TestCase use RefreshDatabase; /** @test */ - public function admin_can_edit_couple_data() + public function manager_can_edit_couples() { - $couple = factory(Couple::class)->create(); - $manager = $couple->manager; + $otherCoupleManagerId = Str::random(); + $manager = factory(User::class)->create(); + $couple = factory(Couple::class)->create(['manager_id' => $manager->id]); + $otherCouple = factory(Couple::class)->create(['manager_id' => $otherCoupleManagerId]); $this->assertTrue($manager->can('edit', $couple)); + $this->assertFalse($manager->can('edit', $otherCouple)); + } + + /** @test */ + public function admins_can_edit_any_couple_data() + { + $adminEmail = 'admin@example.net'; + $otherCoupleManagerId = Str::random(); + config(['app.system_admin_emails' => $adminEmail]); + + $manager = factory(User::class)->create(); + $admin = factory(User::class)->create(['email' => $adminEmail]); + $couple = factory(Couple::class)->create(['manager_id' => $manager->id]); + $otherCouple = factory(Couple::class)->create(['manager_id' => $otherCoupleManagerId]); + + $this->assertTrue($admin->can('edit', $couple)); + $this->assertTrue($admin->can('edit', $otherCouple)); + + $this->assertTrue($manager->can('edit', $couple)); + $this->assertFalse($manager->can('edit', $otherCouple)); } } From 4768f5f0e3c7e04526d25764d9949c14484002fe Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Sat, 11 Apr 2020 19:36:57 +0800 Subject: [PATCH 7/9] Fix missing birthday lang --- resources/lang/en/birthday.php | 11 ++++++----- resources/lang/id/birthday.php | 11 ++++++----- resources/views/birthdays/index.blade.php | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/resources/lang/en/birthday.php b/resources/lang/en/birthday.php index a90b50b..6d1eb6f 100644 --- a/resources/lang/en/birthday.php +++ b/resources/lang/en/birthday.php @@ -1,9 +1,10 @@ 'Birhtday', - 'upcoming' => 'Upcoming birthdays', - 'remaining' => ':count days', - 'age_years' => ':age years', - 'days' => 'days', + 'birthday' => 'Birthday', + 'upcoming' => 'Upcoming birthdays', + 'no_upcoming' => 'No upcoming birthdays in the next :days days.', + 'remaining' => ':count days', + 'age_years' => ':age years', + 'days' => 'days', ]; diff --git a/resources/lang/id/birthday.php b/resources/lang/id/birthday.php index 7a446a6..6962549 100644 --- a/resources/lang/id/birthday.php +++ b/resources/lang/id/birthday.php @@ -1,9 +1,10 @@ 'Ulang Tahun', - 'upcoming' => 'Ulang tahun akan datang', - 'remaining' => ':count hari', - 'age_years' => ':age tahun', - 'days' => 'Hari', + 'birthday' => 'Ulang Tahun', + 'upcoming' => 'Ulang tahun akan datang', + 'no_upcoming' => 'Belum ada ulang tahun dalam :days hari kedepan.', + 'remaining' => ':count hari', + 'age_years' => ':age tahun', + 'days' => 'Hari', ]; diff --git a/resources/views/birthdays/index.blade.php b/resources/views/birthdays/index.blade.php index 713df35..422831f 100644 --- a/resources/views/birthdays/index.blade.php +++ b/resources/views/birthdays/index.blade.php @@ -35,7 +35,7 @@ @empty - {{ __('user.no_upcoming_birthday', ['days' => 60]) }} + {{ __('birthday.no_upcoming', ['days' => 60]) }} @endforelse From d65eaf9e63dc79a46ee1b7147bf8f864389c801d Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Sat, 11 Apr 2020 22:15:28 +0800 Subject: [PATCH 8/9] Create admin only middleware --- app/Http/Kernel.php | 1 + app/Http/Middleware/AdminOnly.php | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 app/Http/Middleware/AdminOnly.php diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 41fa18a..56caea8 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -53,6 +53,7 @@ class Kernel extends HttpKernel protected $routeMiddleware = [ 'auth' => \Illuminate\Auth\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, + 'admin' => \App\Http\Middleware\AdminOnly::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, diff --git a/app/Http/Middleware/AdminOnly.php b/app/Http/Middleware/AdminOnly.php new file mode 100644 index 0000000..63a89d2 --- /dev/null +++ b/app/Http/Middleware/AdminOnly.php @@ -0,0 +1,24 @@ +user())) { + abort(403); + } + + return $next($request); + } +} From 418b7a2ac629638cefdee1c74344338538a0761a Mon Sep 17 00:00:00 2001 From: Nafies Luthfi Date: Sat, 11 Apr 2020 22:16:04 +0800 Subject: [PATCH 9/9] Apply admin only middleware to backup restore database feature --- resources/views/layouts/partials/nav.blade.php | 4 +++- routes/web.php | 15 ++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/resources/views/layouts/partials/nav.blade.php b/resources/views/layouts/partials/nav.blade.php index 00a14f3..bdfbfff 100644 --- a/resources/views/layouts/partials/nav.blade.php +++ b/resources/views/layouts/partials/nav.blade.php @@ -39,7 +39,9 @@