diff --git a/inc/Action/Admin.php b/inc/Action/Admin.php index 8d43057888fdd26c00e55f5cdc40bedcee954796..eedf7174cdd47ce5f448d9ec55d78cf93ff9b8cc 100644 --- a/inc/Action/Admin.php +++ b/inc/Action/Admin.php @@ -41,7 +41,7 @@ class Admin extends AbstractUserAction { if(($page = $INPUT->str('page', '', true)) != '') { /** @var $plugin \DokuWiki_Admin_Plugin */ if($plugin = plugin_getRequestAdminPlugin()) { // FIXME this method does also permission checking - if($plugin->forAdminOnly() && !$INFO['isadmin']) { + if(!$plugin->isAccessibleByCurrentUser()) { throw new ActionException('denied'); } $plugin->handle(); diff --git a/inc/Ui/Admin.php b/inc/Ui/Admin.php index aa3b8b99e281c17e5c20b0a5b7159b495acc3e4c..20416e1371c86bc65eff9589674472a9f9ec91be 100644 --- a/inc/Ui/Admin.php +++ b/inc/Ui/Admin.php @@ -12,6 +12,9 @@ namespace dokuwiki\Ui; */ class Admin extends Ui { + protected $forAdmins = array('usermanager', 'acl', 'extension', 'config', 'styling'); + protected $forManagers = array('revert', 'popularity'); + /** @var array[] */ protected $menu; /** @@ -24,58 +27,30 @@ class Admin extends Ui { echo '<div class="ui-admin">'; echo p_locale_xhtml('admin'); $this->showSecurityCheck(); - $this->showAdminMenu(); - $this->showManagerMenu(); + $this->showMenu('admin'); + $this->showMenu('manager'); $this->showVersion(); - $this->showPluginMenu(); + $this->showMenu('other'); echo '</div>'; } /** - * Display the standard admin tasks + * Show the given menu of available plugins + * + * @param string $type admin|manager|other */ - protected function showAdminMenu() { - /** @var \DokuWiki_Auth_Plugin $auth */ - global $auth; - global $INFO; - - if(!$INFO['isadmin']) return; - - // user manager only if the auth backend supports it - if(!$auth || !$auth->canDo('getUsers') ) { - if(isset($this->menu['usermanager'])) unset($this->menu['usermanager']); + protected function showMenu($type) { + if (!$this->menu[$type]) return; + + if ($type === 'other') { + echo p_locale_xhtml('adminplugins'); + $class = 'admin_plugins'; + } else { + $class = 'admin_tasks'; } - echo '<ul class="admin_tasks">'; - foreach(array('usermanager','acl', 'extension', 'config', 'styling') as $plugin) { - if(!isset($this->menu[$plugin])) continue; - $this->showMenuItem($this->menu[$plugin]); - unset($this->menu[$plugin]); - } - echo '</ul>'; - } - - /** - * Display the standard manager tasks - */ - protected function showManagerMenu() { - echo '<ul class="admin_tasks">'; - foreach(array('revert','popularity') as $plugin) { - if(!isset($this->menu[$plugin])) continue; - $this->showMenuItem($this->menu[$plugin]); - unset($this->menu[$plugin]); - } - echo '</ul>'; - } - - /** - * Display all the remaining plugins - */ - protected function showPluginMenu() { - if(!count($this->menu)) return; - echo p_locale_xhtml('adminplugins'); - echo '<ul class="admin_plugins">'; - foreach ($this->menu as $item) { + echo "<ul class=\"$class\">"; + foreach ($this->menu[$type] as $item) { $this->showMenuItem($item); } echo '</ul>'; @@ -104,7 +79,9 @@ class Admin extends Ui { if(substr($conf['savedir'], 0, 2) !== './') return; echo '<a style="border:none; float:right;" href="http://www.dokuwiki.org/security#web_access_security"> - <img src="' . DOKU_URL . $conf['savedir'] . '/dont-panic-if-you-see-this-in-your-logs-it-means-your-directory-permissions-are-correct.png" alt="Your data directory seems to be protected properly." + <img src="' . DOKU_URL . $conf['savedir'] . + '/dont-panic-if-you-see-this-in-your-logs-it-means-your-directory-permissions-are-correct.png" + alt="Your data directory seems to be protected properly." onerror="this.parentNode.style.display=\'none\'" /></a>'; } @@ -136,19 +113,27 @@ class Admin extends Ui { * @return array list of plugins with their properties */ protected function getPluginList() { - global $INFO; global $conf; $pluginlist = plugin_list('admin'); - $menu = array(); + $menu = ['admin' => [], 'manager' => [], 'other' => []]; + foreach($pluginlist as $p) { /** @var \DokuWiki_Admin_Plugin $obj */ - if(($obj = plugin_load('admin', $p)) === null) continue; + if (($obj = plugin_load('admin', $p)) === null) continue; // check permissions - if($obj->forAdminOnly() && !$INFO['isadmin']) continue; + if (!$obj->isAccessibleByCurrentUser()) continue; + + if (in_array($p, $this->forAdmins, true)) { + $type = 'admin'; + } elseif (in_array($p, $this->forManagers, true)){ + $type = 'manager'; + } else { + $type = 'other'; + } - $menu[$p] = array( + $menu[$type][$p] = array( 'plugin' => $p, 'prompt' => $obj->getMenuText($conf['lang']), 'icon' => $obj->getMenuIcon(), @@ -157,17 +142,26 @@ class Admin extends Ui { } // sort by name, then sort - uasort( - $menu, - function ($a, $b) { - $strcmp = strcasecmp($a['prompt'], $b['prompt']); - if($strcmp != 0) return $strcmp; - if($a['sort'] == $b['sort']) return 0; - return ($a['sort'] < $b['sort']) ? -1 : 1; - } - ); + uasort($menu['admin'], [$this, 'menuSort']); + uasort($menu['manager'], [$this, 'menuSort']); + uasort($menu['other'], [$this, 'menuSort']); return $menu; } + /** + * Custom sorting for admin menu + * + * We sort alphabetically first, then by sort value + * + * @param array $a + * @param array $b + * @return int + */ + protected function menuSort ($a, $b) { + $strcmp = strcasecmp($a['prompt'], $b['prompt']); + if($strcmp != 0) return $strcmp; + if($a['sort'] === $b['sort']) return 0; + return ($a['sort'] < $b['sort']) ? -1 : 1; + } } diff --git a/inc/pluginutils.php b/inc/pluginutils.php index a395be43512ba5c4afe766353797200f67582ca3..0cd113b14825258485dcba8328af3d97216b1781 100644 --- a/inc/pluginutils.php +++ b/inc/pluginutils.php @@ -123,7 +123,7 @@ function plugin_getRequestAdminPlugin(){ /** @var $admin_plugin DokuWiki_Admin_Plugin */ $admin_plugin = plugin_load('admin', $page); // verify - if ($admin_plugin && $admin_plugin->forAdminOnly() && !$INFO['isadmin']) { + if ($admin_plugin && !$admin_plugin->isAccessibleByCurrentUser()) { $admin_plugin = null; $INPUT->remove('page'); msg('For admins only',-1); diff --git a/lib/plugins/admin.php b/lib/plugins/admin.php index 4e1cbbb337c11393ab40afeaa4b769a9e35c11cd..770fe582f9193481d5930a6cb58c8fcbb58405bd 100644 --- a/lib/plugins/admin.php +++ b/lib/plugins/admin.php @@ -72,6 +72,29 @@ class DokuWiki_Admin_Plugin extends DokuWiki_Plugin { trigger_error('html() not implemented in '.get_class($this), E_USER_WARNING); } + /** + * Checks if access should be granted to this admin plugin + * + * @return bool true if the current user may access this admin plugin + */ + public function isAccessibleByCurrentUser() { + global $INFO; + + $data['hasAccess'] = false; + + $event = new Doku_Event('ADMINPLUGIN_ACCESS_CHECK', $data); + if($event->advise_before()) { + if ($this->forAdminOnly()) { + $data['hasAccess'] = $INFO['isadmin']; + } else { + $data['hasAccess'] = $INFO['ismanager']; + } + } + $event->advise_after(); + + return $data['hasAccess']; + } + /** * Return true for access only by admins (config:superuser) or false if managers are allowed as well * diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index 6d9bf3b202bbd5067f9338e9523ed57500f3fe35..3148971ce19f137816ae1f333716ec80d0f7bdd1 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -297,6 +297,24 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { return true; } + /** + * User Manager is only available if the auth backend supports it + * + * @inheritdoc + * @return bool + */ + public function isAccessibleByCurrentUser() + { + /** @var DokuWiki_Auth_Plugin $auth */ + global $auth; + if(!$auth || !$auth->canDo('getUsers') ) { + return false; + } + + return parent::isAccessibleByCurrentUser(); + } + + /** * Display form to add or modify a user *