diff --git a/_test/types/UserTest.php b/_test/types/UserTest.php index fe072905..a5848541 100644 --- a/_test/types/UserTest.php +++ b/_test/types/UserTest.php @@ -35,7 +35,19 @@ public function test_validate_success() public function test_ajax() { - global $INPUT; + global $INFO, $INPUT, $USERINFO; + include(__DIR__ . '/../../conf/default.php'); + $default_allow_autocomplete = $conf['allow_username_autocomplete']; + unset($conf); + + global $conf; + $conf['plugin']['struct']['allow_username_autocomplete'] = $default_allow_autocomplete; + $_SERVER['REMOTE_USER'] = 'john'; + $USERINFO['name'] = 'John Smith'; + $USERINFO['mail'] = 'john.smith@example.com'; + $USERINFO['grps'] = ['user', 'test']; + //update info array + $INFO['userinfo'] = $USERINFO; $user = new User( [ @@ -56,6 +68,21 @@ public function test_ajax() $INPUT->set('search', 'd'); // under mininput $this->assertEquals([], $user->handleAjax()); + // Check restrictions on who can access username data are respected + $conf['plugin']['struct']['allow_username_autocomplete'] = 'john'; + $INPUT->set('search', 'dent'); + $this->assertEquals([['label' => 'Arthur Dent [testuser]', 'value' => 'testuser']], $user->handleAjax()); + + $conf['plugin']['struct']['allow_username_autocomplete'] = '@user'; + $INPUT->set('search', 'dent'); + $this->assertEquals([['label' => 'Arthur Dent [testuser]', 'value' => 'testuser']], $user->handleAjax()); + + $conf['plugin']['struct']['allow_username_autocomplete'] = '@not_in_group,not_this_user'; + $INPUT->set('search', 'dent'); + $this->assertEquals([], $user->handleAjax()); + + $conf['plugin']['struct']['allow_username_autocomplete'] = $default_allow_autocomplete; + $user = new User( [ 'autocomplete' => [ diff --git a/conf/default.php b/conf/default.php index e41ca5ca..70b365b2 100644 --- a/conf/default.php +++ b/conf/default.php @@ -4,3 +4,4 @@ $conf['topoutput'] = 0; $conf['disableDeleteSerial'] = 0; $conf['show_not_found'] = 1; +$conf['allow_username_autocomplete'] = '@ALL'; diff --git a/conf/metadata.php b/conf/metadata.php index 5a131dfa..cccebccf 100644 --- a/conf/metadata.php +++ b/conf/metadata.php @@ -4,3 +4,4 @@ $meta['topoutput'] = ['onoff']; $meta['disableDeleteSerial'] = ['onoff']; $meta['show_not_found'] = ['onoff']; +$meta['allow_username_autocomplete'] = ['string']; diff --git a/lang/en/settings.php b/lang/en/settings.php index eae3f50b..fe9bfff9 100644 --- a/lang/en/settings.php +++ b/lang/en/settings.php @@ -4,3 +4,4 @@ $lang['topoutput'] = 'Display data at the top of the page'; $lang['disableDeleteSerial'] = 'Disable delete button for serial data'; $lang['show_not_found'] = 'Show the default text when no results are returned for struct value syntax'; +$lang['allow_username_autocomplete'] = 'Group, user or comma separated list user1,@group1,user2 to offer autocomplete suggestions for username data'; diff --git a/types/AbstractBaseType.php b/types/AbstractBaseType.php index 973599da..fcd7c993 100644 --- a/types/AbstractBaseType.php +++ b/types/AbstractBaseType.php @@ -545,6 +545,18 @@ public function getLang($string) return $this->hlp->getLang($string); } + /** + * Convenience method to access plugin configurations + * + * @param string $string + * @return string + */ + public function getConf($string) + { + if (is_null($this->hlp)) $this->hlp = plugin_load('helper', 'struct'); + return $this->hlp->getConf($string); + } + /** * With what comparator should dynamic filters filter this type? * diff --git a/types/User.php b/types/User.php index 93aa2c08..db929f0f 100644 --- a/types/User.php +++ b/types/User.php @@ -60,18 +60,29 @@ public function renderValue($value, \Doku_Renderer $R, $mode) * Autocompletion for user names * * @return array - * @todo should we have any security mechanism? Currently everybody can look up users */ public function handleAjax() { /** @var AuthPlugin $auth */ global $auth; global $INPUT; + global $_SERVER; + global $USERINFO; if (!$auth->canDo('getUsers')) { return []; } + if ( + !auth_isMember( + $this->getConf('allow_username_autocomplete'), + $_SERVER['REMOTE_USER'], + (array) $USERINFO['grps'] + ) + ) { + return []; + } + // check minimum length $lookup = trim($INPUT->str('search')); if (PhpString::strlen($lookup) < $this->config['autocomplete']['mininput']) return [];