Skip to content
Snippets Groups Projects
Unverified Commit 76e41fc5 authored by Andreas Gohr's avatar Andreas Gohr Committed by GitHub
Browse files

Merge pull request #2561 from splitbrain/adminEvent

add event to check access to admin plugins
parents 5a361db5 10580724
No related branches found
No related tags found
No related merge requests found
......@@ -26,7 +26,7 @@ class action_general extends DokuWikiTest {
array('Revert', AUTH_ADMIN, array('exists' => true, 'ismanager' => false)),
array('Revert', AUTH_EDIT, array('exists' => true, 'ismanager' => true)),
array('Admin', AUTH_ADMIN, array('exists' => true, 'ismanager' => false)),
array('Admin', AUTH_READ, array('exists' => true, 'ismanager' => false)), // let in, check later again
array('Admin', AUTH_READ, array('exists' => true, 'ismanager' => true)), // let in, check later again
array('Check', AUTH_READ, array('exists' => true, 'ismanager' => false)), // sensible?
......
......@@ -32,7 +32,9 @@ class template_pagetitle_test extends DokuWikiTest {
}
function test_adminPluginTitle() {
global $ID,$ACT,$INPUT,$conf;
global $ID,$ACT,$INPUT,$conf,$INFO;
$INFO['isadmin'] = true;
$INFO['ismanager'] = true;
if (!plugin_load('admin','revert')) {
$this->markTestSkipped('Revert plugin not found, unable to test admin plugin titles');
......
......@@ -15,22 +15,11 @@ class Admin extends AbstractUserAction {
/** @inheritdoc */
public function minimumPermission() {
global $INFO;
if($INFO['ismanager']) {
return AUTH_READ; // let in check later
} else {
return AUTH_ADMIN;
}
return AUTH_READ; // let in check later
}
public function checkPreconditions() {
parent::checkPreconditions();
global $INFO;
if(!$INFO['ismanager']) {
throw new ActionException('denied');
}
}
public function preProcess() {
......@@ -41,7 +30,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();
......
......@@ -11,14 +11,18 @@ class Admin extends AbstractItem {
/** @inheritdoc */
public function __construct() {
global $INFO;
parent::__construct();
$this->svg = DOKU_INC . 'lib/images/menu/settings.svg';
}
/** @inheritdoc */
public function visibleInContext($ctx)
{
global $INFO;
if(!$INFO['ismanager']) return false;
if(!$INFO['ismanager']) {
throw new \RuntimeException("admin is for managers only");
}
return parent::visibleInContext($ctx);
}
}
......@@ -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;
}
}
......@@ -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);
......
......@@ -34,7 +34,7 @@ class action_plugin_acl extends DokuWiki_Action_Plugin {
* @return void
*/
public function handle_ajax_call_acl(Doku_Event &$event, $param) {
public function handle_ajax_call_acl(Doku_Event $event, $param) {
if($event->data !== 'plugin_acl') {
return;
}
......@@ -44,7 +44,10 @@ class action_plugin_acl extends DokuWiki_Action_Plugin {
global $ID;
global $INPUT;
if(!auth_isadmin()) {
/** @var $acl admin_plugin_acl */
$acl = plugin_load('admin', 'acl');
if(!$acl->isAccessibleByCurrentUser()) {
echo 'for admins only';
return;
}
......@@ -54,9 +57,6 @@ class action_plugin_acl extends DokuWiki_Action_Plugin {
}
$ID = getID();
/** @var $acl admin_plugin_acl */
$acl = plugin_load('admin', 'acl');
$acl->handle();
$ajax = $INPUT->str('ajax');
......
......@@ -72,6 +72,31 @@ 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 = [];
$data['instance'] = $this;
$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
*
......
......@@ -36,7 +36,9 @@ class action_plugin_extension extends DokuWiki_Action_Plugin {
$event->preventDefault();
$event->stopPropagation();
if(empty($_SERVER['REMOTE_USER']) || !auth_isadmin($_SERVER['REMOTE_USER'], $USERINFO['grps'])) {
/** @var admin_plugin_extension $admin */
$admin = plugin_load('admin', 'extension');
if(!$admin->isAccessibleByCurrentUser()) {
http_status(403);
echo 'Forbidden';
exit;
......
......@@ -41,7 +41,9 @@ class action_plugin_styling extends DokuWiki_Action_Plugin {
global $ACT;
global $INPUT;
if($ACT != 'admin' || $INPUT->str('page') != 'styling') return;
if(!auth_isadmin()) return;
/** @var admin_plugin_styling $admin */
$admin = plugin_load('admin', 'styling');
if(!$admin->isAccessibleByCurrentUser()) return;
// set preview
$len = count($event->data['link']);
......
......@@ -8,7 +8,7 @@ header('X-UA-Compatible: IE=edge,chrome=1');
/** @var admin_plugin_styling $plugin */
$plugin = plugin_load('admin', 'styling');
if(!auth_isadmin()) die('only admins allowed');
if(!$plugin->isAccessibleByCurrentUser()) die('only admins allowed');
$plugin->ispopup = true;
// handle posts
......
......@@ -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
*
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment