diff options
-rw-r--r-- | Zotlabs/Access/Permissions.php | 158 | ||||
-rw-r--r-- | tests/unit/Access/PermissionsTest.php | 148 |
2 files changed, 254 insertions, 52 deletions
diff --git a/Zotlabs/Access/Permissions.php b/Zotlabs/Access/Permissions.php index d51e4d0ea..74286934f 100644 --- a/Zotlabs/Access/Permissions.php +++ b/Zotlabs/Access/Permissions.php @@ -1,45 +1,52 @@ <?php - namespace Zotlabs\Access; use Zotlabs\Lib as Zlib; +/** + * @brief Extensible permissions. + * + * To add new permissions, add to the list of $perms below, with a simple description. + * + * Also visit PermissionRoles.php and add to the $ret['perms_connect'] property for any role + * if this permission should be granted to new connections. + * + * Next look at PermissionRoles::new_custom_perms() and provide a handler for updating custom + * permission roles. You will want to set a default PermissionLimit for each channel and also + * provide a sane default for any existing connections. You may or may not wish to provide a + * default auto permission. If in doubt, leave this alone as custom permissions by definition + * are the responsibility of the channel owner to manage. You just don't want to create any + * suprises or break things so you have an opportunity to provide sane settings. + * + * Update the version here and in PermissionRoles. + * + * + * Permissions with 'view' in the name are considered read permissions. Anything + * else requires authentication. Read permission limits are PERMS_PUBLIC and anything else + * is given PERMS_SPECIFIC. + * + * PermissionLimits::Std_limits() retrieves the standard limits. A permission role + * MAY alter an individual setting after retrieving the Std_limits if you require + * something different for a specific permission within the given role. + * + */ class Permissions { - /** - * Extensible permissions. - * To add new permissions, add to the list of $perms below, with a simple description. - * - * Also visit PermissionRoles.php and add to the $ret['perms_connect'] property for any role - * if this permission should be granted to new connections. - * - * Next look at PermissionRoles::new_custom_perms() and provide a handler for updating custom - * permission roles. You will want to set a default PermissionLimit for each channel and also - * provide a sane default for any existing connections. You may or may not wish to provide a - * default auto permission. If in doubt, leave this alone as custom permissions by definition - * are the responsibility of the channel owner to manage. You just don't want to create any - * suprises or break things so you have an opportunity to provide sane settings. - * - * Update the version here and in PermissionRoles - * - * - * Permissions with 'view' in the name are considered read permissions. Anything - * else requires authentication. Read permission limits are PERMS_PUBLIC and anything else - * is given PERMS_SPECIFIC. - * - * PermissionLimits::Std_limits() retrieves the standard limits. A permission role - * MAY alter an individual setting after retrieving the Std_limits if you require - * something different for a specific permission within the given role. - * - */ - static public function version() { // This must match the version in PermissionRoles.php before permission updates can run. return 2; } - + /** + * @brief Return an array with Permissions. + * + * @hooks permissions_list + * * \e array \b permissions + * * \e string \b filter + * @param string $filter (optional) only passed to hook permission_list + * @return Associative array with permissions and short description. + */ static public function Perms($filter = '') { $perms = [ @@ -63,18 +70,27 @@ class Permissions { 'delegate' => t('Can administer my channel') ]; - $x = array('permissions' => $perms, 'filter' => $filter); - call_hooks('permissions_list',$x); - return($x['permissions']); + $x = [ + 'permissions' => $perms, + 'filter' => $filter + ]; + call_hooks('permissions_list', $x); + return($x['permissions']); } + /** + * @brief Perms from the above list that are blocked from anonymous observers. + * + * e.g. you must be authenticated. + * + * @hooks write_perms + * * \e array \b permissions + * @return Associative array with permissions and short description. + */ static public function BlockedAnonPerms() { - // Perms from the above list that are blocked from anonymous observers. - // e.g. you must be authenticated. - - $res = array(); + $res = []; $perms = PermissionLimits::Std_limits(); foreach($perms as $perm => $limit) { if($limit != PERMS_PUBLIC) { @@ -82,17 +98,22 @@ class Permissions { } } - $x = array('permissions' => $res); - call_hooks('write_perms',$x); - return($x['permissions']); + $x = ['permissions' => $res]; + call_hooks('write_perms', $x); + return($x['permissions']); } - // converts [ 0 => 'view_stream', ... ] - // to [ 'view_stream' => 1 ] - // for any permissions in $arr; - // Undeclared permissions are set to 0 - + /** + * @brief Converts indexed perms array to associative perms array. + * + * Converts [ 0 => 'view_stream', ... ] + * to [ 'view_stream' => 1 ] for any permissions in $arr; + * Undeclared permissions which exist in Perms() are added and set to 0. + * + * @param array $arr + * @return array + */ static public function FilledPerms($arr) { if(is_null($arr)) { btlogger('FilledPerms: null'); @@ -101,15 +122,26 @@ class Permissions { $everything = self::Perms(); $ret = []; foreach($everything as $k => $v) { - if(in_array($k,$arr)) + if(in_array($k, $arr)) $ret[$k] = 1; else $ret[$k] = 0; } - return $ret; + return $ret; } + /** + * @brief Convert perms array to indexed array. + * + * Converts [ 'view_stream' => 1 ] for any permissions in $arr + * to [ 0 => ['name' => 'view_stream', 'value' => 1], ... ] + * + * @param array $arr associative perms array 'view_stream' => 1 + * @return Indexed array with elements that look like + * * \e string \b name the perm name (e.g. view_stream) + * * \e int \b value the value of the perm (e.g. 1) + */ static public function OPerms($arr) { $ret = []; if($arr) { @@ -120,7 +152,12 @@ class Permissions { return $ret; } - + /** + * @brief + * + * @param int $channel_id + * @return boolean|array + */ static public function FilledAutoperms($channel_id) { if(! intval(get_pconfig($channel_id,'system','autoperms'))) return false; @@ -137,16 +174,33 @@ class Permissions { return $arr; } - static public function PermsCompare($p1,$p2) { + /** + * @brief Compares that all Permissions from $p1 exist also in $p2. + * + * @param array $p1 The perms that have to exist in $p2 + * @param array $p2 The perms to compare against + * @return boolean true if all perms from $p1 exist also in $p2 + */ + static public function PermsCompare($p1, $p2) { foreach($p1 as $k => $v) { - if(! array_key_exists($k,$p2)) + if(! array_key_exists($k, $p2)) return false; + if($p1[$k] != $p2[$k]) return false; } + return true; } + /** + * @brief + * + * @param int $channel_id A channel id + * @return associative array + * * \e array \b perms Permission array + * * \e int \b automatic 0 or 1 + */ static public function connect_perms($channel_id) { $my_perms = []; @@ -155,7 +209,7 @@ class Permissions { // If a default permcat exists, use that - $pc = ((feature_enabled($channel_id,'permcats')) ? get_pconfig($channel_id,'system','default_permcat') : 'default'); + $pc = ((feature_enabled($channel_id,'permcats')) ? get_pconfig($channel_id,'system','default_permcat') : 'default'); if(! in_array($pc, [ '','default' ])) { $pcp = new Zlib\Permcat($channel_id); $permcat = $pcp->fetch($pc); @@ -167,7 +221,7 @@ class Permissions { } // look up the permission role to see if it specified auto-connect - // and if there was no permcat or a default permcat, set the perms + // and if there was no permcat or a default permcat, set the perms // from the role $role = get_pconfig($channel_id,'system','permissions_role'); @@ -195,7 +249,7 @@ class Permissions { } // If we reached this point with no permissions, the channel is using - // custom perms but they are not automatic. They will be stored in abconfig with + // custom perms but they are not automatic. They will be stored in abconfig with // the channel's channel_hash (the 'self' connection). if(! $my_perms) { diff --git a/tests/unit/Access/PermissionsTest.php b/tests/unit/Access/PermissionsTest.php new file mode 100644 index 000000000..93c641fb1 --- /dev/null +++ b/tests/unit/Access/PermissionsTest.php @@ -0,0 +1,148 @@ +<?php +/* + * Copyright (c) 2017 Hubzilla + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +namespace Zotlabs\Tests\Unit\Access; + +use Zotlabs\Tests\Unit\UnitTestCase; +use Zotlabs\Access\Permissions; + +/** + * @brief Unit Test case for Permissions class. + * + * @covers Zotlabs\Access\Permissions + */ +class PermissionsTest extends UnitTestCase { + + /** + * @dataProvider FilledPermsProvider + */ + public function testFilledPerms($permarr, $expected) { + $this->markTestIncomplete( + 'Need to mock static function Permissions::Perms() ...' + ); + //$this->assertEquals($expected, Permissions::FilledPerms($permarr)); + +/* $perms = $this->getMockBuilder(Permissions::class) + ->setMethods(['Perms']) + ->getMock(); + $perms->expects($this->once()) + ->method('Perms'); + // still calls the static self::Perms() + $perms->FilledPerms($permarr); +*/ + } + public function FilledPermsProvider() { + return [ + 'empty' => [ + [], + ['perm1' => 0, 'perm2' => 0] + ], + 'valild' => [ + [['perm1' => 1]], + ['perm1' => 1, 'perm2' => 0] + ] + ]; + } +/* public function testFilledPermsNull() { + // need to mock global function btlogger(); + Permissions::FilledPerms(null); + } +*/ + /** + * @dataProvider OPermsProvider + * + * @param array $permarr + * @param array $expected + */ + public function testOPerms($permarr, $expected) { + $this->assertEquals($expected, Permissions::OPerms($permarr)); + } + /** + * @return Associative array with test values for OPerms() + * * \e array Array to test + * * \e array Expect array + */ + public function OPermsProvider() { + return [ + 'empty' => [ + [], + [] + ], + 'valid' => [ + ['perm1' => 1, 'perm2' => 0], + [['name' => 'perm1', 'value' => 1], ['name' => 'perm2', 'value' => 0]] + ], + 'null array' => [ + null, + [] + ] + ]; + } + + + /** + * @dataProvider permsCompareProvider + * + * @param array $p1 + * @param array $p2 + * @param boolean $expectedresult + */ + public function testPermsCompare($p1, $p2, $expectedresult) { + $this->assertEquals($expectedresult, Permissions::PermsCompare($p1, $p2)); + } + /** + * @return Associative array with test values for PermsCompare() + * * \e array 1st array + * * \e array 2nd array + * * \e boolean expected result for the test + */ + public function permsCompareProvider() { + return [ + 'equal' => [ + ['perm1' => 1, 'perm2' => 0], + ['perm1' => 1, 'perm2' => 0], + true + ], + 'different values' => [ + ['perm1' => 1, 'perm2' => 0], + ['perm1' => 0, 'perm2' => 1], + false + ], + 'different order' => [ + ['perm1' => 1, 'perm2' => 0], + ['perm2' => 0, 'perm1' => 1], + true + ], + 'partial first in second' => [ + ['perm1' => 1], + ['perm1' => 1, 'perm2' => 0], + true + ], + 'partial second in first' => [ + ['perm1' => 1, 'perm2' => 0], + ['perm1' => 1], + false + ] + ]; + } +}
\ No newline at end of file |