From 919835e5dedea477c1a160e655537657e26efbd3 Mon Sep 17 00:00:00 2001 From: Dan Harrin Date: Sat, 21 Sep 2019 16:42:11 +0100 Subject: [PATCH] Add method removePermission() for AuthManager (#4522) Allows programmatic removal of permissions being listed in Permission selection widget. Credit to @DanHarrin. --- modules/backend/classes/AuthManager.php | 26 ++- .../unit/backend/classes/AuthManagerTest.php | 150 ++++++++++++++++++ 2 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 tests/unit/backend/classes/AuthManagerTest.php diff --git a/modules/backend/classes/AuthManager.php b/modules/backend/classes/AuthManager.php index 3eadb5633..365dd2522 100644 --- a/modules/backend/classes/AuthManager.php +++ b/modules/backend/classes/AuthManager.php @@ -2,6 +2,7 @@ use System\Classes\PluginManager; use October\Rain\Auth\Manager as RainAuthManager; +use October\Rain\Exception\SystemException; /** * Back-end authentication manager. @@ -81,7 +82,7 @@ class AuthManager extends RainAuthManager * - order - a position of the item in the menu, optional. * - comment - a brief comment that describes the permission, optional. * - tab - assign this permission to a tabbed group, optional. - * @param string $owner Specifies the menu items owner plugin or module in the format Vendor/Module. + * @param string $owner Specifies the permissions' owner plugin or module in the format Author.Plugin * @param array $definitions An array of the menu item definitions. */ public function registerPermissions($owner, array $definitions) @@ -96,6 +97,29 @@ class AuthManager extends RainAuthManager } } + /** + * Removes a single back-end permission + * @param string $owner Specifies the permissions' owner plugin or module in the format Author.Plugin + * @param string $code The code of the permission to remove + * @return void + */ + public function removePermission($owner, $code) + { + if (!$this->permissions) { + throw new SystemException('Unable to remove permissions before they are loaded.'); + } + + $ownerPermissions = array_filter($this->permissions, function ($permission) use ($owner) { + return $permission->owner === $owner; + }); + + foreach ($ownerPermissions as $key => $permission) { + if ($permission->code === $code) { + unset($this->permissions[$key]); + } + } + } + /** * Returns a list of the registered permissions items. * @return array diff --git a/tests/unit/backend/classes/AuthManagerTest.php b/tests/unit/backend/classes/AuthManagerTest.php new file mode 100644 index 000000000..6bb9f9684 --- /dev/null +++ b/tests/unit/backend/classes/AuthManagerTest.php @@ -0,0 +1,150 @@ +createApplication(); + + $this->instance = AuthManager::instance(); + $this->instance->registerPermissions('October.TestCase', [ + 'test.permission_one' => [ + 'label' => 'Test Permission 1', + 'tab' => 'Test', + 'order' => 200 + ], + 'test.permission_two' => [ + 'label' => 'Test Permission 2', + 'tab' => 'Test', + 'order' => 300 + ] + ]); + } + + public function tearDown() + { + AuthManager::forgetInstance(); + } + + public function testListPermissions() + { + $permissions = $this->instance->listPermissions(); + $this->assertCount(2, $permissions); + $this->assertEquals([ + 'test.permission_one', + 'test.permission_two' + ], collect($permissions)->pluck('code')->toArray()); + } + + public function testRegisterPermissions() + { + $this->instance->registerPermissions('October.TestCase', [ + 'test.permission_three' => [ + 'label' => 'Test Permission 3', + 'tab' => 'Test', + 'order' => 100 + ] + ]); + + $permissions = $this->instance->listPermissions(); + $this->assertCount(3, $permissions); + $this->assertEquals([ + 'test.permission_three', + 'test.permission_one', + 'test.permission_two' + ], collect($permissions)->pluck('code')->toArray()); + } + + public function testRegisterPermissionsThroughCallbacks() + { + // Callback one + $this->instance->registerCallback(function ($manager) { + $manager->registerPermissions('October.TestCase', [ + 'test.permission_three' => [ + 'label' => 'Test Permission 3', + 'tab' => 'Test', + 'order' => 100 + ] + ]); + }); + + // Callback two + $this->instance->registerCallback(function ($manager) { + $manager->registerPermissions('October.TestCase', [ + 'test.permission_four' => [ + 'label' => 'Test Permission 4', + 'tab' => 'Test', + 'order' => 400 + ] + ]); + }); + + $permissions = $this->instance->listPermissions(); + $this->assertCount(4, $permissions); + $this->assertEquals([ + 'test.permission_three', + 'test.permission_one', + 'test.permission_two', + 'test.permission_four' + ], collect($permissions)->pluck('code')->toArray()); + } + + public function testRegisterAdditionalTab() + { + $this->instance->registerPermissions('October.TestCase', [ + 'test.permission_three' => [ + 'label' => 'Test Permission 3', + 'tab' => 'Test 2', + 'order' => 100 + ] + ]); + + $this->instance->registerCallback(function ($manager) { + $manager->registerPermissions('October.TestCase', [ + 'test.permission_four' => [ + 'label' => 'Test Permission 4', + 'tab' => 'Test 2', + 'order' => 400 + ] + ]); + }); + + $tabs = $this->instance->listTabbedPermissions(); + $this->assertCount(2, $tabs); + $this->assertEquals([ + 'Test 2', + 'Test' + ], array_keys($tabs)); + $this->assertEquals([ + 'test.permission_three', + 'test.permission_four' + ], collect($tabs['Test 2'])->pluck('code')->toArray()); + $this->assertEquals([ + 'test.permission_one', + 'test.permission_two', + ], collect($tabs['Test'])->pluck('code')->toArray()); + } + + public function testRemovePermission() + { + $this->instance->removePermission('October.TestCase', 'test.permission_one'); + + $permissions = $this->instance->listPermissions(); + $this->assertCount(1, $permissions); + $this->assertEquals([ + 'test.permission_two' + ], collect($permissions)->pluck('code')->toArray()); + } + + public function testCannotRemovePermissionsBeforeLoaded() + { + $this->expectException(SystemException::class); + $this->expectExceptionMessage('Unable to remove permissions before they are loaded.'); + + AuthManager::forgetInstance(); + $this->instance = AuthManager::instance(); + $this->instance->removePermission('October.TestCase', 'test.permission_one'); + } +}