From 085823c16c31482c3d7d26d1dbb8ab2728566544 Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Sat, 25 May 2013 00:01:36 -0400 Subject: [PATCH] CRM-12499 - CRM_Core_Permission_Base::translatePermission Add helper function translatePermission which translates an expression like "administer CiviCRM", "cms:view user account", or "drupal:access user profiles" into something understood by native CMS. Use translatePermission as part of check() in D6, D7, WP. Use placeholder permssions ALWAYS_ALLOW_PERMISSION and ALWAYS_DENY_PERMISSION for select corner cases. ---------------------------------------- * CRM-12499: Allow users with 'access user profiles' to access $userRecordUrl http://issues.civicrm.org/jira/browse/CRM-12499 --- CRM/Core/Permission.php | 10 +++++ CRM/Core/Permission/Base.php | 22 +++++++++++ CRM/Core/Permission/Drupal.php | 23 +++++++++++ CRM/Core/Permission/Drupal6.php | 24 ++++++++++++ CRM/Core/Permission/DrupalBase.php | 15 ------- CRM/Core/Permission/WordPress.php | 10 +++++ .../phpunit/CRM/Core/Permission/BaseTest.php | 39 +++++++++++++++++++ .../CRM/Core/Permission/GenericTest.php | 38 ++++++++++++++++++ 8 files changed, 166 insertions(+), 15 deletions(-) create mode 100644 tests/phpunit/CRM/Core/Permission/BaseTest.php create mode 100644 tests/phpunit/CRM/Core/Permission/GenericTest.php diff --git a/CRM/Core/Permission.php b/CRM/Core/Permission.php index e27da5830f..639308bf87 100644 --- a/CRM/Core/Permission.php +++ b/CRM/Core/Permission.php @@ -53,6 +53,16 @@ class CRM_Core_Permission { */ CONST EDIT = 1, VIEW = 2, DELETE = 3, CREATE = 4, SEARCH = 5, ALL = 6, ADMIN = 7; + /** + * A placeholder permission which always fails + */ + const ALWAYS_DENY_PERMISSION = "*always deny*"; + + /** + * A placeholder permission which always fails + */ + const ALWAYS_ALLOW_PERMISSION = "*always allow*"; + /** * get the current permission of this user * diff --git a/CRM/Core/Permission/Base.php b/CRM/Core/Permission/Base.php index 3b3a406967..31bfdf3ab1 100644 --- a/CRM/Core/Permission/Base.php +++ b/CRM/Core/Permission/Base.php @@ -38,6 +38,28 @@ */ class CRM_Core_Permission_Base { + /** + * Translate permission + * + * @param string $name e.g. "administer CiviCRM", "cms:access user record", "Drupal:administer content", "Joomla:action:com_asset" + * @param string $nativePrefix + * @param array $map array($portableName => $nativeName) + * @return NULL|string a permission name + */ + public function translatePermission($perm, $nativePrefix, $map) { + list ($civiPrefix, $name) = CRM_Utils_String::parsePrefix(':', $perm, NULL); + switch ($civiPrefix) { + case $nativePrefix: + return $name; // pass through + case 'cms': + return CRM_Utils_Array::value($name, $map, CRM_Core_Permission::ALWAYS_DENY_PERMISSION); + case NULL: + return $name; + default: + return CRM_Core_Permission::ALWAYS_DENY_PERMISSION; + } + } + /** * get the current permission of this user * diff --git a/CRM/Core/Permission/Drupal.php b/CRM/Core/Permission/Drupal.php index 60c15c9097..7f82fccaa9 100644 --- a/CRM/Core/Permission/Drupal.php +++ b/CRM/Core/Permission/Drupal.php @@ -62,6 +62,29 @@ class CRM_Core_Permission_Drupal extends CRM_Core_Permission_DrupalBase{ protected $_editPermissionedGroups; + /** + * given a permission string, check for access requirements + * + * @param string $str the permission to check + * + * @return boolean true if yes, else false + * @access public + */ + function check($str, $contactID = NULL) { + $str = $this->translatePermission($str, 'Drupal', array( + 'view user account' => 'access user profiles', + )); + if ($str == CRM_Core_Permission::ALWAYS_DENY_PERMISSION) { + return FALSE; + } + if ($str == CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION) { + return TRUE; + } + if (function_exists('user_access')) { + return user_access($str) ? TRUE : FALSE; + } + return TRUE; + } /** * Given a roles array, check for access requirements diff --git a/CRM/Core/Permission/Drupal6.php b/CRM/Core/Permission/Drupal6.php index 8c7d2c26fe..11690904f3 100644 --- a/CRM/Core/Permission/Drupal6.php +++ b/CRM/Core/Permission/Drupal6.php @@ -61,6 +61,30 @@ class CRM_Core_Permission_Drupal6 extends CRM_Core_Permission_DrupalBase { protected $_viewPermissionedGroups; protected $_editPermissionedGroups; + /** + * given a permission string, check for access requirements + * + * @param string $str the permission to check + * + * @return boolean true if yes, else false + * @access public + */ + function check($str, $contactID = NULL) { + $str = $this->translatePermission($str, 'Drupal6', array( + 'view user account' => 'access user profiles', + )); + if ($str == CRM_Core_Permission::ALWAYS_DENY_PERMISSION) { + return FALSE; + } + if ($str == CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION) { + return TRUE; + } + if (function_exists('user_access')) { + return user_access($str) ? TRUE : FALSE; + } + return TRUE; + } + /** * Given a roles array, check for access requirements * diff --git a/CRM/Core/Permission/DrupalBase.php b/CRM/Core/Permission/DrupalBase.php index 296915d0cb..c4bd8a3c12 100644 --- a/CRM/Core/Permission/DrupalBase.php +++ b/CRM/Core/Permission/DrupalBase.php @@ -215,21 +215,6 @@ class CRM_Core_Permission_DrupalBase extends CRM_Core_Permission_Base { return NULL; } - /** - * given a permission string, check for access requirements - * - * @param string $str the permission to check - * - * @return boolean true if yes, else false - * @access public - */ - function check($str, $contactID = NULL) { - if (function_exists('user_access')) { - return user_access($str) ? TRUE : FALSE; - } - return TRUE; - } - function getContactEmails($uids) { if (empty($uids)) { return ''; diff --git a/CRM/Core/Permission/WordPress.php b/CRM/Core/Permission/WordPress.php index d77e2237c8..9d9d347c0a 100644 --- a/CRM/Core/Permission/WordPress.php +++ b/CRM/Core/Permission/WordPress.php @@ -46,6 +46,16 @@ class CRM_Core_Permission_WordPress extends CRM_Core_Permission_Base { * @access public */ function check($str) { + $str = $this->translatePermission($str, 'WordPress', array( + 'view user account' => 'administrator', + )); + if ($str == CRM_Core_Permission::ALWAYS_DENY_PERMISSION) { + return FALSE; + } + if ($str == CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION) { + return TRUE; + } + // for administrators give them all permissions if (!function_exists('current_user_can')) { return TRUE; diff --git a/tests/phpunit/CRM/Core/Permission/BaseTest.php b/tests/phpunit/CRM/Core/Permission/BaseTest.php new file mode 100644 index 0000000000..606637ce50 --- /dev/null +++ b/tests/phpunit/CRM/Core/Permission/BaseTest.php @@ -0,0 +1,39 @@ + input to translatePermission, 1 => expected output from translatePermission) + */ + public function translateData() { + $cases = array(); + + $cases[] = array("administer CiviCRM", "administer CiviCRM"); + $cases[] = array("cms:universal name", "local name"); + $cases[] = array("cms:universal name2", "local name2"); + $cases[] = array("cms:unknown universal name", CRM_Core_Permission::ALWAYS_DENY_PERMISSION); + $cases[] = array("myruntime:foo", "foo"); + $cases[] = array("otherruntime:foo", CRM_Core_Permission::ALWAYS_DENY_PERMISSION); + $cases[] = array("otherruntime:foo:bar", CRM_Core_Permission::ALWAYS_DENY_PERMISSION); + $cases[] = array(CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION, CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION); + + return $cases; + } + + /** + * @dataProvider translateData + * @param string $input the name of a permission which should be translated + * @param string $expected the name of an actual permission (based on translation matrix for "runtime") + */ + public function testTranslate($input, $expected) { + $perm = new CRM_Core_Permission_Base(); + $actual = $perm->translatePermission($input, "myruntime", array( + 'universal name' => 'local name', + 'universal name2' => 'local name2', + 'gunk' => 'gunky', + )); + $this->assertEquals($expected, $actual); + } +} diff --git a/tests/phpunit/CRM/Core/Permission/GenericTest.php b/tests/phpunit/CRM/Core/Permission/GenericTest.php new file mode 100644 index 0000000000..90459c5e0a --- /dev/null +++ b/tests/phpunit/CRM/Core/Permission/GenericTest.php @@ -0,0 +1,38 @@ +assertEquals(FALSE, $provider->check(CRM_Core_Permission::ALWAYS_DENY_PERMISSION)); + } + + /** + * @dataProvider permissionClasses + * @param string $providerClass + */ + public function testAlwaysAllowPermission($providerClass) { + $provider = new $providerClass(); + $this->assertEquals(TRUE, $provider->check(CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION)); + } +} -- 2.25.1