From 66c46618448aec0dc8bf9ea19556f4257229295a Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Tue, 13 Oct 2020 08:52:34 -0400 Subject: [PATCH] Angular Loader: Allow modules to specify permissions to add client-side --- CRM/Mailing/Info.php | 12 ----------- Civi/Angular/AngularLoader.php | 12 ++++++++++- Civi/Angular/Manager.php | 3 +++ ang/crmMailing.ang.php | 10 +++++++++ tests/phpunit/Civi/Angular/LoaderTest.php | 25 +++++++++++++++-------- 5 files changed, 40 insertions(+), 22 deletions(-) diff --git a/CRM/Mailing/Info.php b/CRM/Mailing/Info.php index e339405c56..fa647e4679 100644 --- a/CRM/Mailing/Info.php +++ b/CRM/Mailing/Info.php @@ -159,18 +159,6 @@ class CRM_Mailing_Info extends CRM_Core_Component_Info { $result['crmMailingAB'] = include "$civicrm_root/ang/crmMailingAB.ang.php"; $result['crmD3'] = include "$civicrm_root/ang/crmD3.ang.php"; - CRM_Core_Resources::singleton() - ->addPermissions([ - 'view all contacts', - 'edit all contacts', - 'access CiviMail', - 'create mailings', - 'schedule mailings', - 'approve mailings', - 'delete in CiviMail', - 'edit message templates', - ]); - return $result; } diff --git a/Civi/Angular/AngularLoader.php b/Civi/Angular/AngularLoader.php index be80912a62..11ef57276c 100644 --- a/Civi/Angular/AngularLoader.php +++ b/Civi/Angular/AngularLoader.php @@ -120,8 +120,18 @@ class AngularLoader { foreach ($angular->getResources($moduleNames, 'settingsFactory', 'settingsFactory') as $moduleName => $factory) { $settingsByModule[$moduleName] = array_merge($settingsByModule[$moduleName] ?? [], $factory()); } + // Add clientside permissions + $permissions = []; + $toCheck = $angular->getResources($moduleNames, 'permissions', 'permissions'); + foreach ($toCheck as $perms) { + foreach ((array) $perms as $perm) { + if (!isset($permissions[$perm])) { + $permissions[$perm] = \CRM_Core_Permission::check($perm); + } + } + } // TODO optimization; client-side caching - return array_merge($settingsByModule, [ + return array_merge($settingsByModule, ['permissions' => $permissions], [ 'resourceUrls' => \CRM_Extension_System::singleton()->getMapper()->getActiveModuleUrls(), 'angular' => [ 'modules' => $moduleNames, diff --git a/Civi/Angular/Manager.php b/Civi/Angular/Manager.php index f925b7d343..ab9600175a 100644 --- a/Civi/Angular/Manager.php +++ b/Civi/Angular/Manager.php @@ -31,6 +31,8 @@ class Manager { * List of settings to preload. * - settingsFactory: callable * Callback function to fetch settings. + * - permissions: array + * List of permissions to make available client-side * - requires: array * List of other modules required */ @@ -413,6 +415,7 @@ class Manager { case 'settings': case 'settingsFactory': case 'requires': + case 'permissions': if (!empty($module[$resType])) { $result[$moduleName] = $module[$resType]; } diff --git a/ang/crmMailing.ang.php b/ang/crmMailing.ang.php index ebd23e5f7c..a91d495221 100644 --- a/ang/crmMailing.ang.php +++ b/ang/crmMailing.ang.php @@ -16,4 +16,14 @@ return [ 'partials' => ['ang/crmMailing'], 'settingsFactory' => ['CRM_Mailing_Info', 'createAngularSettings'], 'requires' => ['crmUtil', 'crmAttachment', 'crmAutosave', 'ngRoute', 'ui.utils', 'crmUi', 'dialogService', 'crmResource'], + 'permissions' => [ + 'view all contacts', + 'edit all contacts', + 'access CiviMail', + 'create mailings', + 'schedule mailings', + 'approve mailings', + 'delete in CiviMail', + 'edit message templates', + ], ]; diff --git a/tests/phpunit/Civi/Angular/LoaderTest.php b/tests/phpunit/Civi/Angular/LoaderTest.php index 07857bd040..c6c144b6a2 100644 --- a/tests/phpunit/Civi/Angular/LoaderTest.php +++ b/tests/phpunit/Civi/Angular/LoaderTest.php @@ -29,9 +29,9 @@ class LoaderTest extends \CiviUnitTestCase { public function factoryScenarios() { return [ - ['dummy1', 2, 1], - ['dummy2', 2, 0], - ['dummy3', 2, 2], + ['dummy1', 2, 1, ['access CiviCRM', 'administer CiviCRM']], + ['dummy2', 2, 0, []], + ['dummy3', 2, 2, ['access CiviCRM', 'administer CiviCRM', 'view debug output']], ]; } @@ -43,25 +43,29 @@ class LoaderTest extends \CiviUnitTestCase { * @param $module * @param $expectedSettingCount * @param $expectedCallbackCount + * @param $expectedPermissions */ - public function testSettingFactory($module, $expectedSettingCount, $expectedCallbackCount) { + public function testSettingFactory($module, $expectedSettingCount, $expectedCallbackCount, $expectedPermissions) { (new \Civi\Angular\AngularLoader()) ->setModules([$module]) ->useApp() ->load(); // Run factory callbacks - $factorySettings = \Civi::resources()->getSettings(); + $actual = \Civi::resources()->getSettings(); // Dummy1 module's factory setting should be set if it is loaded directly or required by dummy3 - $this->assertTrue(($expectedCallbackCount > 0) === isset($factorySettings['dummy1']['dummy_setting_factory'])); + $this->assertTrue(($expectedCallbackCount > 0) === isset($actual['dummy1']['dummy_setting_factory'])); // Dummy3 module's factory setting should be set if it is loaded directly - $this->assertTrue(($expectedCallbackCount > 1) === isset($factorySettings['dummy3']['dummy_setting_factory'])); + $this->assertTrue(($expectedCallbackCount > 1) === isset($actual['dummy3']['dummy_setting_factory'])); // Dummy1 module's regular setting should be set if it is loaded directly or required by dummy3 - $this->assertTrue(($module !== 'dummy2') === isset($factorySettings['dummy1']['dummy_setting'])); + $this->assertTrue(($module !== 'dummy2') === isset($actual['dummy1']['dummy_setting'])); // Dummy2 module's regular setting should be set if loaded - $this->assertTrue(($module === 'dummy2') === isset($factorySettings['dummy2']['dummy_setting'])); + $this->assertTrue(($module === 'dummy2') === isset($actual['dummy2']['dummy_setting'])); + + // Assert appropriate permissions have been added + $this->assertEquals($expectedPermissions, array_keys($actual['permissions'])); // Assert the callback functions ran the expected number of times $this->assertEquals($expectedSettingCount, self::$dummy_setting_count); @@ -72,6 +76,7 @@ class LoaderTest extends \CiviUnitTestCase { $modules['dummy1'] = [ 'ext' => 'civicrm', 'settings' => $this->getDummySetting(), + 'permissions' => ['access CiviCRM', 'administer CiviCRM'], 'settingsFactory' => [self::class, 'getDummySettingFactory'], ]; $modules['dummy2'] = [ @@ -82,6 +87,8 @@ class LoaderTest extends \CiviUnitTestCase { 'ext' => 'civicrm', // The string self::class is preferred but passing object $this should also work 'settingsFactory' => [$this, 'getDummySettingFactory'], + // This should get merged with dummy1's permissions + 'permissions' => ['view debug output', 'administer CiviCRM'], 'requires' => ['dummy1'], ]; } -- 2.25.1